Google annotated timeline not displaying on application start - javascript

I am having a problem with the Google annotated timeline. I have this function (shown below) that is called in the jQuery ready function:
//creates an annotated timeline
function graphAnnotatedTimeLine(url) {
jQuery.get(url, function(returned_data) {
//parse returned_data ...
//build data table
var dataTable = new google.visualization.DataTable();
dataTable.addColumn('datetime', columnHeadings[0]);
dataTable.addColumn('number', columnHeadings[1]);
//populate table
for(var i = 0; i < rawData.length; i++) {
var parsedData = data[i].split(",");
dataTable.addRow([new Date(parsedData[0]), parseFloat(parsedData[1])]);
}
//draw graph
var options = {displayAnnotations: false,
allowRedraw: true,
legendPosition: 'newRow',
displayZoomButtons: false,
wmode: 'transparent'};
var chart = new google.visualization.AnnotatedTimeLine(document.getElementById('chart-div'));
chart.draw(dataTable, options);
});
}
Called in the ready function as:
$.ready(function() {
//generate url string
google.setOnLoadCallback(graphAnnotatedTimeline(url));
self.setInterval('updateGraph', 60000);
//more stuff
});
So in the ready I call it to draw the first set of data and then set an update function to be called every minute. All the update function does is basically the same as the ready function does: build a url string and call the graph function with that url. The problem I'm having is that the graph it doesn't display on startup. Once the update gets called once though, it displays fine after that. Is there anyone that can give me some insite as to why this is happening?

This is because your jquery ready function is called before the google visualization script is loaded. google.setOnLoadCallback must be called like this...
<script type="text/javascript" src='http://www.google.com/jsapi?autoload={"modules":[{"name":"visualization","version":"1","packages":["annotatedtimeline"]}]}'></script>
<script type="text/javascript">
google.setOnLoadCallback(graphAnnotatedTimeline(url));
</script>

Related

Creating multiple Google Charts recursively in Javascript

I'm trying to create multiple Google Charts recursively with the code below. I'm using AJAX to get the chart data and to store in the array histogramData.
With this code I can create the multiple i_histogram charts, but apparently, on each loop interaction, the previous chart is overwritten by the last one.
HTML code:
<div id="histogramCharts"></div>
Javascript code:
var histogramChartElement = document.getElementById('histogramCharts');
// remove histogram chart element children
while (histogramChartElement.hasChildNodes()) {
histogramChartElement.removeChild(histogramChartElement.childNodes[0]);
}
for (var i = 0; i < histogramLabels.length; i++) {
var label = histogramLabels[i];
var node = document.createElement('div');
node.setAttribute('id', i + '_histogram');
histogramChartElement.appendChild(node);
var dataTable = new google.visualization.DataTable();
dataTable.addColumn('string', 'A');
dataTable.addColumn('number', 'B');
dataTable.addRows(histogramData[i]);
google.charts.setOnLoadCallback(function () {
var options = {
title: histogramLabels[i],
legend: {position: 'none'},
histogram: {bucketSize: 0.1}
};
var histogramChart = new google.visualization.Histogram(node);
histogramChart.draw(dataTable, options);
});
}
I got this result:
<div id="histogramCharts">
<div id="0_histogram"></div>
<div id="1_histogram"></div>
<div id="2_histogram">
<div style="position: relative;">....</div>
</div>
</div>
first, setOnLoadCallback should only be called once per page load,
once it fires, you can draw as many charts as needed...
you can also depend on the callback to know when the page is ready,
instead of --> $(document).ready -- or something similar...
as such, recommend loading google first, before anything else,
then use ajax to get the data, then draw the charts...
try similar setup as follows, placing the callback in the load statement...
google.charts.load('current', {
callback: getData,
packages:['corechart']
});
function getData() {
$.ajax({
url: '...',
}).done(drawCharts);
}
function drawCharts(data) {
// use data to build histogramData
var histogramChartElement = document.getElementById('histogramCharts');
// remove histogram chart element children
while (histogramChartElement.hasChildNodes()) {
histogramChartElement.removeChild(histogramChartElement.childNodes[0]);
}
for (var i = 0; i < histogramLabels.length; i++) {
var label = histogramLabels[i];
var node = document.createElement('div');
node.setAttribute('id', i + '_histogram');
histogramChartElement.appendChild(node);
var dataTable = new google.visualization.DataTable();
dataTable.addColumn('string', 'A');
dataTable.addColumn('number', 'B');
dataTable.addRows(histogramData[i]);
var options = {
title: histogramLabels[i],
legend: {position: 'none'},
histogram: {bucketSize: 0.1}
};
var histogramChart = new google.visualization.Histogram(node);
histogramChart.draw(dataTable, options);
}
}

Loading or Activating ChartJS on Load

I have Chart.js set up with a form so that it takes input fields from the form and after clicking Submit/Update button, it generates a donut chart using those numbers from the input fields as data points.
The issue is how can I get the form or Chart.js to run once and generate a donut chart with the input fields numbers when its on the page (on page load).
The form input fields are already filled with numbers/data via HTML5 Local Storage).
I've tried jQuery .submit(); on page load but nothing happens. I appreciate any help. Thank you.
EDIT: I've gone ahead and created a fiddle to re-create the issue.
$(document).ready(function () {
$("#submit-btn").click(function (e) {
e.preventDefault();
var outputyearly = $('#outputyearly');
var amount = parseInt($('#amount').val().replace(/,/g, ''), 10);
var rate = parseFloat($('#rate').val(), 10);
var term = parseFloat($('#term').val(), 10);
// Some math calculations code
if (window.onload.myDoughnutChart != null) {
window.onload.myDoughnutChart.destroy();
}
var ctx = document.getElementById("myChart").getContext("2d");
window.onload.myDoughnutChart = new Chart(ctx, {
type: 'doughnut',
data: data,
options: options
});
});
});
You can put the code that draws the chart in a function and call that function on both the $(document).ready and $("#submit-btn").click event, like this:
function drawChart() {
var outputyearly = $('#outputyearly');
var amount = parseInt($('#amount').val().replace(/,/g, ''), 10);
var rate = parseFloat($('#rate').val(), 10);
var term = parseFloat($('#term').val(), 10);
//Destroy the dougnut chart here, not sure how it's accessible, but it won't work through window.onload
var ctx = document.getElementById("myChart").getContext("2d");
new Chart(ctx, {
type: 'doughnut',
data: data,
options: options
});
}
$(document).ready(function() {
drawChart();
$("#submit-btn").click(function (e) {
e.preventDefault();
drawChart();
});
});
Note that $(document).ready already imposes the code inside of it to be executed when the page is done, so putting a window.onload inside of it won't make any difference.

this.someProperty is not a function in JavaScript object

I am trying to abstract some of my JavaScript code by adding functions as objects of properties. The ultimate goal is a dynamic way to render data using Google charts. Below is my charts object which right now works when I call it on the page. This is assuming a separate config and util object which have some other methods:
app.charts = {
init: function(){
// Load the Visualization API and the piechart package, wait until loaded
google.load('visualization', '1.0', {'packages':['corechart']});
google.setOnLoadCallback(this.createChart);
},
createChart: function(){
// draw charts to their id
chartData = app.utils.getAjax(s.urls.dashUrl, function(data){
// Convert to a table
var jsonDataTable = new google.visualization.DataTable(data);
// Select html element and draw the chart
var chartJson = new google.visualization.BarChart(document.getElementById('json'));
chartJson.draw(jsonDataTable);
this.dataTable();
});
},
dataTable: function(){
console.log("whatever");
}
};
What i would like to do is abstract the var chartJson = new google.visualization.BarChart(document.getElementById('json')); line so that I can give an option and switch to different charts instead of hard coding every chart I want (and thus make it so I can let the user choose chart type.
Whenever I try and write another method, I get a google.visualization is undefined error. I don't see why though because I don't call anything until after the google load callback in init.
To start simple I tried to take have the dataTable: function return a new new google.visualization.DataTable(data); and I received ReferenceError: dataTable is not defined.
I am not sure what is going on that these values can't be found or used, any help appreciated.
I've just just writing some code thinking you meant one thing but I'm not sure it is now reading follow up comments... I'm posting it anyway just FYI:
app.charts = {
init: function(){
// Load the Visualization API and the piechart package, wait until loaded
google.load('visualization', '1.0', {'packages':['corechart']});
google.setOnLoadCallback(this.createChart);
},
createChart: function(){
// draw charts to their id
chartData = app.utils.getAjax(s.urls.dashUrl, function(data){
// Convert to a table
var jsonDataTable = new google.visualization.DataTable(data);
// Select html element and draw the chart
var input = document.getElementById('user-input').value;
this.chartType(input);
this.dataTable();
});
},
dataTable: function(){
console.log("whatever");
},
chartType: function(input){
switch(input)
{
case 'whatever':
var chartJson = new google.visualization.BarChart(document.getElementById('json'));
chartJson.draw(jsonDataTable);
break;
case 'whatever2':
// etc
break;
}
}
};
HTML
<select id="user-input">
<option value="whatever">whataver</option>
<option value="whatever2">whataver2</option>
</select>

How to get two different google charts on one page from two separate spreadsheet data sources

I'm trying to get multiple chats on the same page, each one using a different spreadsheet url for its data source.
The code below works ok, but I really want to have multiple urls for different data ranges and show a different chart each time.
When I tried this originally, it only ever showed the last chart I tried to draw.
I’ve reworked the script (which still works) to move closer to a situation where I’ve got multiple sets of data for the multiple charts and their locations. It’s not quite there though. This was based on the following post:
How to add two Google charts on the one page?
I think I need to pass the multiple sets of data as attributes of the handleQueryResponse function but I don’t know how to do that.
I was trying to get it to work for just one set of data first, and if that works ok, add multiple sets of data into it.
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
(function() { // Begin scoping function
// vars Global to my code, invisible outside the scoping function
// Set chart options
// I'll be using multiple options for different charts, options1, options2 etc.
var options1 = {'title':'Light & Temperature data - Last 24 Hours',
'width':750,
'height':400,
'curveType': 'function',
'backgroundColor':'ffe599',
"hAxes":[{"title":"Time"}],
"vAxes":[{"title":"Temp in °C -- Light Levels"}]};
//I think I will need containerID1, containerID2 etc. one for each chart
var containerID = 'chart_div1';
//same for chartType1, chartType2
var chartType = 'LINECHART';
// Load the Visualization API and the core chart package.
google.load('visualization', '1.0', {'packages':['corechart']});
// Set a callback to run when the Google Visualization API is loaded.
google.setOnLoadCallback(drawChart);
// Callback that creates and populates a data table,
// instantiates the chart, passes in the data and
// draws it.
function drawChart() {
//I'm going to have multiple urls and each one will be the source for a seperate chart
var query1 = new google.visualization.Query(
'https://docs.google.com/spreadsheet/ccc?key=0ArGuv......&transpose=0&headers=1&range=L1%3AN500&gid=1');
query1.send(handleQueryResponse);
}
// how do I get containerID1, containerID2, chartType1, ChartType2 Options1, Options2 etc. into this function?
function handleQueryResponse(response) {
if (response.isError()) {
alert('Error in query: ' + response.getMessage() + ' ' + response.getDetailedMessage());
return;
}
var data = response.getDataTable();
var containerDiv = document.getElementById(containerID);
var chart = false;
// Instantiate and draw the chart, based on some the chartType and passing in the options.
if (chartType.toUpperCase() == 'BARCHART') {
chart = new google.visualization.BarChart(containerDiv);
}
else if (chartType.toUpperCase() == 'COLUMNCHART') {
chart = new google.visualization.ColumnChart(containerDiv);
}
else if (chartType.toUpperCase() == 'PIECHART') {
chart = new google.visualization.PieChart(containerDiv);
}
else if (chartType.toUpperCase() == 'LINECHART'){
chart = new google.visualization.LineChart(containerDiv);
}
if (chart == false) {
return false;
}
chart.draw(data, options1);
}
})(); // End scoping function
</script>
<!--Divs that will hold the charts - Only chart_div1 is in effect at the moment -->
<div id="chart_div1"></div>
<div id="chart_div2"></div>
You need two response handlers and two queries if you are querying two different data sources:
function drawChart() {
var query1 = new google.visualization.Query(url1);
query1.send(handleQueryResponse1);
var query2 = new google.visualization.Query(url2);
query2.send(handleQueryResponse2);
}

Creating Raphael SVG without onload

Iam fairly new to SVG and this is my first time trying svg with javascript. I am trying to create a collection of charts using Raphael SVG. In order to create these charts I need to create an SVG element dynamically. The problem here is that the javascript function to create the chart is being accessed from the html page where the data input for the charts is entered. So inorder to access the function (Charts();) I have not added an onload function. Due to this, the Raphael svg is not getting created as it needs a DOM element on which it is created. How do I fix this problem?
Charts.js is as follows:
var Charts = function Charts(config){
var chart = this;
chart.defaults = {
.....
};
chart.Line = function(series, dataline){
var newconfig = (config) ? mergeConfig(chart.defaults, config) : chart.defaults;
return new KzSc(createSVG(newconfig, series, 'line'), newconfig, { series : series, name : 'line', dataline : dataline});
}
function createSVG(config, series, name){
//create svg
var chart_wrapper = document.getElementById(config.wrapperId);
chart_wrapper.style.position = "relative";
var SVGpaper = new Raphael(320, 200);
chart_wrapper.appendChild(SVGpaper);
var createSVGContainer = document.createElement("div");
createSVGContainer.setAttribute('id',config.containerId);
chart_wrapper.appendChild(createSVGContainer);
}}
This gives the error 'Cannot read property of 'x'' in the rapahel script.
The html part contains the script which calls the function.
<html>
<head>
<script src="charts.js"></script>
<script>
var = (describe data for charts)
new Charts(....);
</script>
</head>
<body>
<div id="containerforsvg"></div>
</body>
</html>
Also, if I add an onload or ready function i.e;
$(document).ready(function() {
var Charts = ...
)}
Then it gives the error Uncaught ReferenceError: Charts is not defined

Categories