Problem Rendering Multiple CanvasJS charts on one page - javascript

I have a page (stats.php) that calls php pages containing canvasjs scripts for rendering charts on them. I can get the pages (top_airlines.php and top_aircraft.php) that contain each individual chart to render, however, when I try to get them on the single stats.php page only one of them will actually render.
It utilizes JSON, which I am not at all familiar with and am using the example that was given to me by their help desk a couple of years ago. I've attempted to modify the code so that it should, in theory, load the chart. Again, they'll load on their independent pages it's just when I try to call them on a single page together that all code breaks loose.
I am curious to think that maybe it is related to the javascript code for
$(document).ready(function ()`
TOP AIRLINES (top_airlines.php)
<script src=”http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js”></script>
<script src=”https://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js”></script>
<script src=”http://globe-trekking.com/vg/includes/js/jquery.canvasjs.min.js”></script>
<script type=”text/javascript”>
window.onload = function () {
CanvasJS.addColorSet(“blueShades2”,
[//colorSet Array
“#074b83”,
“#085a9d”,
“#0a69b7”,
“#0b78d1”,
“#0c87eb”,
“#2196f3”,
“#4daaf6”,
“#79bff8”,
“#a6d4fa”,
“#d2eafd”
]);
$(document).ready(function () {
$.getJSON(“http://globe-trekking.com/vg/charts/top_airlines_data.php”, function (result) {
var chartAirlines = new CanvasJS.Chart(“top_10_airlines_chart”, {
animationEnabled: false,
colorSet: “blueShades2”,
toolTip:{content: “{name}”},
data: [
{
type: “bar”,
indexLabelFontSize: 22,
dataPoints: result
}
]
});
chartAirlines.render();
});
});
}
</script>
<div id=”top_10_airlines_chart” style=”width: 100%; height: 300px;”></div>
TOP AIRCRAFT (top_aircraft.php)
<script src=”http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js”></script>
<script src=”https://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js”></script>
<script src=”http://globe-trekking.com/vg/includes/js/jquery.canvasjs.min.js”></script>
<script type=”text/javascript”>
window.onload = function () {
CanvasJS.addColorSet(“blueShades”,
[//colorSet Array
“#074b83”,
“#085a9d”,
“#0a69b7”,
“#0b78d1”,
“#0c87eb”,
“#2196f3”,
“#4daaf6”,
“#79bff8”,
“#a6d4fa”,
“#d2eafd”
]);
$(document).ready(function () {
$.getJSON(“http://globe-trekking.com/vg/charts/top_aircraft_data.php”, function (result) {
var chartAircraft = new CanvasJS.Chart(“top_10_airplanes_chart”, {
animationEnabled: false,
colorSet: “blueShades”,
toolTip:{content: “{name}”},
data: [
{
type: “bar”,
indexLabelFontSize: 22,
dataPoints: result
}
]
});
chartAircraft.render();
});
});
}
</script>
<div id=”top_10_airplanes_chart” style=”width: 100%; height: 300px;”></div>
I'm calling them on the stats.php page by using the following located in a certain location on the stats.php page.

The issue seems to happen due to overriding of window.onload event. Changing it to jQuery ready / load should work fine in your case. Here is the sample project.
You can also try out the ways suggested in this stackoverflow thread.
$(document).ready(function () {
CanvasJS.addColorSet(“blueShades”,
[//colorSet Array
“#074b83”,
“#085a9d”,
“#0a69b7”,
“#0b78d1”,
“#0c87eb”,
“#2196f3”,
“#4daaf6”,
“#79bff8”,
“#a6d4fa”,
“#d2eafd”
]);
});
PS: dataPoints are hardcoded in sample-project.

Related

Chart.js not drawing on mobile (safari/chrome) fine on desktop

I've got a piechart that works perfectly fine on desktop. It retrieves data from an AJAX request and stores the data/json it gets. Selected data is then pushed into the chart. I am using Thymeleaf & Spring in but thats not relevant here I believe.
Everything is rendered fine on my page when I access it through Safari or chrome on mobile, however the graph is not present.
I've tried changing responsive true/false, maintaingAspectRatio false/true, playing with other options provided in the chart.js documentation. Changed the viewport, set my width on the container of the canvas rather than the canvas it self and a whole bunch of other stuff.
Could it be due to the load order? i.e the page is loaded before it can actually get the information from the request? However, that would mean that it shouldn't be working on desktop either.
Here is some code
myGraph.js
$(document).ready(function () {
var id = $.url(2);
$.ajax({
url: "hosturl/a/b/" + id + "/c/d",
type: "GET",
dataType: "json",
success: function (data) {
console.log(data);
var count = [];
var days = [];
for (var i in data) {
days.push(data[i][1]);
count.push(data[i][0]);
}
var chartdata = {
labels: days,
datasets: [
{
label: "By day",
backgroundColor: "#4dc3ff",
borderWidth: 2,
hoverBackgroundColor: "#009",
hoverBorderColor: "#099",
hoverBorderWidth: 5,
data: count
}
]
};
var ctx = $("#daysGraph");
var pieChart = new Chart(ctx, {
type: 'pie',
data: chartdata,
options: {
responsive: true,
legend: {
display: true,
position: 'right',
labels: {
fontColor: "#000"
}
}
}
});
},
error: function (data) {
}
});
graph.html (most of the other html is cut out out, but this on its own doesn't work)
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-
scale=1,maximum-scale=7"/>
<title>Hmm</title>
<script type="text/javascript" src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css"/>
<script src="../../javascript/Chart.min.js" th:href="#{/Chart.min.js}"/>
<script src="../../javascript/js-url-2.5.0/url.js" th:href="#{/url.js}" ></script >
<link rel="stylesheet" href="../static/css/graph.css" th:href="#{/css/graph.css}"/>
<script src="../../javascript/myGraph.js" th:href="#{/myGraph.js}" />
</head>
<body>
<div class="chart-container">
<canvas id="daysGraph" ></canvas>
</div>
</body>
</html>
graph.css
.chart-container {
position: relative;
margin: auto;
height: 80vh;
width: 80vw;
}
On the live server it looks like this
Any advice is welcome
Turned out there was something wrong with the api-route on mobile vs dektop relating to localhost. Therefore my data wasn't being fetched from the api and thus wouldn't populate the chart which is why it is not displaying on mobile. In other words, I was looking in the wrong places for an answer.
I've had similar problems myself, I resolved my issue by playing around with the borderWidth in order to get it working across all devices. Try changing it several times to see if it has any impact at all.

How do you get a Google Chart to redraw based on data you pass to it?

The bulk of the examples I've found showing Google Charts have simple little arrays...
I need to pull an array from my server.
I can get a pie chart to draw, but it doesn't update.
Here is my attempt to get a flexible, redrawing pie chart:
At the top of my javascript, but before document.ready:
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart);
My drawChart function:
function drawChart(arrFeedbackResult3) {
console.log('Draw a fucking chart ... ') + console.log(arrFeedbackResult3);
var chart_data = new google.visualization.DataTable(arrFeedbackResult3);
var options = {
title: 'Comments by Group',
sliceVisibilityThreshold: 1/20, // Only > 5% will be shown.
width: 400,
height: 400
};
chart = new
google.visualization.PieChart(document.getElementById('groupPieChartDiv'));
chart.draw(chart_data, options);
// chart = new google.visualization.PieChart(document.getElementById('groupPieChartDiv'));
// chart.draw(data, options);
}
And the function that, after a button is clicked, passes fresh data to drawChart:
function setupFeedback3(arrFeedbackResult3){ // Create Group summary Graphs
console.log('Groups summary from DB: ') + console.log(arrFeedbackResult3);
drawChart(arrFeedbackResult3);
} // END setupFeedback3
I get a "table has no columns" message on my page with the above code.
The array, arrFeedbackResult3, is formatted correctly and does render a chart when I change the code but end up without the ability to refresh.
Any help appreciated. I think I'm just missing the basic flow of using Google Charts...and how/where the callback should be used.
Updating with my next attempt after a very generous and detailed reply.
My js is in a separate file from the html. I cannot get the passing of an array via callback to work. I get "not a constructor" errors or "not a function." I think because adding a parenthetical value breaks the code.
I also don't understand the comment about document.ready in the answer...I have kept document.ready in order to load all my other functions.
Right after document.ready I have:
google.charts.load('current', {
packages:['corechart'],
callback: drawChart
});
Then, after my db POST to get data, I call:
function setupFeedback3(result){ // Create Group summary Graphs
arrFeedbackResult3 = result; //Store in global variable for access by chart
drawChart();
} // END setupFeedback3
arrFeedbackResult3 is a GLOBAL variable - only way I could get the data to the draw chart function.
Then:
function drawChart() {
console.log('Draw a chart ... ') + console.log(arrFeedbackResult3);
// var chart_data = new google.visualization.DataTable(arrFeedbackResult3);
var chart_data = google.visualization.arrayToDataTable(arrFeedbackResult3);
var options = {
title: 'Comments by Group',
sliceVisibilityThreshold: 1/20,
width: 400,
height: 400
};
var chart = new google.visualization.PieChart(document.getElementById('groupPieChartDiv'));
chart.draw(chart_data, options);
}
This is working, and the chart does update as you feed different data, but it seems a shoddy state of affairs. One specific example of passing data, vs. a stupid simple example or using AJAX inside the function, would have been really helpful.
first, recommend not using jsapi to load the library.
according to the release notes...
The version of Google Charts that remains available via the jsapi loader is no longer being updated consistently. Please use the new gstatic loader.js from now on.
<script src="https://www.gstatic.com/charts/loader.js"></script>
this will only change the load statement...
google.charts.load('current', {packages:['corechart']});
next, the callback can be added to the load statement...
google.charts.load('current', {
packages:['corechart'],
callback: drawChart
});
or you can use the promise it returns...
google.charts.load('current', {
packages:['corechart']
}).then(drawChart);
also, the load statement will wait until the document is ready by default,
so it can be used in place of --> $(document).ready
finally, when creating a data table,
the argument for the constructor should be JSON, not a simple array
see Format of the Constructor's JavaScript Literal data Parameter,
for the specific JSON format
if you want to create a data table from a simple array,
use static method --> arrayToDataTable
recommend setup similar to following...
google.charts.load('current', {
packages:['corechart']
}).then(function () {
// get data
drawChart(arrayData);
});
function drawChart(arrayData) {
var chart_data = google.visualization.arrayToDataTable(arrayData);
var options = {
title: 'Comments by Group',
sliceVisibilityThreshold: 1/20,
width: 400,
height: 400
};
var chart = new google.visualization.PieChart(document.getElementById('groupPieChartDiv'));
chart.draw(chart_data, options);
}
function setupFeedback(arrayData) {
// get data
drawChart(arrayData);
}
UPDATE
you can use the promise the load statement returns as the callback and the document ready
just move the code as shown below...
then you can load your ajax call to get the data
google.charts.load('current', {
packages:['corechart']
}).then(function () {
// move code from document ready here
// get data
getData();
});
function getData() {
$.ajax({
type: 'POST',
contentType: 'application/json',
url: sourceURL,
success: setupFeedback
});
}
function setupFeedback(result) {
// you could draw the chart here
// just move the code from drawChart
// or pass the data along to another function
drawChart(result);
}
function drawChart(result) {
var chart_data = google.visualization.arrayToDataTable(result);
var options = {
title: 'Comments by Group',
sliceVisibilityThreshold: 1/20,
width: 400,
height: 400
};
var chart = new google.visualization.PieChart(document.getElementById('groupPieChartDiv'));
chart.draw(chart_data, options);
}

jquery prevent multiple instances of plugin

I am trying to display and update a chart using the plugin http://workshop.rs/jqbargraph/. The plugin is initiated on page load but I need to allow users to update the data that powers the chart. However, this functionality adds multiple charts everytime the update event is initiated. I assume I need to somehow destroy the original instance of the plugin before updating the chart data and re-initiating it but there is nothing incorporated into the plugin to allow this.
Can anyone tell me what I need to add to my code to get this working?
jQuery( document ).ready(function() {
var chartData = new Array([0]);
showChart(chartData);
jQuery('#update').live("click", function() {
var qtyArr = [];
jQuery('input[name=qty]').each(function(i) {
qty = Number(jQuery(this).val());
if(qty > 0){
qtyArr.push(qty);
}
});
chartData = new Array(
[qtyArr]
);
showChart(chartData);
});
});
function showChart(chartData){
jQuery("#chart").jqBarGraph({
data: chartData,
width: 200,
height: 300
});
}
call empty() before you call the plugin:
jQuery("#chart").empty().jqBarGraph({
data: chartData,
width: 200,
height: 300
});
The plugin's demo page clears the chart and reinitialises it as follows :
$('#exampleSimple').html('');
$('#exampleSimple').jqbargraph({ data: arrayOfData });
.empty() should also work.
You probably want -
function showChart(chartData) {
$('#chart').empty().jqBarGraph({
data: chartData,
width: 200,
height: 300
});
}

morris pie chart with a larger data

I need to know how can with jquery maybe show a better pie chart with morris.js...with jquery flot the library I can hide the result with per example less than 100 coincidences but with morris I don't know how?
Here the capture:
and I want to show it like this one:
here is the jquery i use:
<script type='text/javascript' charset='utf-8'>
$(function () {
var pie = {
element: 'pie',
hideHover: 'auto',
resize: true,
data: <?php include('graficas6.php'); ?>,
colors: [
'#1424b8',
'#0aa623',
'#940f3f',
'#148585',
'#098215',
'#b86c14',
'#b83214'
],
formatter: function (y) {
return y + " "
}
}
donut1 = Morris.Donut(pie)
});
</script>
I would suggest if you have the large data then you should use pagination ,so that data will be shown on each of the different pages.
There are many benefits if you look into these website.
https://demo.aheadmetrics.com/#UIJGJX6MIQ
I am currently making my ecommerce sales report . Once it gets love i will put that link over here

Using Flot with multiple bars with orderbars.js and categories

I am having trouble creating multiple bars with flot. There is a plugin that can be downloaded here: http://www.benjaminbuffet.com/public/js/jquery.flot.orderBars.js that makes graphs with multiple bars per x category like this: http://www.pikemere.co.uk/blog/tutorial-flot-how-to-create-bar-charts/ (see under the customized bar charts). However, his example is a bit different in that it uses the time function rather than categories.
Here is my code:
<!doctype html>
<head>
<script language="javascript" type="text/javascript" src="/flot/jquery.js"></script>
<script language="javascript" type="text/javascript" src="/flot/jquery.flot.js"> </script>
<script language="javascript" type="text/javascript" src="/flot/jquery.flot.categories.js"></script>
<script language="javascript" type="text/javascript" src="/flot/jquery.flot.orderBars.js"></script>
<script type="text/javascript">
$(document).ready(function () {
var data1 = [
{
label: "Male" ,
data: [["True", 1],["False", 2]] ,
bars: {
show: true,
barWidth: 0.13,
order: 1
}
},
{
label: "Female" ,
data: [["True", 3],["False", 4]],
bars: {
show: true,
barWidth: 0.13,
order: 2
}
}
];
$.plot($("#placeholder"), data1, {
xaxis: {
mode: "categories"
},
});
});
</script>
<title>Test</title>
</head>
<body>
<div id="placeholder" style="width:600px;height:300px"></div>
</body>
</html>
With the above code, the graph displays, but without any bars. If I remove the order:1 and order:2, it displays correctly, except with the bars overlapping each other rather than being offset by each other (I think it just ignores the orderbars plugin).
This is a very simplified example of what I really want to do, but if someone knows how I can get it to do what I want fairly simply, I would be very much appreciative.
To sum up, what I want is to have two sets of two bars. The first set with "True" under them and the second second set with "False" under them. I do not want to use numbers to represent the values, if possible as it will greatly complicate my more complex situation. But if I must, I would still like to know how to do it that way.
change the function getAxeMinMaxValues in orderBars.js
function getAxeMinMaxValues(series, AxeIdx) {
var minMaxValues = new Array();
for (var i = 0; i < series.length; i++) {
series[i].data[series[i].data.length - 1][AxeIdx];
minMaxValues[0] = 0;
minMaxValues[1] = series[i].data.length - 1;
}
return minMaxValues;
}
hope this will help

Categories

Resources