Whenever I am trying to update my chart through AJAX by clicking a button, I am getting following error:
TypeError: this.canvas is null
this.context = this.canvas.getContext('2d');
RGraph.bar.js (line 49, col 9)
I tried various solutions but nothing worked for me. Here's are my two files which are being used in this process:
index.php:
<?php
include("includes/db-config.php");
$query = "SELECT * FROM `tb_daily_statistics`";
$rs = mysqli_query($con, $query);
$labels = array();
$data = array();
while($row = mysqli_fetch_array($rs))
{
$labels[] = $row['day'];
$data[] = $row['statistics'];
}
// Now you can aggregate all the data into one string
$data_string = "[" . implode(", ", $data) . "]";
$labels_string = "['" . implode("', '", $labels) . "']";
?>
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>RGraph Charts</title>
<script type="text/javascript" src="js/jquery-1.12.4.min.js"></script>
<script type="text/javascript" src="js/RGraph/RGraph.common.core.js"></script>
<script type="text/javascript" src="js/RGraph/RGraph.bar.js"></script>
<!--[if lt IE 9]><script src="js/RGraph/excanvas.js"></script><![endif]-->
<script type="text/javascript">
$(document).ready(function (){
var bar = new RGraph.Bar({
id: 'mycanvas',
data: <?php echo $data_string; ?>,
options: {
labels: <?php echo $labels_string; ?>,
gutter: {
left: 50
}
}
}).draw()
$("#btnstats").click(function(){
var order_by = $(this).data("order");
//alert(order_by);
// Reset the canvas
RGraph.Reset(document.getElementById("mycanvas"));
// Prepare data to send over server
data = 'order_by='+order_by;
RGraph.AJAX.getJSON('ajax/update-chart.php?'+data, draw_graph);
})
});
// This is the AJAX callback function. It splits up the response, converts it to numbers and then creates the chart.
function draw_graph(json)
{
// Set the JSON on the window object so that the button below can show it to the user.
//window.__json__ = json;
//$p(window.__json__);
// Reset the canvas
RGraph.Reset(document.getElementById("mycanvas"));
// Now draw the chart
var bar = new RGraph.Bar({
id: 'mycanvas',
data: json.data,
options: {
labels: json.labels,
gutter: {
left: 50
}
}
}).draw()
}
</script>
</head>
<body>
<canvas id="mycanvas" width="600" height="250">[No canvas support]</canvas>
<br />
<input type="button" id="btnstats" value="Order By Stats" data-order="statistics" />
</body>
</html>
update-chart.php:
<?php
require_once '../includes/db-config.php';
/*
echo "<pre>";
print_r($_GET);
echo "<pre>";
*/
// Order by day
if(isset($_GET['order_by']) && $_GET['order_by'] == "statistics")
{
$order_by = $_GET['order_by'];
$query = "SELECT * FROM `tb_daily_statistics` ";
$query .= "ORDER BY " . $order_by;
$rs = mysqli_query($con, $query);
$labels = array();
$data = array();
while($row = mysqli_fetch_array($rs))
{
$labels[] = $row['day'];
$data[] = $row['statistics'];
}
// Now you can aggregate all the data into one string
$data_string = "[" . implode(", ", $data) . "]";
$labels_string = "['" . implode("', '", $labels) . "']";
echo json_encode(array('data' => $data_string, 'labels' => $labels_string));
}
?>
The response from server is fine. Here's what I am receiving:
{"data":"[64, 75, 84, 94, 95, 98, 124]","labels":"['Wed', 'Fri', 'Sun', 'Thu', 'Tue', 'Sat', 'Mon']"
}
What could be the issue?
The response from the server is not formatted in correct way that RGraph understands. It's
{"data":"[64, 75, 84, 94, 95, 98, 124]","labels":"['Wed', 'Fri', 'Sun', 'Thu', 'Tue', 'Sat', 'Mon']"
}
If you do
window.__json__ = json;
$p(window.__json__);
in your draw_graph(json) function, then response from server will be
Object {
data => [64, 75, 84, 94, 95, 98, 124] (string, 29)
labels => ['Wed', 'Fri', 'Sun', 'Thu', 'Tue', 'Sat', 'Mon'] (string, 49)
}
which is wrong. Rather it should be
Object {
data => Object {
0 => 64 (number)
1 => 75 (number)
2 => 84 (number)
3 => 94 (number)
4 => 95 (number)
5 => 98 (number)
6 => 124 (number)
}
labels => Object {
0 => Wed (string, 3)
1 => Fri (string, 3)
2 => Sun (string, 3)
3 => Thu (string, 3)
4 => Tue (string, 3)
5 => Sat (string, 3)
6 => Mon (string, 3)
}
}
To fix your issue, change few lines of code in update-chart.php as
From
$data[] = $row['statistics'];
to
$data[] = (int) $row['statistics'];
Remove following lines:
// Now you can aggregate all the data into one string
$data_string = "[" . implode(", ", $data) . "]";
$labels_string = "['" . implode("', '", $labels) . "']";
From
echo json_encode(array('data ' => $data_string , 'labels' => $labels_string));
to
echo json_encode(array('data' => $data, 'labels' => $labels));
Related
I have a controller function where it gets my json data for my bar graph
The json code from controller is
{"xkey":[["0","Sun"],["1","Mon"],["2","Tue"],["3","Wed"],["4","Thu"],["5","Fri"],["6","Sat"]],"user":[[2,"1"],[3,"1"]]}
Question from the controller function how am I able to pass the
json['xkey'] and json['user'] to my script
I have looked at Morris Js and Codeigniter pass data from a controller but not work for me.
Here is what I have tried
<script type="text/javascript">
$( document ).ready(function() {
$('#range').on('click', function(e) {
e.preventDefault();
$.ajax({
type: 'get',
url: "<?php echo base_url('admin/dashboard/chart/chart_data');?>/" + $( "#range" ).val(),
dataType: 'json',
success: function(json) {
if (typeof Morris != 'undefined') {
Morris.Bar({
element: 'bar-example',
resize: true,
stacked: false,
xLabelAngle: 50,
grid: true,
gridTextSize: 10,
data: [{m: json['xkey'] a: json['user']}],
xkey: 'm',
ykeys: ['a'],
labels: ['Users']
});
}
}
});
});
});
</script>
Controller
<?php
class Chart extends MX_Controller {
public function index() {
return $this->load->view('template/dashboard/chart_view');
}
public function chart_data() {
$json = array();
$json['xkey'] = array();
$json['user'] = array();
$uri_segment = $this->uri->segment(5);
if (isset($uri_segment)) {
$range = $uri_segment;
} else {
$range = 'month';
}
switch ($range) {
case "week":
$results = $this->getUserTotalByWeek();
foreach ($results as $key => $value) {
$json['user'][] = array($key, $value['total']);
}
$date_start = strtotime('-' . date('w') . ' days');
for ($i = 0; $i < 7; $i++) {
$date = date('Y-m-d', $date_start + ($i * 86400));
$json['xkey'][] = array(date('w', strtotime($date)), date('D', strtotime($date)));
}
break;
default:
echo "Your favorite color is neither red, nor green!";
}
$this->output->set_header('Content-Type: application/json; charset=utf-8');
$this->output->set_output(json_encode($json));
}
public function getUserTotalByWeek() {
$user_data = array();
$date_start = strtotime('-' . date('w') . ' days');
for ($i = 0; $i < 7; $i++) {
$date = date('Y-m-d', $date_start + ($i * 86400));
$customer_data[date('w', strtotime($date))] = array(
'day' => date('D', strtotime($date)),
'total' => 0
);
}
$this->db->select('COUNT(*) AS total, date_reg');
$this->db->from('user');
$this->db->where('date_reg >=', date('Y-m-d', $date_start));
$this->db->group_by('DAYNAME(date_reg)');
$query = $this->db->get();
foreach ($query->result_array() as $result) {
$user_data[date('w', strtotime($result['date_reg']))] = array(
'day' => date('D', strtotime($result['date_reg'])),
'total' => $result['total']
);
}
return $user_data;
}
}
* In javascript part i got the dates that are booked by user on dates, i n calendar i marked that dates are unavilable, but i want to show user info on that dates
<script type="text/javascript">
// Add New Dates and Block Out Booked Days Below
/*var unavailableDates1 = ["20-5-2016", "21-5-2016", "22-5-2016", "23-5-2016", "5-6-2016", "7-6-2016", "8-6-2016",
"15-6-2016", "16-6-2016", "25-6-2016", "26-6-2016", "27-6-2016", "28-6-2016", "14-2-2016",
"15-7-2016", "16-7-2016", "17-7-2016", "18-7-2016", "19-7-2016","20-7-2016","21-7-2016",
]; */
var unavailableDates = <?php echo json_encode($arr2); ?>;
var unavaila = <?php echo json_encode($e); ?>;
document.write(unavailableDates);
function unavailable(date) {
dmy = date.getDate() + "-" + (date.getMonth() + 1 ) + "-" + date.getFullYear();
if($.inArray(dmy, unavailableDates) == -1) {
return [true, ""];
}else {
return [false, "", unavaila];
}
}
$(function() {
$("#Datepicker1").datepicker({
numberOfMonths:3,
beforeShowDay: unavailable
});
});
</script>
*
and my php code is getting the dates from database in between start to end m, and showing calendar booked, how to show info on that
<?php
include 'dbconfig.php';
$query_getaway = "SELECT * FROM getaway_table; ";
$result_getaway = $db->query($query_getaway);
$category = mysqli_real_escape_string($db, filter_input(INPUT_POST, 'category')) .'<br>';
$resort = mysqli_real_escape_string($db, filter_input(INPUT_POST, 'resorts')) .'<br>';
if( $category != 0 ){
$query = "SELECT * FROM booking_request where room_id = '$resort' '<br>' ";
$result = $db->query($query);
if( $result -> num_rows > 0 ) {
while( $row = $result-> fetch_assoc() )
{
$name = $row['getaway_name']." <br>";
$start = $row['check_in_date']." <br>";
$end = $row['check_out_date']." <br>";
$guest_n[]= $row['guest_name'];
$guest_number[]= $row['guest_phone'];
$arr1 = range(strtotime($row['check_in_date']),strtotime($row['check_out_date']), "86400");
array_walk_recursive($arr1, function(&$element) { $element = date("j-n-Y", $element); });
foreach ($arr1 as $value)
{
$arr2[]= $value;
}
$arrt= (array_merge($guest_n, $guest_number));
//print_r($arrt);
foreach($arrt as $val)
{
echo $arr_val[]=$val;
}
$arr[]= $value;
}
}
else { echo "select" ;}
?>
how to get the result to show user details on mousehover on dates from db.
I have looked through many posts and tried their suggestions. A new problem arises each time though.
Objective: To create a Google line chart taking data from MYSQL table and encoding it in JSON. From there, I attempt to use an html file to display the chart.
someFile.php:
<?php
//connect to the database
$username = ...;
$password = ...;
$hostname = ...;
$database = ...;
$conn = mysqli_connect($hostname, $username)
or die("Unable to connect to MySQL");
echo "Connected to MySQL<br>";
//Select database
$db_found = mysqli_select_db($conn,$database);
if($db_found) {
print "Database Found<br><br>";
}
else{
print "Database NOT Found<br>";
}
$sql = mysqli_query($conn, 'SELECT * FROM Travel_Test');
if (!$sql) {
die("Error running $sql: " . mysql_error());
}
$results = array(
'cols' => array (
array('label' => 'travel_time_date', 'type' => 'datetime'),
array('label' => 'travel_time_duration', 'type' => 'number')
),
'rows' => array()
);
while($row = mysqli_fetch_assoc($sql))
{
//date assumes "yyyy - mm -- dd" format
$dateArr = explode('-', $row['travel_time_date']);
$year = (int) $dateArr[0];
$month = (int) $dateArr[1]; //subtract 1 to make compatible with javascript months
$day = (int) $dateArr[2];
//time assumes "hh:mm:ss" format
$timeArr = explode(':', $row['travel_time_timestamp']);
$hour = (int) $timeArr[0];
$minute = (int) $timeArr[1];
$second = (int) $timeArr[2];
$results['rows'][] = array('c' => array(
array('v' => "travel_time_date($year, $month, $day, $hour, $minute, $second)"),
array('v' => $row['travel_time_duration'])
));
}
$json = json_encode($results, JSON_NUMERIC_CHECK );
echo $json;
//header("Access-Control-Allow-Origin: *");
?>
JSON output:
{"cols":[{"label":"travel_time_date","type":"datetime"},
{"label":"travel_time_duration","type":"number"}],
"rows":[{"c":
[{"v":"travel_time_date(2014, 2, 1, 1, 30, 30)"},{"v":55}]},{"c":
[{"v":"travel_time_date(2014, 2, 1, 2, 30, 30)"},{"v":80}]},{"c":
[{"v":"travel_time_date(2014, 2, 1, 3, 30, 30)"},{"v":60}]},{"c":
[{"v":"travel_time_date(2014, 2, 1, 4, 30, 30)"},{"v":120}]}]}
anotherFile.html:
<html>
<head>
<!--Load the AJAX API-->
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script type="text/javascript">
google.load('visualization', '1', {'packages':['corechart']});
// Set a callback to run when the Google Visualization API is loaded.
google.setOnLoadCallback(drawChart);
function drawChart() {
var jsonData = $.ajax({
url: "http:///Volumes/OS%20X%20Mountain%20Lion/Applications/XAMPP/xamppfiles/htdocs/traveltrak/travelGraphData.php",
dataType:"json",
async: false
}).responseText;
//success: function (jsonData) {
//Create data table out of JSON data loaded from server
var data = new google.visualization.DataTable(jsonData);
// Instantiate and draw our chart, passing in some options.
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, {width: 400, height: 240});
//}
//});
}
</script>
</head>
<body>
<div id="chart_div"></div>
</body>
</html>
When I tried to preview the page, I checked the developer's console. It states no issues. The error is when the page says: Table has no columns. Any suggestions from here please?
Your dates are not input correctly; the format is 'Date(year, month, day, hours, minutes, seconds)'. You need to replace "travel_time_date" with "Date":
$results['rows'][] = array('c' => array(
array('v' => "Date($year, $month, $day, $hour, $minute, $second)"),
array('v' => $row['travel_time_duration'])
));
Working on a line chart in google chart. Having the issue that I cant show the title of the measurement as label. I am further going to get different measurements, right now I can only show one measurement at a time.
Here is the sql query and output in database:
This is the visualization, as you can see I want the routine.value to show the title: T_Badende_per_Time:
Code:
<?php
$con=mysql_connect("localhost","root","") or die("Failed to connect with database!!!!");
mysql_select_db("nih_bw", $con);
$sth = mysql_query("Select measurements.title, routines.value, routines.date, routines.time from routines, measure_routine, measurements Where routines.id=measure_routine.routine_id AND measure_routine.measure_id=measurements.id AND measurements.title='T_Badende_per_Time' order by routines.date, routines.time;");
$rows = array();
//flag is not needed
$flag = true;
$table = array();
$table['cols'] = array(
array('label' => 'routines.date' & 'routines.time', 'type' => 'datetime'),
array('label' => 'routines.value', 'type' => 'number'),
);
$rows = array();
while($r = mysql_fetch_assoc($sth)) {
$temp = array();
// assumes dates are in the format "yyyy-MM-dd"
$dateString = $r['date'];
$dateArray = explode('-', $dateString);
$year = $dateArray[0];
$month = $dateArray[1] - 1; // subtract 1 to convert to javascript's 0-indexed months
$day = $dateArray[2];
// assumes time is in the format "hh:mm:ss"
$timeString = $r['time'];
$timeArray = explode(':', $timeString);
$hours = $timeArray[0];
$minutes = $timeArray[1];
$seconds = $timeArray[2];
$temp = array();
$temp[] = array('v' => "Date($year, $month, $day, $hours, $minutes, $seconds)");
$temp[] = array('v' => (string) $r['value']);
$rows[] = array('c' => $temp);
}
$table['rows'] = $rows;
$jsonTable = json_encode($table);
echo $jsonTable;
?>
<html>
<head>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = new google.visualization.DataTable(<?=$jsonTable?>);
var options = {
/*width: 900, height: 900, */
title: 'Visualization',
curveType: 'function',
legend: { position: 'bottom' },
pointSize: 5,
vAxis: {title: "Values", titleTextStyle: {italic: false}},
hAxis: {title: "Time", titleTextStyle: {italic: false}},
explorer: {
actions: ['dragToZoom', 'rightClickToReset'],
axis: 'vertical'}
};
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
</script>
</head>
<body>
<div id="chart_div" style="width: 900px; height: 500px;"></div>
</body>
</html>
If you want one line per measurement type, you need to pivot your data by measurements.title. MySQL does not support the PIVOT statement, so you have to fake it like this:
SELECT
routines.data,
routines.time,
SUM(IF(measurements.title = 'T_Badende_per_Time', , 0)) CAST(REPLACE(measurements.value, ',', '.') AS DECIMAL(18, 2)) as T_Badende_per_Time,
SUM(IF(measurements.title = 'measure_2', CAST(REPLACE(measurements.value, ',', '.') AS DECIMAL(18, 2)), 0)) as measure_2,
SUM(IF(measurements.title = 'measure_3', CAST(REPLACE(measurements.value, ',', '.') AS DECIMAL(18, 2)), 0)) as measure_3
etc...
FROM
routines
INNER JOIN measure_routine ON routines.id = measure_routine.routine_id
INNER JOIN measurements ON measure_routine.measure_id = measurements.id
WHERE
<conditions>
GROUP BY routines.date, routines.time
ORDER BY routines.date, routines.time
Then in PHP, create one column for each measurement type:
$table['cols'] = array(
array('label' => 'routines.date' & 'routines.time', 'type' => 'datetime'),
array('label' => 'T_Badende_per_Time', 'type' => 'number'),
array('label' => 'measure_2', 'type' => 'number'),
array('label' => 'measure_3', 'type' => 'number')
// etc
);
$rows = array();
while($r = mysql_fetch_assoc($sth)) {
$temp = array();
// assumes dates are in the format "yyyy-MM-dd"
$dateString = $r['date'];
$dateArray = explode('-', $dateString);
$year = $dateArray[0];
$month = $dateArray[1] - 1; // subtract 1 to convert to javascript's 0-indexed months
$day = $dateArray[2];
// assumes time is in the format "hh:mm:ss"
$timeString = $r['time'];
$timeArray = explode(':', $timeString);
$hours = $timeArray[0];
$minutes = $timeArray[1];
$seconds = $timeArray[2];
$temp = array();
$temp[] = array('v' => "Date($year, $month, $day, $hours, $minutes, $seconds)");
$temp[] = array('v' => (string) $r['T_Badende_per_Time']);
$temp[] = array('v' => (string) $r['measure_2']);
$temp[] = array('v' => (string) $r['measure_3']);
// etc..
$rows[] = array('c' => $temp);
}
Well, you need to set the vAxis.title. You already set it in your line 73 (vAxis: {title: "Values"}) but it needs to be set to a variable from PHP:
[...]
$vAxis = false;
while($r = mysql_fetch_assoc($sth)) {
// this will overwrite itself, it looks to me that in your case it doesn't matter
$vAxis = $r["title"];
[...]
and then output it
vAxis: {title: "<?=$vAxis ?: "default title"; ?>"}
i have some JS Code for displaying graph data:
series: [{
name: 'Year 1800',
data: [107, 31, 635, 203, 2]
}, {
name: 'Year 1900',
data: [133, 156, 947, 408, 6]
}, {
name: 'Year 2008',
data: [973, 914, 4054, 732, 34]
}]
i need to get the data to display in a while loop in PHP. I have tried this:
<?php
$sql="SELECT *, COUNT(category) AS my_groupcount from tickets where deleted = '' and DAY(datetime) = '".$day."' and MONTH(datetime) = '".$month."' and YEAR(datetime) = '".$year."' group by category order by datetime ASC ";
$rs=mysql_query($sql,$conn);
while($result=mysql_fetch_array($rs))
{
echo "name: 'Cat ".$result["category"]."',";
echo "data: [".$result["my_groupcount"]."]";
echo "}, {";
}
?>
i need to group the category column in the tickets table and display the graphs for each category but its not working - i think its because in the while loop its ending with }, { but i need it to end with }]
how can i get round this - the amount of category items in the tickets table is changing all the time as users are able to add/delete categories.
Why not do it like this:
<?php
$sql = "[.. SQL Statement ..]";
$rs = mysql_query($sql, $conn);
$json = array();
while($result = mysql_fetch_array($rs)) {
$json[] = array(
'name' => 'Cat '. $result['category'],
// This does assume that my_groupcount is an array with numbers
// i.e. array(1, 34, 54, 345)
// If not, you'll have to make it an array by doing:
// explode(', ', $result['my_groupcount'])
// This however does assume that the numbers are in
// the "12, 23" format
'data' => $result['my_groupcount'],
);
}
echo json_encode($json);
<?php
$sql="SELECT *, COUNT(category) AS my_groupcount from tickets where deleted = '' and DAY(datetime) = '".$day."' and MONTH(datetime) = '".$month."' and YEAR(datetime) = '".$year."' group by category order by datetime ASC ";
$rs=mysql_query($sql,$conn);
$first = true;
echo 'series: [{';
while($result=mysql_fetch_array($rs))
{
if(!$first) {
echo "}, {";
} else {
$first = false;
}
echo "name: 'Cat ".$result["category"]."',";
echo "data: [".$result["my_groupcount"]."]";
}
echo '}]';
?>
Bookend the brackets instead, though it's better to build it then echo it so you can get rid of the last comma.
$string = '';
while($result=mysql_fetch_array($rs))
{
string.= "{";
string.= "name: 'Cat ".$result["category"]."',";
string.= "data: [".$result["my_groupcount"]."]";
string.= "},";
}
$string = trim($string,','); // gets rid of that last comma
echo "[$string]";
try
$sql="SELECT *, COUNT(category) AS my_groupcount from tickets where deleted = '' and DAY(datetime) = '".$day."' and MONTH(datetime) = '".$month."' and YEAR(datetime) = '".$year."' group by category order by datetime ASC ";
$rs=mysql_query($sql,$conn);
$output = '[';
while($result=mysql_fetch_array($rs))
{
$output .= "name: 'Cat ".$result["category"]."',";
$output .= "data: [".$result["my_groupcount"]."]";
$output .= "}, {";
}
$output = substr($output, 0, -3) . ']';
but as rich said you really shouldn't be writing JSON by hand.