Dynamic data from xml into Jqplot for pie chart Options - javascript

I have been trying to create a pie chart using an array that extracts
data from an xml file.
It does display the pie chart but the size of the sectors do not
correspond to the values in the array. Surprisingly, the code works if
I use a static array.
This is the xml file:
<?xml version="1.0" ?>
<A>
<a1>a1</a1>
<a2>a2</a2>
<C>20</C>
<C>30</C>
<C>50</C>
<C>60</C>
<C>70</C>
</A>
This is the javascript file(I have written only the main code):
var x=xmlDoc.getElementsByTagName("A");
var myvalues=new Array();
var staticarray = {5,5,5};
for (i=0;i<x.length;i++)
{
myvalues[i]=x[i].getElementsByTagName("C")[0].childNodes[0].nodeValue;
}
$(document).ready(function(){
$.jqplot.config.enablePlugins=true;
plot1 = $.jqplot('chart1', [myvalues]); // Doesn't work
plot2 = $.jqplot('chart2', [staticarray]); // Works

Use parseInt() to convert the node value to an integer.
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script>
<script type="text/javascript" src="js/jquery.jqplot.min.js"></script>
<script type="text/javascript" src="js/plugins/jqplot.pieRenderer.min.js"></script>
<link rel="stylesheet" type="text/css" href="css/jquery.jqplot.min.css" />
</head>
<body>
<div class="jqPlot" id="chart1" style="height: 480px; width: 90%;"></div>
<script type="text/javascript">
$.jqplot.config.enablePlugins = true;
xmlhttp=new XMLHttpRequest();
xmlhttp.open("GET","test.xml",false);
xmlhttp.send();
xmlDoc=xmlhttp.responseXML;
var x=xmlDoc.getElementsByTagName("C");
var myvalues=new Array();
for (i=0;i<x.length;i++) {
myvalues[i]=parseInt(x[i].childNodes[0].nodeValue);
}
$(document).ready(function(){
$.jqplot.config.enablePlugins=true;
plot1 = $.jqplot('chart1', [myvalues], {
seriesDefaults:{renderer:$.jqplot.PieRenderer}
});
});
</script>
</body>
</html>

Related

An array can't be used in datatables

I have tried to make a table by using datatables with an array, but somehow it doesn't show the table on my html file.
The array is defined in my gs file as you can see in the code below.
It's a simple work but I'm still not sure what it went wrong.
var ssId = 'xxxxxxxxxxxxx';
var ss = SpreadsheetApp.openById(ssId);
var indexPage_sheetName = 'xxxxxxxx';
var valuesFromIndexPage = ss.getSheetByName(indexPage_sheetName).getDataRange().getValues();//array of 850rows×15cols
valuesFromIndexPage.shift();
function getData() {
$(document).ready(function(){
$("#foo-table").DataTable({
data: valuesFromIndexPage
});
});
}
<html>
<head>
<script src="//ajax.aspnetcdn.com/ajax/jquery/jquery-1.9.1.js"></script>
<link rel="stylesheet" href="https://cdn.datatables.net/1.10.20/css/jquery.dataTables.min.css"/>
<script src="https://cdn.datatables.net/1.10.20/js/jquery.dataTables.min.js"></script>
<body>
<table id="foo-table" class="display" width="100%"></table>
</body>
</head>
</html>
#ZektorH Here's the console log of running my code.
userCodeAppPanel:9 Uncaught TypeError: Cannot read property 'slice' of null
at initializeTable (userCodeAppPanel:9)
at af (4105580746-mae_html_user_bin_i18n_mae_html_user__ja.js:67)
at 4105580746-mae_html_user_bin_i18n_mae_html_user__ja.js:10
at ng.J (4105580746-mae_html_user_bin_i18n_mae_html_user__ja.js:94)
at Hd (4105580746-mae_html_user_bin_i18n_mae_html_user__ja.js:42)
at Dd (4105580746-mae_html_user_bin_i18n_mae_html_user__ja.js:43)
at Bd.b (4105580746-mae_html_user_bin_i18n_mae_html_user__ja.js:39)
I looked again at my data and I found out the data became null on console.log(but it has data when I see it on Logger.log).
I'm posting what I did and got below.
function getData() {
Logger.log(valuesFromIndexPage); //the array is in valuesFromIndexPage
return valuesFromIndexPage;
}
function initializeTable(data) {
console.log(data); //it returns null here...
var aDataSet = data.slice(1);
The log from Logger.log
[19-10-31 09:47:00:116 JST] [[ID, 案件名, .......
#ZektorH These're the whole codes without data.
code.gs
var ssId = 'xxxxxxxxxxxxxxxxxxxxxxxxx';
var ss = SpreadsheetApp.openById(ssId);
var indexPage_sheetName = 'xxxxxxxxxxxxxx';
var valuesFromIndexPage = ss.getSheetByName(indexPage_sheetName).getDataRange().getValues();
function createSidebar() {
SpreadsheetApp.getUi().showSidebar(HtmlService.createHtmlOutputFromFile('index').setTitle('My custom sidebar').setWidth(300))
}
function getData() {
return valuesFromIndexPage;
}
function doGet(e) {
return HtmlService.createTemplateFromFile('index').evaluate().setTitle('title');
}
index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script src="https://code.jquery.com/jquery-3.4.1.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.20/css/jquery.dataTables.css">
<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.10.20/js/jquery.dataTables.js"></script>
<script>
$(document).ready(function() {
console.log("ready!");
google.script.run.withSuccessHandler(initializeTable).getData(); //calls the getData funciton from Apps Script and returns the results to the initializeTable function
});
function initializeTable(data) {
console.log(data)
var aDataSet = data.slice(1); // all except header
var head = []; // headers
data[0].forEach(function(e) {
head.push({
'sTitle': e
});
});
$('#foo-table').dataTable({
"aaData": aDataSet,
"aoColumns": head
});
}
</script>
</head>
<body>
<table id="foo-table" class="display" width="100%"></table>
</body>
</html>
Chage with columns of of key in dataTable for table headers and chage $("#foo-table").DataTable at $("#foo-table").dataTable
var valuesFromIndexPage=[{"free-text-c1":"free-text-r1","c2":"r1","c3":"r1","c4":"r1","c5":"r1","c6":"r1","c7":"r1","c8":"r1","c9":"free-text-r1","c10":"free-text-r1"},{"free-text-c1":"free-text-r2","c2":"r2","c3":"r2","c4":"r2","c5":"r2","c6":"r2","c7":"r2","c8":"r2","c9":"free-text-r2","c10":"free-text-r2"}];
valuesFromIndexPage.shift();
function getData() {
$(document).ready(function(){
$("#foo-table").dataTable({
destroy: true,
scrollX: true,
data: valuesFromIndexPage,
columns: _.keys(valuesFromIndexPage[0]).map((key) => { return { "title": key, "data": key } })
});
});
}
getData()
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>
<html>
<head>
<script src="//ajax.aspnetcdn.com/ajax/jquery/jquery-1.9.1.js"></script>
<link rel="stylesheet" href="https://cdn.datatables.net/1.10.20/css/jquery.dataTables.min.css"/>
<script src="https://cdn.datatables.net/1.10.20/js/jquery.dataTables.min.js"></script>
<body>
<table id="foo-table" class="display" width="100%"></table>
</body>
</head>
</html>
Assuming you are using it on a sidebar, I was able to get it to work like this:
Apps Script
function createSidebar() {
SpreadsheetApp.getUi().showSidebar(HtmlService.createHtmlOutputFromFile('sidebar').setTitle('My custom sidebar').setWidth(300))
}
function getData() {
return SpreadsheetApp.getActiveSheet().getDataRange().getValues();
}
HTML Page
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script src="https://code.jquery.com/jquery-3.4.1.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.20/css/jquery.dataTables.css">
<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.10.20/js/jquery.dataTables.js"></script>
<script>
$(document).ready(function() {
console.log("ready!");
google.script.run.withSuccessHandler(initializeTable).getData(); //calls the getData funciton from Apps Script and returns the results to the initializeTable function
});
function initializeTable(data) {
var aDataSet = data.slice(1); // all except header
var head = []; // headers
data[0].forEach(function(e) {
head.push({
'sTitle': e
});
});
$('#foo-table').dataTable({
"aaData": aDataSet,
"aoColumns": head
});
}
</script>
</head>
<body>
<table id="foo-table" class="display" width="100%"></table>
</body>
</html>
Hope this helps!

jQuery templates fundamentals

I've got two items in a data object which should subsitute two expressions within my html file. However this is somehow not working. Do you guys know what I am doing wrong?
<head>
<script src="jquery-1.11.3.js"></script>
<script src="handlebars-v4.0.5.js"></script>
</head>
<body>
<script type="text/x-handlebars-template">
var source = $("#template").html();
var template = Handlebars.compile(source);
var data = {
title:"The Earth seen from Apollo 11",
author:"Ed g2s",
};
var html = template(data);
</script>
<script id="template" type="text/x-handlebars-template">
<h1>{{title}}</h1>
<h3>{{author}}</h3>
</script></body>

AngularJS : Can Controller request external js on fly?

I have a non-AngularJS based page - basic.html which works fine as expected.
basic.html
<!doctype html>
<html>
<head>
</head>
<body>
<div class="tab-container" >
<div id="piechart" style="width:1000px;height:470px;"></div>
</div>
<script src="scripts/angular.min.js"></script>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script>
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Device', 'Hits (in millions)'],
['A', 89],
['B', 13],
['C', 21],
]);
var options = { title: '' };
var chart = new google.visualization.PieChart(document.getElementById('piechart'));
chart.draw(data, options);
}
</script>
</body>
</html>
Then I tried to reorganize the code (a bit naively) to put into AngularJS framework as follows:
basic.html
<!doctype html>
<html ng-app = "Analytics-App" ng-controller="MainController">
<head>
</head>
<body>
<div class="tab-container" >
<div id="piechart" style="width:1000px;height:470px;"></div>
</div>
<script src="scripts/angular.min.js"></script>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script src="scripts/base.js"></script>
</body>
</html>
base.js
var myApp = angular.module('Analytics-App', []);
myApp.controller('MainController', function($scope, $interval) {
var e = document.createElement("script");
e.src = "https://www.google.com/jsapi";
e.type="text/javascript";
document.getElementsByTagName("head")[0].appendChild(e);
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Device', 'Hits (in millions)'],
['A', 89],
['B', 13],
['C', 21],
]);
var options = {
title: ''
};
var chart = new google.visualization.PieChart(document.getElementById('piechart'));
chart.draw(data, options);
}
});
Apparently, when loaded, the page DOM changes completely (when viewed using chrome debugger) as:
<html><head><script src="https://www.google.com/uds/?file=visualization&v=1&packages=corechart" type="text/javascript"></script><link href="https://www.google.com/uds/api/visualization/1.0/d90be93871e947a274f6a5157bd75fb0/ui+en.css" type="text/css" rel="stylesheet"><script src="https://www.google.com/uds/api/visualization/1.0/d90be93871e947a274f6a5157bd75fb0/format+en,default+en,ui+en,corechart+en.I.js" type="text/javascript"></script></head></html>
I am trying to understand why controller script failed to add elements into page DOM and why rest of the page elements are removed.
Please use this following.
google.setOnLoadCallback(function () {
angular.bootstrap(document.body, ['Analytics-App']);
});
google.load('visualization', '1', {packages: ['corechart']});
var googleChart = googleChart || angular.module("google-chart",[]);
var myApp = myApp || angular.module("Analytics-App",["google-chart"]);
googleChart.directive("googleChart",function(){
return{
restrict : "A",
link: function($scope, $elem, $attr){
var dt = $scope[$attr.ngModel].dataTable;
var options = {};
if($scope[$attr.ngModel].title)
options.title = $scope[$attr.ngModel].title;
var googleChart = new google.visualization[$attr.googleChart]($elem[0]);
googleChart.draw(dt,options)
}
}
});
myApp.controller("IndexCtrl",function($scope){
$scope.data1 = {};
$scope.data1.dataTable = new google.visualization.DataTable();
$scope.data1.dataTable.addColumn("string","Name")
$scope.data1.dataTable.addColumn("number","Qty")
$scope.data1.dataTable.addRow(["Test",89]);
$scope.data1.dataTable.addRow(["Test2",13]);
$scope.data1.dataTable.addRow(["Test3",21]);
$scope.data1.title="My Pie"
});
<!doctype html>
<html>
<head>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js"></script>
<script src="script.js"></script>
<style type="text/css">
.bigGraph {width:500px;height:500px;float:left;}
.mediumGraph {width:400px;height:400px;float:left;}
.smallGraph {width:200px;height:200px;float:left;}
</style>
</head>
<body ng-controller="IndexCtrl">
<div google-chart="PieChart" ng-model="data1" class="bigGraph"></div>
</body>
</html>
Plunker URL http://plnkr.co/edit/5guBqC0upuCVgBtY6076?p=preview
Further help http://gavindraper.com/2013/07/30/google-charts-in-angularjs/
and http://jrrera.github.io/angularjs/2014/04/05/a-better-way-to-integrate-angularjs-and-google-charts/

Turn model into JSON and pass it into JavaScript setOnLoadCallBack

Below is my view. I have modified it to display how I would like it to work. I have a graph that is drawn when the page is loaded. My model contains the data it needs. I have to transform it to JSON (right?) and then pass it into the generateGraph, but the setOnLoadCallBack is my problem. I can't figure out how to create the JSON string before the setOnLoadCallBack is called.
#model IEnumerable<FHWebUserInterface.Models.Weight>
<div id="visualization" style="width: 600px; height: 400px;"></div>
<div id="linechart_material"></div>
#{
var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
var weightsAsJsonString = serializer.Serialize(Enumerable.Select(Model, weight =>
new
{
date = weight.Date,
value = weight.Value
}));
}
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load('visualization', '1.1', { packages: ['corechart', 'imagelinechart'] });
</script>
<script type="text/javascript">
function drawVisualization(weightsAsJsonString) {
// Removed the body
chart.draw(data, options);
}
google.setOnLoadCallback(drawVisualization(weightsAsJsonString));
</script>
You just need to render your json somewhere in JavaScript block like this (i've added it before google.setOnLoadCallback call):
#model IEnumerable<FHWebUserInterface.Models.Weight>
<div id="visualization" style="width: 600px; height: 400px;"></div>
<div id="linechart_material"></div>
#{
var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
var weightsAsJsonString = serializer.Serialize(Enumerable.Select(Model, weight =>
new
{
date = weight.Date,
value = weight.Value
}));
}
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load('visualization', '1.1', { packages: ['corechart', 'imagelinechart'] });
</script>
<script type="text/javascript">
function drawVisualization(weightsAsJsonString) {
// Removed the body
chart.draw(data, options);
}
// here is my change
var weightsAsJsonString = #weightsAsJsonString; // so it will render your C# object from server side here on client side
google.setOnLoadCallback(drawVisualization(weightsAsJsonString));
</script>

Googlecharts arraytodatatable possible dimension issue?

I have a 2 arrays which I got from php, put into a single 2D Javascript array. I'm trying to use it to autofill a Google Chart DataTable, but so far I've had no success.
The only thing that I can think of is that maybe the array ix MxN dimension, while the function needs a NxM array?
Either does it not work because the first array is made of numbers?
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>Pressure Monitor</title>
<script type="text/javascript">
var samptable = new Array();
samptable[0] = new Array(2);
samptable[0,0]= nbsamples; //first array obtained from php
samptable[0,1]= samples; //second array obtained from php. both are merged into a 2d array
</script>
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load('visualization', '1', {packages: ['corechart']});
</script>
<script type="text/javascript">
//var data;
function drawVisualization() {
var data = google.visualization.arrayToDataTable(samptable[0]);
// Create and draw the visualization.
new google.visualization.LineChart(document.getElementById('visualization')).
draw(data, {curveType: "function",
width: 500, height: 400,
vAxis: {maxValue: 10}}
);
}
//function draw(){
//}
google.setOnLoadCallback(drawVisualization);
</script>
</head>
<body style="font-family: Arial;border: 0 none;">
<div id="visualization" style="width: 800px; height: 400px;"></div>
</body>
</html>
The code used to get nbsamples and samples:
echo '<script type="text/javascript">';
echo 'var samples = new Array("', join($ydata,'","'), '");';
echo 'var nbsamples = new Array("', join($nbsamples,'","'), '");';
echo '</script>';
Try this instead to create the arrays:
var samptable = [];
samptable.push(nbsamples);
samptable.push(samples);
Then, since it appears that your arrays are all data, make sure to specify *opt_firstRowIsData* option as true (defaults to false):
var data = google.visualization.arrayToDataTable(samptable, true);
You might want to also verify that nbsamples and samples are valid arrays by logging them to the console:
console.log(nbsamples);
console.log(samples);
For this to be valid, they should each appear as a row of data (same number of items), eg:
[5, 4, 10]
[1, 3, 3]

Categories