Creating a live web app - javascript

I have to make an application which dynamically updates data using Highcharts. That wasn't a big problem because they have a good tutorial. And the example works fine.
When I wan't to share this application across multiple device (using xampp), I have some problems. When I open the link to my webapp:
http://IP-adress/ENRGYMONITOR/index.html
The graph shows up, but the no data is displayed or updated. Here is the javascript I wrote:
var chart; // global
/**
* Request data from the server, add it to the graph and set a timeout to request again
*/
function requestData() {
$.ajax({
url: 'http://localhost/live-server-data.php',
success: function(point) {
var series = chart.series[0],
shift = series.data.length > 20; // shift if the series is longer than 20
// add the point
chart.series[0].addPoint(eval(point), true, shift);
// call it again after one second
setTimeout(requestData, 5000);
},
cache: false
});
}
$(document).ready(function() {
chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
defaultSeriesType: 'spline',
events: {
load: requestData
}
},
title: {
text: 'Live random data'
},
xAxis: {
type: 'datetime',
tickPixelInterval: 150,
maxZoom: 20 * 1000
},
yAxis: {
minPadding: 0.2,
maxPadding: 0.2,
title: {
text: 'Value',
margin: 80
}
},
series: [{
name: 'Random data',
data: []
}]
});
});
Can anyone let me know what the issue is?

Your $.ajax call is failing:
url: 'http://localhost/live-server-data.php'
"localhost" here would be the computer running the client (the web browser), not the server sending the data.
You should try to avoid an absolute URL. Modify it to just:
url: 'live-server-data.php'
assuming (this is important) that live-server-data.php is in the same directory as index.html

Related

HighChart- Wrong Datetime in the X-Axis for Live Chart

I am using HighChart for Live Chart (Data changes each 10 seconds).In each Second , an ajax call will take place and get the data from the Controller as json. In the example , I can get the data in each 10 seconds but the time shows in the X-axis is wrong. Instead of showing the correct time , it showing the time more than 4 from the current time.
This is the HTML+js file
<!DOCTYPE html>
<html>
<head>
<title>Index</title>
#*//Add JQUERY*#
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.1.1.min.js"></script>
#*//Add HighChart.js*#
<script src="http://code.highcharts.com/highcharts.js"></script>
<script>
var chart;
$(document).ready(function () {
chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
defaultSeriesType: 'spline',
events: {
load: getData
}
},
title: {
text: 'Live Bin Usage'
},
xAxis: {
type:'datetime',
tickPixelInterval: 150
},
yAxis: {
minPadding: 0.2,
maxPadding: 0.2,
title: {
text: 'Value',
margin: 80
}
},
series: [{
name: 'Time'
}]
});
});
/**
* Request data from the server, add it to the graph and set a timeout to request again
*/
function getData() {
$.ajax({
url: '/AswinDemo/FetchData',
dataType: 'json',
success: function (data) {
var series = chart.series[0],
shift = series.data.length > 20; // shift if the series is
// longer than 20
var x = (new Date()).getTime(), // current time
y = Math.random();
// add the point
chart.series[0].addPoint([x ,data.BinUsage], true, shift);
// call it again after one second
setTimeout(getData, 1000);
},
cache: false
});
}
</script>
</head>
<body>
<div id="container" style="width:100%; height:400px;"></div>
</body>
</html>
The server or Controller
public ActionResult FetchData()
{
Random rn = new Random();
return Json(new { BinUsage = rn.Next(), Time = DateTime.Now.TimeOfDay.ToString()} ,JsonRequestBehavior.AllowGet );
}
Below is the Screen Shot of the Chart : -
You can see the time in my chart is deffer from the time of the PC (in the task bar)
I have solved the problem by setting global.useUTC to false. Thanks.

Golang Highcharts dynamic data

I am currently learning golang and a bit of webstuff on the way. So excuse my maybe not so smart question
My problem is that I want to provide a Highchart with dynamic Data. I looked up the documentation and the example but cannot get it to work.
The Highchart example:
<script type="text/javascript" src="http://code.jquery.com/jquery-1.10.1.js"></script>
<script type="text/javascript" src="http://code.highcharts.com/highcharts.js"></script>
<!-- 2. Add the JavaScript to initialize the chart on document ready -->
<script>
var chart; // global
/**
* Request data from the server, add it to the graph and set a timeout to request again
*/
function requestData() {
$.ajax({
url: 'http://localhost:3000/',
success: function(point) {
var series = chart.series[0],
shift = series.data.length > 20; // shift if the series is longer than 20
// add the point
chart.series[0].addPoint(eval(point), true, shift);
// call it again after one second
setTimeout(requestData, 1000);
},
cache: false
});
}
$(document).ready(function() {
chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
defaultSeriesType: 'spline',
events: {
load: requestData
}
},
title: {
text: 'Live random data'
},
xAxis: {
type: 'datetime',
tickPixelInterval: 150,
maxZoom: 20 * 1000
},
yAxis: {
minPadding: 0.2,
maxPadding: 0.2,
title: {
text: 'Value',
margin: 80
}
},
series: [{
name: 'Random data',
data: [1]
}]
});
});
</script>
</head>
<body>
<!-- 3. Add the container -->
<div id="container" style="width: 800px; height: 400px; margin: 0 auto"></div>
My Server should Provide a json encoding string as requested.
func main(){
http.HandleFunc("/",foo)
http.ListenAndServe(":3000", nil)
}
func foo(w http.ResponseWriter, r *http.Request) {
numbers := []int{14,5}
js, err := json.Marshal(numbers)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
fmt.Println("Received Request")
w.Header().Set("Content-Type", "text/json")
w.Write(js)
}
I can see that the highchart makes a request. My guess it that the ajax call does not understand my json?
Thanks for any help in advance :)
Edit: Do I habe to do a success message as a return too?
The error (thx to #jmaloney 's hint)
{"readyState":4,"status":200,"statusText":"success"}
ajax.html:28 parsererror: Error: jQuery110109016359453089535_1446814074235 was not called
A simple
w.Header().Set("Access-Control-Allow-Origin", "*")
on my go-Server solves it :)

HighCharts with Dynamic Data not working

I have a ASP.NET MVC project with SignalR.
I have a page with a HighChart and the script looks like this:
$(function () {
window.Highcharts.setOptions({
global: {
useUTC: false
}
});
var chart;
$(document).ready(function () {
chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'line',
marginRight: 10
},
title: {
text: 'GMAS Queues'
},
xAxis: {
type: 'datetime',
tickInterval: 500,
labels: {
enabled: false
}
},
yAxis: {
title: {
text: 'Queue Count'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
},
legend: {
enabled: false
},
exporting: {
enabled: false
},
series: [{
name: 'Processing Queues'
}]
});
});
$.connection.hub.logging = true;
// Reference the auto-generated proxy for the hub.
var chartData = $.connection.processingQueuesHub;
// Create a function that the hub can call back to display messages.
chartData.client.updateQueueCounts = function (data) {
//$.each(data, function(i, item) {
// // Add the message to the page.
// $('#chartDataLog').append('<li><strong>' + htmlEncode(item.QueueName)
// + '</strong>: ' + htmlEncode(item.Length) + '</li>');
//});
// set up the updating of the chart.
var series = chart.series[0];
$.each(data, function (i, item) {
if (item.QueueName == "Queue A") {
var x = Date.parse(item.Date),
y = item.Length;
series.addPoint([x, y], true, false);
}
});
};
However, I see the graph but not the points.
The strange part is the series data points are there:
Anyone know why HighCharts is not rendering the points?
Thanks, Bill N
I have to thank my good friend and co developer for figuring this out. He is a smarter and braver man than me. :) He went to the highcharts source and found that the highcharts breaks if you add to the graph series before the initial animation is completed. The animation is why the clip-rect is zero-width (it animates from zero to full width over 1s when you first create the chart). You end up adding a point to the series before this animation even really starts. This kills the animation but it doesn’t fix the width of the clip-rect. The fix is to add animation is false for the series.
series: [{ name: 'Processing Queues', data: [], animation: false }]
It looks like you are not defining what your chart.series is until it is created. The line in your ajax is as follows and its not waiting for DOM ready:
var series = chart.series[0];
But you do not define chart until $(document).ready(function () {.... Try keeping your chart object in scope of your ajax.

Highcharts multiple charts, each with live data

I have the following files:
rsrp.txt, sinr.txt, rssi.txt
each of them containg information like this:
[1433289760000,-83.5]
I want to use multiple charts on the same page.
I tried to use the sample script from the Highcharts page:
var chart; // global
/**
* Request data from the server, add it to the graph and set a timeout to request again
*/
function requestData() {
$.ajax({
url: 'rssi.txt',
success: function(point) {
var series = chart.series[0],
shift = series.data.length > 30; // shift if the series is longer than 20
// add the point
chart.series[0].addPoint(eval(point), true, shift);
// call it again after one second
setTimeout(requestData, 1700);
},
cache: false
});
}
$(document).ready(function() {
chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
defaultSeriesType: 'spline',
events: {
load: requestData
}
},
title: {
text: 'RSSI'
},
xAxis: {
type: 'datetime',
tickPixelInterval: 150,
maxZoom: 20 * 1000
},
yAxis: {
minPadding: 2.5,
maxPadding: 2.5,
title: {
text: 'dBm',
margin: 80
}
},
series: [{
name: 'RSSI',
data: []
}]
});
});
Copy pasting the script outside the and changing the URL does not work. (only one chart is getting updates)
If I create a second requestData()-function and copy the $(document).ready part does not work either.
Is this possible in Highcharts?
It would be not a problem to combine the input files into a single file, if that would help.
Edit:
I tried to solve it using the answers here:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Signal</title>
<!-- 1. Add these JavaScript inclusions in the head of your page -->
<script type="text/javascript" src="jquery-1.10.1.js"></script>
<script type="text/javascript" src="highcharts.js"></script>
<!-- 2. Add the JavaScript to initialize the chart on document ready -->
<script>
var chart; // global
var chartRsrp;
/**
* Request data from the server, add it to the graph and set a timeout to request again
*/
function requestData() {
$.ajax({
url: 'rssi.txt',
success: function(point) {
var series = chart.series[0],
shift = series.data.length > 30; // shift if the series is longer than 20
// add the point
chart.series[0].addPoint(eval(point), true, shift);
// call it again after one second
setTimeout(requestData, 1700);
},
cache: false
});
}
function requestData2() {
$.ajax({
url: 'rsrp.txt',
success: function(point) {
var series = chartRsrp.series[0],
shift = series.data.length > 30; // shift if the series is longer than 20
// add the point
chartRsrp.series[0].addPoint(eval(point), true, shift);
// call it again after one second
setTimeout(requestData, 1700);
},
cache: false
});
}
$(document).ready(function() {
chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
defaultSeriesType: 'spline',
events: {
load: requestData
}
},
title: {
text: 'RSSI'
},
xAxis: {
type: 'datetime',
tickPixelInterval: 150,
maxZoom: 20 * 1000
},
yAxis: {
minPadding: 2.5,
maxPadding: 2.5,
title: {
text: 'dBm',
margin: 80
}
},
series: [{
name: 'RSSI',
data: []
}]
});
chartRsrp = new Highcharts.Chart({
chart: {
renderTo: 'container2',
defaultSeriesType: 'spline',
events: {
load: requestData2
}
},
title: {
text: 'RSRP'
},
xAxis: {
type: 'datetime',
tickPixelInterval: 150,
maxZoom: 20 * 1000
},
yAxis: {
minPadding: 2.5,
maxPadding: 2.5,
title: {
text: 'dBm',
margin: 80
}
},
series: [{
name: 'RSRP',
data: []
}]
});
});
</script>
</head>
<body>
<!-- 3. Add the container -->
<div id="container" style="width: 800px; height: 400px; margin: 0 auto"></div>
<div id="container2" style="width: 800px; height: 400px; margin: 0 auto"></div>
Edit 2: solved it that way:
requestData2();
requestData3();
requestData4();
setTimeout(requestData, 1300);
in the first requestData()
In Highcharts-land, each chart needs to be its own object. It's certainly possible to have multiple charts on the same page, but you'd have to make sure that:
Each chart is instantiated separately (in this case, if you're just copying/pasting the $(document).ready part, you're probably stepping on your chart variable. So, instead of a single chart variable you could set these up separately (e.g. chartRsrp = new Highcharts.Chart(...)) and be sure to reference them differently in your requestData calls.
Each chart is rendered to a different DOM element. So, you might render to "container-rsrp", "container-sinr", "container-rssi" etc.
Hopefully this helps!
First of all, each chart have to be instantiated separately, so in your HTML you must have a div with an ID for each chart where the chart will be rendered, for example:
<div id='chartrsrp' class="large-12 columns"></div>
<div id='chartsinr' class="large-12 columns"></div>
<div id='chartrssi' class="large-12 columns"></div>
Next, to render your chart from Js you have to get the div object and instantiate each chart like:
var chartrsrp = $("#chartrsrp");
chartrsrp.highcharts({
title: {
...
},
chart: {
...
});
Hopefully this helps!

How to save an image of the chart on the server with highcharts?

With highcharts, you have a built-in button to download the current chart (example: http://www.highcharts.com/demo/, this button: ). You can save it as PNG, JPEG, PDF or SVG.
What I'd like to do is to create a link that saves the image on the server, instead of downloading it. How could I do that ?
I suppose that I have to modify the exportChart function in the exporting.src.js file. It looks like this (but I don't know javascript enough to do that) :
exportChart: function (options, chartOptions) {
var form,
chart = this,
svg = chart.getSVG(chartOptions);
// merge the options
options = merge(chart.options.exporting, options);
// create the form
form = createElement('form', {
method: 'post',
action: options.url
}, {
display: NONE
}, doc.body);
// add the values
each(['filename', 'type', 'width', 'svg'], function (name) {
createElement('input', {
type: HIDDEN,
name: name,
value: {
filename: options.filename || 'chart',
type: options.type,
width: options.width,
svg: svg
}[name]
}, null, form);
});
// submit
form.submit();
// clean up
discardElement(form);
},
It could be done really easy with PhantomJS. You can render Highchart chart and save it to SVG, PNG, JPEG or PDF. The example below renders a demo Highcharts diagram to SVG and PDF at the same time:
var system = require('system');
var page = require('webpage').create();
var fs = require('fs');
// load JS libraries
page.injectJs("js/jquery.min.js");
page.injectJs("js/highcharts/highcharts.js");
page.injectJs("js/highcharts/exporting.js");
// chart demo
var args = {
width: 600,
height: 500
};
var svg = page.evaluate(function(opt){
$('body').prepend('<div id="container"></div>');
var chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
width: opt.width,
height: opt.height
},
exporting: {
enabled: false
},
title: {
text: 'Combination chart'
},
xAxis: {
categories: ['Apples', 'Oranges', 'Pears', 'Bananas', 'Plums']
},
yAxis: {
title: {
text: 'Y-values'
}
},
labels: {
items: [{
html: 'Total fruit consumption',
style: {
left: '40px',
top: '8px',
color: 'black'
}
}]
},
plotOptions: {
line: {
dataLabels: {
enabled: true
},
enableMouseTracking: false
},
series: {
enableMouseTracking: false,
shadow: false,
animation: false
}
},
series: [{
type: 'column',
name: 'Andrii',
data: [3, 2, 1, 3, 4]
}, {
type: 'column',
name: 'Fabian',
data: [2, 3, 5, 7, 6]
}, {
type: 'column',
name: 'Joan',
data: [4, 3, 3, 9, 0]
}, {
type: 'spline',
name: 'Average',
data: [3, 2.67, 3, 6.33, 3.33],
marker: {
lineWidth: 2,
lineColor: 'white'
}
}, {
type: 'pie',
name: 'Total consumption',
data: [{
name: 'Andrii',
y: 13,
color: '#4572A7'
}, {
name: 'Fabian',
y: 23,
color: '#AA4643'
}, {
name: 'Joan',
y: 19,
color: '#89A54E'
}],
center: [100, 80],
size: 100,
showInLegend: false,
dataLabels: {
enabled: false
}
}]
});
return chart.getSVG();
}, args);
// Saving SVG to a file
fs.write("demo.svg", svg);
// Saving diagram as PDF
page.render('demo.pdf');
phantom.exit();
If you save the code as demo.js, then just run bin/phantomjs demo.js to generate demo.svg and demo.pdf
I just implement this using Nobita's method. I was creating a survey that showed the user's results in a chart, uploaded the image to my server and then sent out an email with the image in it. Here's a few things to note.
I had to make a few updates to the highcharts/exporting-server/index.php file which are the following:
I changed the directory from "temp" to something else and just note that it is in 4 different locations.
I had to change shell_exec() adding "-XX:MaxHeapSize=256m" because it was giving me an error:
$output = shell_exec("java -XX:MaxHeapSize=256m -jar ". BATIK_PATH ." $typeString -d $outfile $width /mypathhere/results/$tempName.svg");
If you want it to download that image you can leave the following alone:
header("Content-Disposition: attachment; filename=$filename.$ext");
header("Content-Type: $type");
echo file_get_contents($outfile);
But, I changed this because I wanted to send back the path to the image, so I deleted the above and replace this with the image path (Note that I'm just using the temporary name.):
echo "/mypathhere/results/$tempName.$ext";
Also, this file is deleting the svg file and also the new file you made. You need to remove the code that deletes the file:
unlink($outfile);
And you can also delete the line before it if you want to keep the svg file.
Make sure to include highcharts/js/modules/exporting.js
Then, in your JS you can do something like the following:
var chart = new Highcharts.Chart();
var imageURL = '';
var svg = chart.getSVG();
var dataString = 'type=image/jpeg&filename=results&width=500&svg='+svg;
$.ajax({
type: 'POST',
data: dataString,
url: '/src/js/highcharts/exporting-server/',
async: false,
success: function(data){
imageURL = data;
}
});
The URL you are posting to is the new version of the /exporting-server/index.php. Then, you can use the imageURL however you like.
I haven't done that before, but I believe you want to play with the index.php file located in the exporting-server folder.
By default Highcharts provides (for free) a web service but you can modify that and create your own web service for exporting, or do whatever you want with the chart. Look at these instructions which can be found here Export module:
"If you want to set up this web service on your own server, the index.php file that handles the POST is supplied in the download package inside the /exporting-server directory.
Make sure that PHP and Java is installed on your server.
Upload the index.php file from the /exporting-server directory in
the download package to your server.
In your FTP program, create directory called temp in the same
directory as index.php and chmod this new directory to 777
(Linux/Unix servers only).
Download Batik from http://xmlgraphics.apache.org/batik/#download.
Find the binary distribution for your version of jre
Upload batik-rasterizer.jar and the entire lib directory to a
location on your web server. In the options in the top of the
index.php file, set the path to batik-rasterier.jar.
In your chart options, set the exporting.url option to match your
PHP file location. "
You can try this
var chart = $('#yourchart').highcharts();
svg = chart.getSVG();
var base_image = new Image();
svg = "data:image/svg+xml,"+svg;
base_image.src = svg;
$('#mock').attr('src', svg);
Take html of Mock and send to DB or save only the binary code .
Save highchart as binary image

Categories

Resources