My intention is to develop a pie chart from a csv file. The perspectives are the headers. My code takes the csv file. The headers are to be stored as options in the drop down menu. When a drop down menu item is selected a visualisation of the selected perspective is to be shown. A sample of the csv file is as follows:
,org_title,role_title,continent,country,updated_at_date
1,Startup,Founder,Oceania,Australia,27/06/2016
2,SME,C-Level / Owner,Oceania,Australia,27/06/2016
3,School / University,Student,Oceania,Australia,27/06/2016
4,School / University,Student,South America,Brazil,27/06/2016
5,Government Department,other,Asia,Philippines,28/06/2016
6,other,other,Asia,Singapore,27/06/2016
7,Non Profit Organisation,other,Asia,Malaysia,27/06/2016
8,Non Profit Organisation,other,Asia,Mongolia,27/06/2016
My code is as follows:
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<input type="file" id="file" name="file"/>
<div id='container'/>
<select id='options'/>
<script>
$('#options').change(function () {
var v =this.value;
var res=[];
Object.keys(CSVARRAY[v]).forEach(function(k) {
res.push({'name':k,'y':CSVARRAY[v][k]});
});
console.log(JSON.stringify(res));
Highcharts.chart('container', {
chart: {
plotBackgroundColor: null,
plotBorderWidth: null,
plotShadow: false,
type: 'pie'
},
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
dataLabels: {
enabled: true,
format: '<b>{point.name}</b>: {point.percentage:.1f} %',
style: {
color: (Highcharts.theme && Highcharts.theme.contrastTextColor) || 'black'
}
}
}
},
series: [{
data: res
}]
});
});
//Selecting file and converting it to tabular form
var file = document.getElementById('file');
var CSVARRAY;
file.addEventListener('change', function() {
var reader = new FileReader();
var f = file.files[0];
reader.onload = function(e) {
CSVARRAY = parseResult(e.target.result); //this is where the csv array will be
};
reader.readAsText(f);
});
function parseResult(result) {
var res = result.split("\n");
var headers = res[0].split(',');
headers.shift();
res.shift();
var d = {};
var prev={};
headers.forEach(function(h) {
d[h] = {};
prev[h] = [];
});
res.forEach(function(row) {
var i=0;
var r = row.split(",");
r.shift();
r.forEach(function(cell) {
if (cell !== prev[headers[i]])
{
d[headers[i]][cell]=[];
d[headers[i]][cell]=[];
d[headers[i]][cell]=1;
}
else
{
d[headers[i]][cell]+=1;
}
prev[headers[i]]=cell;
i += 1;
});
});
//return resultArray;
var options = $("#options");
headers.forEach(function(h) {
options.append($("<option />").val(h).text(h));
});
return d;
}
</script>
</body>
</html>
It is almost correct. However, the drop down menu dissappears after I click on any item.
The reason is actually because your div with the id "container" is not closed correctly. This means that the browser is interpreting that the select tag is actually within the container div. The same container div which is being overwritten with your chart.
If you change the following from:
<div id='container'/>
// javascript references are here
<select id='options'/>
To:
<input type="file" id="file" name="file"/>
<div id='container'>
</div>
// javascript references are here
<select id='options'/>
On an aside, your JavaScript code is very hard to follow, mostly because there is a lot of strange indenting going on. Take a look at airBnB's JavaScript style guide for information on making your code easier for others to read.
Related
I'm playing around with node graphs using Sigmajs.
Recently I tried to implement moving nodes in the graph but in the web-debugger I get an error saying "TypeError: Right hand side of instanceof is not an object" referring to the plugin sigma.plugins.dragNodes.js.
I followed the example given by the good folks at Sigmajs.org called "drag-nodes.html" and I believe I've included the packages correctly, yet I get the error.
The web-debugger refers to two places in the sigma.plugins.dragNodes.js file, these being: (At line 64)
if (renderer instanceof sigma.renderers.svg) {
_mouse = renderer.container.firstChild;
}
and (at line 304)
if (!_instance[s.id]) {
_instance[s.id] = new DragNodes(s, renderer);
}
This is my code:
<script src='{{ url_for("static", filename="js/sigma.min.js") }}'></script>
<script src='{{ url_for("static", filename="js/sigma.parsers.json.min.js") }}'></script>
<script src='{{ url_for("static", filename="js/sigma.plugins.dragNodes.js") }}'></script>
<div>
<button onclick="AddNode()"> Click</button>
</div>
<div>
<!-- testing function -->
<button onclick="update()"> update</button>
</div>
<div> <!-- ONSUBMIT send: (fromNode, toNode) Not complete -->
<input type="text" maxlength="2" name="value" id="value" />
<input type="button" value="submit" onclick="AddEdge()" />
</div>
<div id="container">
<style>
#graph-container {
max-width: 800px;
height: 500px;
margin: auto;
}
</style>
<div id="graph-container"></div>
</div>
<script>
var nodeCount = 0,
edgeCount = 0,
s,
maxNodes = 20,
maxEdges = 50,
g = {
nodes: [],
edges: []
}
s = new sigma({
graph: g,
container: 'graph-container',
renderers:[ {
container: document.getElementById('graph-container'),
type: 'canvas'
}],
settings: {
}
});
// Testing function only
function PrintNodes(){
var edgeval = document.getElementById('value').value[0];
alert(edgeval);
}
function AddNode() {
s.graph.addNode({
id: 'n' + nodeCount,
label: 'Node ' + nodeCount,
x: nodeCount,
y: 5,
size: 8,
color: '#000000'
});
nodeCount =nodeCount +1;
s.refresh();
}
function AddEdge() {
var fromNode = document.getElementById('value').value[0];
var toNode = document.getElementById('value').value[1];
s.graph.addEdge({
id: 'e' + edgeCount,
source: 'n' + fromNode,
target: 'n' + toNode,
size: 8,
color: '#FF0000'
});
edgeCount = edgeCount + 1;
s.refresh();
}
// Testing function only
function update(){
s.graph.nodes().forEach(function(n){
n.size = 34,
n.color = '#000'
});
s.refresh();
}
// Initialize the dragNodes plugin:
var dragListener = sigma.plugins.dragNodes(s, s.renderers[0]);
dragListener.bind('startdrag', function(event) {
console.log(event);
});
dragListener.bind('drag', function(event) {
console.log(event);
});
dragListener.bind('drop', function(event) {
console.log(event);
});
dragListener.bind('dragend', function(event) {
console.log(event);
});
</script>
Why is this giving me that error? And any help to fix it is appreciated.
Thanks.
You have this code:
if (renderer instanceof sigma.renderers.svg) {
_mouse = renderer.container.firstChild;
}
You should check sigma.renderers.svg ( console.log(sigma.renderers.svg) ) or something else, because as error insists it isn't an object. It could be undefined, null etc...
Check where you are defining sigma.renderers.svg.
As usual, the solution was more simple than I thought but at least I learned a lot whilst trying to solve it. The object was correct all the time but I had forgotten to implement necessary renderers. Even though I don't use the SVG type I had to have ../src/renderers/sigma.renderers.svg.js, included as a script-package.
Thanks for the help!
I am currently querying a table from Google sheet which has a Date column. The date column in my dashboard has time info included, which I want to remove; also the starting date in my code is 12/18/2018 but my dashboard starts with one day earlier. 12/17/2018 16.00
My Data source looks like this:
My Dashboard looks like this:
My Code Looks like this.
Code.gs:
function doGet(e) {
return HtmlService
.createTemplateFromFile("Line Chart multiple Table")
.evaluate()
.setTitle("Google Spreadsheet Chart")
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
function getSpreadsheetData() {
var ssID = "1jxWPxxmLHP-eUcVyKAdf5pSMW6_KtBtxZO7s15eAUag";
var sheet = SpreadsheetApp.openById(ssID).getSheets()[1];
var data1 = sheet.getRange('A2:F9').getValues();
var data2 = sheet.getRange('A2:F9').getValues();
var rows = {data1: data1, data2: data2};
var r = JSON.stringify(rows);
return r;
}
Line Chart multiple Table.html
<!DOCTYPE html>
<html>
<head>
<script src="https://www.gstatic.com/charts/loader.js"></script>
</head>
<body>
<div id="linechartweekly"></div>
<div id="table2"></div>
<div class = "block" id="message" style="color:red;">
<script>
google.charts.load('current', {'packages':['table']});
google.charts.load('current', {packages: ['corechart', 'line']});
google.charts.setOnLoadCallback(getSpreadsheetData);
function display_msg(msg) {
console.log("display_msg():"+msg);
document.getElementById("message").style.display = "block"; // Style of display
var div = document.getElementById('message');
div.innerHTML = msg;
}
function getSpreadsheetData() {
google.script.run.withSuccessHandler(drawChart).getSpreadsheetData();
}
function drawChart(r) {
// Parse back to an object
var rows = JSON.parse(r);
console.log("rows:"+rows);
var data1 = google.visualization.arrayToDataTable(rows.data1, false);
var data2 = google.visualization.arrayToDataTable(rows.data2, false);
var options1 = {
title: 'SPC Chart weekly',
legend: ['USL', 'UCL', 'Data', 'LCL', 'LSL'],
colors: ['Red', 'Orange', 'blue', 'Orange', 'Red'],
pointSize: 4,
};
var chart1 = new google.visualization.LineChart(document.getElementById("linechartweekly"));
chart1.draw(data1, options1);
var table2 = new google.visualization.Table(document.getElementById("table2"));
table2.draw(data2, {showRowNumber: false, width: '50%', height: '100%'});
}
function failure_callback(error) {
display_msg("ERROR: " + error.message);
console.log('failure_callback() entered. WTF'+error.message);
}
</script>
</body>
</html>
May I know how to change my date to the right format removing the time and also ensure the correct starting date
Any help is much appreciated.
The actual problem has me stumped, but I do have a workaround; see modified code example below, with some additional error handling.
I've extensively tested the server-side function, and from its perspective there is absolutely no difference in the row object that is created whether the range starts at column 'I' or 'J'.
The problem manifests itself in the client-side success handler which, when column 'I' is included is essentially passed a null argument, note the whole object, not just the row.data1 part, is null.
The row object that is being passed from the server to the client is quite complicated (an object with 3 key value pairs, where the values are fairly long arrays). I can't see anything in the GAS documentation that disallows this: Legal parameters and return values are JavaScript primitives like a Number, Boolean, String, or null, as well as JavaScript objects and arrays that are composed of primitives, objects and arrays. So this could be a bug?
The workaround, illustrated in the code examples below is to stringify the object in the server-side function, and then parsing it back to an object in the client.
HTML
<!DOCTYPE html>
<html>
<head>
<script src="https://www.gstatic.com/charts/loader.js"></script>
</head>
<body>
<div id="table1"></div>
<div id="linechartweekly"></div>
<div id="table2"></div>
<div class = "block" id="message" style="color:red;">
<script>
google.charts.load('current', {'packages':['table']});
google.charts.load('current', {packages: ['corechart', 'line']});
google.charts.setOnLoadCallback(getSpreadsheetData);
function display_msg(msg) {
console.log("display_msg():"+msg);
document.getElementById("message").style.display = "block"; // Style of display
var div = document.getElementById('message');
div.innerHTML = msg;
}
function getSpreadsheetData() {
google.script.run.withFailureHandler(failure_callback).withSuccessHandler(drawChart).getSpreadsheetData();
}
function drawChart(r) {
// Parse back to an object
var rows = JSON.parse(r);
console.log("rows:"+rows);
var data1 = google.visualization.arrayToDataTable(rows.data1, false);
var data2 = google.visualization.arrayToDataTable(rows.data2, false);
var data3 = google.visualization.arrayToDataTable(rows.data3, false);
var options1 = {
title: 'SPC Chart weekly',
legend: ['USL', 'UCL', 'Data', 'LCL', 'LSL'],
colors: ['Red', 'Orange', 'blue', 'Orange', 'Red'],
pointSize: 4,
};
var table1 = new google.visualization.Table(document.getElementById("table1"));
table1.draw(data1, {showRowNumber: false, width: '50%', height: '100%'});
var chart1 = new google.visualization.LineChart(document.getElementById("linechartweekly"));
chart1.draw(data2, options1);
var table2 = new google.visualization.Table(document.getElementById("table2"));
table2.draw(data3, {showRowNumber: false, width: '50%', height: '100%'});
}
function failure_callback(error) {
display_msg("ERROR: " + error.message);
console.log('failure_callback() entered. WTF'+error.message);
}
</script>
</body>
</html>
Code
function doGet(e) {
return HtmlService
.createTemplateFromFile("Line Chart multiple Table")
.evaluate()
.setTitle("Google Spreadsheet Chart")
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
function getSpreadsheetData() {
var ssID = "1jxWPxxmLHP-eUcVyKAdf5pSMW6_KtBtxZO7s15eAUag";
var sheet = SpreadsheetApp.openById(ssID).getSheets()[0];
//var firstrow = 6; //11th row
//var range = sheet.getRange(firstrow, 1, sheet.getLastRow() - firstrow + 1, 6);
//var data1 = range.getValues();
var d1 = sheet.getRange('A1:B5').getValues();
var d2 = sheet.getRange('I2:O4').getValues();
var d3 = sheet.getRange('I2:O4').getValues();
var rows = {data1: d1, data2: d2, data3: d3};
// Stringify the object
var r = JSON.stringify(rows);
return r;
}
I'm trying to use Plotly.js to create some graphs of historical cryptocurrency prices, and am running into the problem that my data is not showing up on the graph created. I'm building my code from the sample code at https://plot.ly/javascript/ajax-call/ but tooling it for my own data source and a local copy of plotly-latest.min.js. I'm using a small subset of my data and only one trace to get the code functional, and I've placed console.log statements after the processing of the data and the creation of the trace that show me my data is properly formatted judging by the sample code and its dataset. I've set the range of the chart to the range of my data, but I still see nothing on the chart when its created despite modeling it after working sample code. Where am I going wrong?
My code:
<!DOCTYPE html>
<html>
<head>
<script src="plotly-latest.min.js"></script>
</head>
<body>
<div id="myDiv" style="width: 480px; height: 400px;"></div>
<script>
function makePlot() {
Plotly.d3.csv("bitcoin.csv", function(data){ processData(data) } );
}
function processData(allRows) {
var Date = [], Open = [], High = [], Low = [], Volume = [], MarketCap = [];
for (var i=0; i<allRows.length; i++) {
row = allRows[i];
tmpDate = row['Date;Open;High;Low;Close;Volume;MarketCap'].split(';')[0]
Date.unshift( tmpDate.split('/')[2] + '-' + tmpDate.split('/')[1] + '-' + tmpDate.split('/')[0]);
Open.unshift( row['Date;Open;High;Low;Close;Volume;MarketCap'].split(';')[1]);
High.unshift( row['Date;Open;High;Low;Close;Volume;MarketCap'].split(';')[2]);
Low.unshift( row['Date;Open;High;Low;Close;Volume;MarketCap'].split(';')[3]);
Volume.unshift( row['Date;Open;High;Low;Close;Volume;MarketCap'].split(';')[4]);
MarketCap.unshift( row['Date;Open;High;Low;Close;Volume;MarketCap'].split(';')[5]);
};
makePlotly(Date, Open);
}
function makePlotly(Date, Open) {
var plotDiv = document.getElementById("plot");
var traces = [{
Date: Date,
Open: Open}
];
console.log(traces);
var layout = {
xaxis: {
type: 'date',
title: 'Date',
range: ['2017-11-12', '2017-11-22']
},
yaxis: {
title: 'Price (USD)',
range: [4000, 10000]
},
title: 'Cryptocurrency Historical Prices'
}
Plotly.newPlot('myDiv', traces, layout);
}
makePlot();
</script>
</body>
</html>
bitcoin.csv (1 column)
Date;Open;High;Low;Close;Volume;MarketCap
22/11/2017;8077.95;8302.26;8075.47;8253.55;3633530000;134851000000
21/11/2017;8205.74;8348.66;7762.71;8071.26;4277610000;136967000000
20/11/2017;8039.07;8336.86;7949.36;8200.64;3488450000;134167000000
19/11/2017;7766.03;8101.91;7694.10;8036.49;3149320000;129595000000
18/11/2017;7697.21;7884.99;7463.44;7790.15;3667190000;128425000000
17/11/2017;7853.57;8004.59;7561.09;7708.99;4651670000;131026000000
16/11/2017;7323.24;7967.38;7176.58;7871.69;5123810000;122164000000
15/11/2017;6634.76;7342.25;6634.76;7315.54;4200880000;110667000000
14/11/2017;6561.48;6764.98;6461.75;6635.75;3197110000;109434000000
13/11/2017;5938.25;6811.19;5844.29;6559.49;6263250000;99029000000
12/11/2017;6295.45;6625.05;5519.01;5950.07;8957350000;104980000000
I guess it should be your variable traces causes the problem
var traces = [{
x: Date, //not Date: Date
y: Open //not Open: Open
}];
Here is my use case. I am using Flume and Spark Streaming to count the number of events generated from the server. So in the output of the spark i get timestamp and number of events. After every 10 second the old value is erased and new value is written in a file in HDFS.
I have created Spring framework which will pull the data from HDFS convert it to json and push it to Highcharts. So I am trying to generate a live spline chart which will show timestamp in the x-axis and number of count in the y-axis and update it as it gets new data from the spark output after every 10 seconds. But the x-axis is not shifting and I can see 10 zero values in y-axis. So I am unable to get the updated y value. I am sure I am missing something in the java script. Because from the console of the spring i can see the events are updating after every 10 seconds. But its not reflecting in the chart.
I am stuck here for past two weeks and desperately need help. Any help will be much appreciated. Thanks.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script type="text/javascript" src="http://code.highcharts.com/highcharts.js" ></script>
<script type="text/javascript" src="http://code.highcharts.com/maps/modules/exporting.js" ></script>
<script type="text/javascript" src="http://code.highcharts.com/modules/drilldown.js"></script>
<script src="http://code.highcharts.com/modules/exporting.js"></script>
<script type="text/javascript" src="js/app/appStart.js" ></script>
<link type="text/css" href="css/app.css" rel="stylesheet">
<script src="http://code.highcharts.com/stock/modules/exporting.js"></script>
</head>
<body>
<div class="chart" id="statusChart" >
</div>
</body>
$(function() {
var url = 'statistics';
$.ajax(url).done(function(data) {
loadStatusChart(data);
});
});
function updateStatusSeries(series){
var url = 'statistics';
$.ajax(url).done(function(data) {
var statusCode = data.statusCode[0];
series.addPoint([statusCode.label, statusCode.value], true, true);
});
}
function loadStatusChart(statistics) {
var StatusCode = statistics.statusCode;
var StatusSeries = [];
$.each(StatusCode, function(index, item) {
var timeInSeconds = item.label/1000;
for(var i = 10; i >= 1; i--){
StatusSeries.push({
x : (timeInSeconds - (i*10))*1000,
y : 0
});
}
StatusSeries.push({
x : item.label,
y : item.value
});
})
var x = StatusCode.length;
$("#statusChart").highcharts({
chart : {
type : 'spline',
//animation : Highcharts.svg,
marginRight : 10,
events : {
load : function(){
//set up updating of the chart each second
var series = this.series[0];
setInterval(function (){
updateStatusSeries(series);
}, 10000);
}
}
},
title: {
text: 'Live Data'
},
xAxis: {
type: 'datetime'
},
yAxis: {
title: {
text: 'Number of Counts'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
},
tooltip: {
formatter: function () {
return '<b>' + this.series.name + '</b><br/>' +
Highcharts.dateFormat('yyyy/mm/dd hh:mm:ss', this.x) + '<br/>' +
Highcharts.numberFormat(this.y, 2);
}
},
legend: {
enabled: false
},
exporting: {
enabled: false
},
series: [{ data: StatusSeries }]
});
};
First, you're getting leading zeroes in the chart because of this code:
for(var i = 10; i >= 1; i--){ // <----- 10
StatusSeries.push({
x : (timeInSeconds - (i*10))*1000,
y : 0 // <----- zero values
});
}
Second, your chart isn't advancing because in this part
events : {
load : function(){
//set up updating of the chart each second
var series = this.series[0];
setInterval(function (){
updateStatusSeries(series); // <----- Not updating series
}, 10000);
}
}
updateStatusSeries(series) actually doesn't update series, thus the chart doesn't get new data and simply stays on the same spot.
To fix that you can either
create a global chart object and use it to access its series, like described here: http://www.highcharts.com/docs/working-with-data/live-data
modify your updateStatusSeries() so that it uses a callback passed to it, like shown here: http://www.in-example.com/?p=316
Also, date formatting (in tooltip.formatter) should be done like so:
Highcharts.dateFormat('%Y-%m-%d %H:%M:%S', this.x)
I am trying to parse some XML data into JSON using Javascript/Jquery for use in a Highcharts project. Unfortunately, I can't figure out what is wrong with my code as it will not even read the XML. So far I have:
xml:
<Row>
<Category>data</Category>
<actual>data</actual>
</row>
....
HTML:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>Document</title>
</head>
<body>
<h1>Hello</h1>
<div id="container" style="height: 400px; width: 500px"></div>
<script type = "text/javascript" src = "jquery-1.11.1.min.js"></script>
<script src="http://code.highcharts.com/highcharts.js"></script>
<script type = "text/javascript" src = "test.js"></script>
</body>
</html>
Javascript:
$(document).ready(function(){
var globalData = new Array();
// $("h1").click(function(){
// Load the data from the XML file
$.get('C:\\Users\\xxxxxx\\Desktop\\xmloutput.xml', function(xml) {
alert("it works");
// Split the lines
var $xml = $(xml);
// push series
$xml.find('Row').each(function(i, row) {
var seriesOptions = {
Category: $(series).find('Category').text(),
Actual: $(series).find('Actual').text(),
};
// add it to the options
globalData.push(seriesOptions);
});
});
// });
$(function() {
var chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'pie'
},
plotOptions: {
pie: {
borderColor: '#000000',
innerSize: '60%'
}
},
series: [{
data: globalData
}]
},
// using
function(chart) { // on complete
var xpos = '50%';
var ypos = '53%';
var circleradius = 102;
// Render the circle
chart.renderer.circle(xpos, ypos, circleradius).attr({
fill: '#ddd',
}).add();
// Render the text
chart.renderer.text('THIS TEXT <span style="color: red">should be in the center of the donut</span>', 155, 215).css({
width: circleradius*2,
color: '#4572A7',
fontSize: '16px',
textAlign: 'center'
}).attr({
// why doesn't zIndex get the text in front of the chart?
zIndex: 999
}).add();
});
});
});
I believe my actual problem may be that my xml-parsing syntax is incorrect but running this on the development console in Firefox reveals no errors. Hopefully the experts here can spot the issue(s)
Thanks for your time.
One imediate problem that I can see is using local path
$.get('C:\\Users\\xxxxxx\\Desktop\\xmloutput.xml',
$.get first parameter is url that is location on network it could be something like $.get('http://localhost/xmls/xmloutput.xml,...