Google Vis annotated timeline from SQL database using PHP JSON issue - php
I am trying to create a simple annotated timeline from a PostgreSQL database using a server side PHP script to access the data from the database, then a JavaScript client side script to display the graph. Basically pretty straightforward stuff there. Now as you may guess, nothing is showing up when I visit the page.
So here is where I've gotten: When I looked at my apache log files, I can see that my PHP script is parsing correctly, and when I use the hyperlink (including all the extra goodies that my JavaScript added to properly ask PHP for what it wants from the database) I can see the response in the correct Google format. At least I think. I KINDA think that the issue may be that the response from my PHP function is actually in an incorrect syntax for the Google annotated timeline object, but I cant find enough documentation to prove that is true or not.
Here is a truncated version of what my PHP function spits out:
Google.visualization.Query.setResponse({version:'0.5',reqId:'0',status:'ok',table:{cols: [{id:'date',label:"date",type:'datetime'},{id:'temp',label:"temp",type:'number'}],
rows: [{c:[{v:new Date(2011,2,22,13,47,26),f:"03\/22\/2011 01:47pm"},{v:132.8,f:"133"}]},{c:[{v:new Date(2011,2,22,13,48,57),f:"03\/22\/2011 01:48pm"},{v:136.8,f:"137"}]},
{c:[{v:new Date(2011,2,22,13,56,49),f:"03\/22\/2011 01:56pm"},{v:132.8,f:"133"}]},{c:[{v:new Date(2011,2,22,13,58,42),f:"03\/22\/2011 01:58pm"},{v:128.8,f:"129"}]},
{c:[{v:new Date(2011,2,22,14,1,26),f:"03\/22\/2011 02:01pm"},{v:124.8,f:"125"}]},{c:[{v:new Date(2011,2,22,14,4,19),f:"03\/22\/2011 02:04pm"},{v:128.8,f:"129"}]},{c:[{v:new Date(2011,2,22,14,5,51),f:"03\/22\/2011 02:05pm"},{v:132.8,f:"133"}]},
And it goes on of course, but I figured I would give you an idea of what I was seeing, not put you to sleep with a complete dump.
Now I know by putting in document.write("got here"); kinda tags into my JavaScript, I can tell that the program does finish, and doesn't throw any crazy errors due to silly oversights on my part...(Opening mouth in preparation to insert foot)... However somehow from what I have read elsewhere it this query response looks mal-formatted somehow (I did change the formatting and insert spacing for readability in this post, so if you see something wrong with the spacing, it was more than likely me). I will include both my PHP and my JavaScript code at the bottom of this post. If anyone sees anything glaring that I missed, or have any insights into what could be the problem, I would really appreciate some help with this!
Thanks in advance everyone!
JavaScript index.html
<html>
<head>
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("visualization", "1", {packages:["annotatedtimeline"]});
google.setOnLoadCallback(drawChart);
function drawChart() {
var query = new google.visualization.Query('/vis.php');
query.setQuery('SELECT date,temp FROM temp1 ORDER BY date');
query.send(function(result) {
document.write(result.getDetailedMessage());
if(result.isError()) {
alert(result.getDetailedMessage());
} else {
var data = result.getDataTable();
var chart = new google.visualization.AnnotatedTimeLine(document.getElementById('chart_div'));
chart.draw(data,{displayAnnotations: false});
}
});
}
</script>
</head>
<body>
<div id="chart_div"></div>
</body>
</html>
PHP vis.php
<?php
require_once 'MC/Google/Visualization.php';
$user = 'postgres';
$db = new PDO('pgsql:host=localhost;dbname=house',$user,'');
$vis = new MC_Google_Visualization($db,'postgres');
$vis->addEntity('temp1', array(
'fields' => array(
'date' => array('field' => 'date', 'type' => 'datetime'),
'temp' => array('field' => 'temp', 'type' => 'number')
)
));
$vis->setDefaultEntity('temp1');
$vis->handleRequest();
?>
----------------------------------------------------------------------------------------
EDIT: Functional Code Alert!
Ok, so here is where I'm at now, this code works, but of course doesnt pull anything from my database. As you can see, the formatting is exactly the same as I was getting from the PHP function above.
FUNCTIONAL CODE but not what I'm looking for
<html>
<head>
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("visualization", "1", {packages:["annotatedtimeline"]});
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = new google.visualization.DataTable(
{
cols: [{id:'date',label: 'date', type: 'datetime'},
{id:'level',label: 'level', type: 'number'}],
rows: [
{c:[{v: new Date(2011,2,24,6,52,26),f:"03\/24\/2011 06:52am"}, {v:91.4,f:"91"} ]},
{c:[{v: new Date(2011,2,25,7,35,20),f:"03\/25\/2011 07:35am"}, {v:89.4,f:"89"} ]},
{c:[{v: new Date(2011,2,26,1,2,15),f:"03\/26\/2011 01:02am"}, {v:85.4,f:"85"} ]},
{c:[{v: new Date(2011,2,27,0,27,13),f:"03\/27\/2011 12:27am"}, {v:85.4,f:"85"} ]}]
}, 0.6);
var annotatedtimeline = new google.visualization.AnnotatedTimeLine(document.getElementById('chart_div'));
annotatedtimeline.draw(data, {'displayAnnotations': true});
}
</script>
</head>
<body>
<div id='chart_div' style="width:400; height:250"></div>
</body>
</html>
To me this indicates that there must be one parsing step I'm missing. Like I said before, from all the troubleshooting I know how to do with the google code, I got that the row and col sizes were correct in the response from the database after calling the var data = result.getDataTable() function. So there must be one further modification I have to do to the variable data before I try to use it in my annotatedtimeline.draw(data, {OPTIONS}) call.... Any ideas?
** ------------------------------------------------------------------------- **
EDIT 2: NON WORKING CODE
This is the non working code. The only real difference is the source of the data. And since I know that the database is responding, I am confused by the fact that its still showing a blank page.
<html>
<head>
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load('visualization', '1', {packages: ['annotatedtimeline']});
function drawChart() {
//Tell Google Visualization where your script is
var query = new google.visualization.Query('/vis.php');
query.setQuery('SELECT date,level FROM tank1 ORDER BY date');
query.send(function(result) {
//if there is an error
document.write(result.getDetailedMessage());
if(result.isError()) {
alert(result.getDetailedMessage());
} else {
// otherwise plot the data
var data = result.getDataTable();
// Inserting a document.write(data.getNumberOfRows()) proves that the datatable is loading seemingly correctly here
var annotatedtimeline = new google.visualization.AnnotatedTimeLine(document.getElementById('chart_div'));
annotatedtimeline.draw(data, { 'displayAnnotations': false });
}
});
}
google.setOnLoadCallback(drawChart);
</script>
</head>
<body>
<div id="chart_div" style="width:400px; height:250px"></div>
</body>
</html>
I have experienced this problem before, just fix this line in NON_WORKING_CODE
query.setQuery('SELECT date,level FROM tank1 ORDER BY date');
into
query.setQuery('SELECT *');
This should work. If not, try to fix the preg_quote issue https://code.google.com/p/mc-goog-visualization/issues/detail?id=16
A look at the Google docmentation page here : http://code.google.com/apis/visualization/documentation/gallery/annotatedtimeline.html
Shows the following :
Important: To use this visualization, you must specify the height and width
of the container element explicitly on your page. So, for example:
<div id="chart_div" style="width:400; height:250"></div>.
You don't appear to do this.
EDIT : I just tried the example on that page and indeed if I remove the explicit height and width I get nothing; with the height and width the timeline displays.
In your response, the keys are not enclosed in quote, it might be the reason why the chart is not rendered
{id:'date', type:'date'}
{"id":"date", "type":"date"}
I just searched for visualization.query documentation and this live example uses a response like yours but in the response, the keys are enclosed in quote:
https://spreadsheets.google.com/tq?key=pCQbetd-CptGXxxQIG7VFIQ&pub=1
I'm not familiarized with PHP and that visualization library you use in vis.php but if you could manage to add those quotes, I'm almost sure that it will work
I'm usign a tabledate with object notation as you did but in .NET and that's the only thing I see difference
Hope it helps, I know is an old post but for people like me in the future
Related
Is there a way to make the Y-axis not adapt to the loaded tables for Google Column Charts?
I'm currently committing to an information security project where fictional data is loaded and visualized with google charts. However, with the column chart that's being loaded, the Y-axis is loaded in an unwanted manner, and i've tried multiple tests to identify where the issue is, but so far no luck. I have 3 Tables, with 2 attributes each. These tables are: 'Phishing', 'SpearPhishing', and 'RogueRouter'. They all have two columns that i want to count and present with the attribute names such as 'curious' and 'intent'. The following SQL syntax is being used: SELECT 'Phishing' as method, count(check_opened) as curious, count(clicked_link) as intent FROM Phishing UNION ALL SELECT 'Spear Phishing' as method, count(check_opened) as curious, count(clicked_link) as intent FROM SpearPhishing UNION ALL SELECT 'Rogue Router' as method, count(page_load) as curious, count(internet_intent) as intent FROM RogueRouter GROUP BY method In Phpmyadmin, when run, it displays the following: However, with the following code in my PHP file to display the data as columns: <?php $connect = mysqli_connect("localhost", "isprojectdbadmin", "isproject!23", "ISProjectDB"); $query = [THE SQL QUERY MENTIONED ABOVE] $result = mysqli_query($connect, $query); ?> <html> <head> <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script> <script type="text/javascript"> google.charts.load('current', {'packages':['bar']}); google.charts.setOnLoadCallback(drawChart); function drawChart() { var data = google.visualization.arrayToDataTable([ ['method', 'curious', 'intent'], <?php while($row = mysqli_fetch_array($result)) { echo "['".$row['method']."', '".$row['curious']."', '".$row['intent']."'], "; } ?> ]); }; var chart = new google.charts.Bar(document.getElementById('columnchart_material')); chart.draw(data, google.charts.Bar.convertOptions(options)); } </script> </head> <body> <div id="columnchart_material" style="width: 800px; height: 500px;"></div> </body> </html> It displays the following: The Y-axis isn't gradient in its values where it initiates from 0 to 40, and i have no idea where the issue resides. Any help is greatly appreciated, or even some slight recommendations would be beneficial since i'm feeling a bit stuck. In addition, as i've mentioned in the beginning of this post, there's no malicious activities behind this project what so ever, quite the opposite.
I solved it by my self! The issue was the PHP syntax for reading the rows. The following row: echo "['".$row['method']."', '".$row['curious']."', '".$row['intent']."'], "; was replaced by: echo "['".$row["method"]."', ".$row["curious"].", ".$row["intent"].", ],";
ajax call PHP script with jQuery showing status
I am learning jQuery recently and trying to do an ajax call to a very simple PHP script, which just output 1 json text. When I just have 1 echo statement in my script, I was able to get the call working. I then tried to mimic a complex script by echo 4 json after sleep for 3 seconds each time, but this time I could not be able to make it work. Here is my index.html: <!DOCTYPE html> <html> <head> <title>ajax</title> <script src="jquery.js"></script> <script src="app.js"></script> </head> <body> <div id="loading"></div> </body> </html> Here is my app.js: $(function() { $('#loading').html('<img src="http://preloaders.net/preloaders/287/Filling%20broken%20ring.gif"> loading...'); var req = $.ajax({ url: "x.php", dataType: "json" }); req.done(function(data) { setTimeout(function () { $('#loading').html(data.text); }, 1000); }); }); Here is my x.php: <?php sleep(3); echo json_encode(array("text"=>"you got me1")); sleep(3); echo json_encode(array("text"=>"you got me2")); sleep(3); echo json_encode(array("text"=>"you got me3")); sleep(3); echo json_encode(array("text"=>"you got me4")); ?> My purpose is trying to show 'you got me1', 'you got me2'...one by one after few seconds. Could anyone please help and tell me where I am doing wrong? Thanks a lot in advance.
JSON must be a monolithic string. You cannot output four separate JSON constructs in a single response. e.g. $x = array('foo'); $y = array('bar'); $z = array('baz'); echo json_encode($x); echo json_encode($y); echo json_encode($z); Will send ['foo']['bar']['baz'] across the wire. That is NOT syntactically valid JSON and will simplyl produce a parse error on the receiving end. If you want to send 4 different chunks of data over as JSON, you'll either have to do four separate requests, or embed each response in a sub-array, e.g. $response = array( 'x' => array('foo'), 'y' => array('bar'), 'z' => array('baz') ); echo json_encode($response); Remember that JSON is (almost exactly) the same as the "right-hand side" of a variable assignment in Javascript: var foo = XXX; ^^^---json goes here If you want your output to be accepted, you have to generate something that you could literally paste into that assignment operation and have the JS engine parse/execute it properly, so var response = ['foo']['bar']['baz']; // syntax error var response = [['foo'],['bar'],['baz']]; // syntactically valid
Google Charts: I get json output but still no graph
I've finally managed to get my php code working for my google charts column chart. When I run my php I get the following output {"cols":[{"id":"id","label":"second","type":"number"}, {"id":"threads","label":"threads","type":"number"}],"rows":[{"c":[{"v":1},{"v":1411}]}, {"c":[{"v":2},{"v":1411}]},{"c":[{"v":3},{"v":1409}]},{"c":[{"v":4},{"v":1408}]},{"c": [{"v":5},{"v":1407}]},{"c":[{"v":6},{"v":1408}]},{"c":[{"v":7},{"v":1408}]},{"c":[{"v":8}, {"v":1410}]},{"c":[{"v":9},{"v":1410}]},{"c":[{"v":10},{"v":1412}]},{"c":[{"v":11}, {"v":1415}]}]} Using this other post as a guide, here, I believe that my output is correct. However I am not entirely sure since my column chart is still not being displayed, on my webapp. This is the code I am using to show my chart <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script> <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 json = $.ajax({ url: 'databaseQuery.php', dataType: 'json', async: false }).responseText; var data = new google.visualization.DataTable(json); var options = { title: 'Active Threads', is3D: 'false', width: 800, height: 600 }; var chart = new google.visualization.ColumnChart(document.getElementById('chart_div')); chart.draw(data, options); } </script> I have a table the displays fine, which is also getting its data from a mysql server and shows the same data the graph should just in a table. I have been going over this code and can't seem to find the mistake. Can anyone point the mistake(s) out or suggest a better way of doing it? If the error is in my JSON, what should it look like for it to work properly? Also the table from my database looks like this id threads 1 1411 2 1411 3 1409 4 1408 5 1407 6 1408 7 1408 8 1410 9 1410 10 1412 11 1415
There's nothing wrong with your code as shown. I've just created a test page basically cut and paste from your markup and it worked perfectly. I'd suggest you try replacing the ajax call with inline json initialisation and see if that works for you. var json = { "cols":[ {"id":"id","label":"second", "type":"number"}, {"id":"threads","label":"threads","type":"number"} ], "rows":[ {"c":[{"v":1},{"v":1411}]}, {"c":[{"v":2},{"v":1411}]}, {"c":[{"v":3},{"v":1409}]}, {"c":[{"v":4},{"v":1408}]}, {"c":[{"v":5},{"v":1407}]}, {"c":[{"v":6},{"v":1408}]}, {"c":[{"v":7},{"v":1408}]}, {"c":[{"v":8},{"v":1410}]}, {"c":[{"v":9},{"v":1410}]}, {"c":[{"v":10},{"v":1412}]}, {"c":[{"v":11},{"v":1415}]} ] }; var data = new google.visualization.DataTable(json); If that works, then you'll at least have confirmed the problem is somewhere in the ajax call or the php backend. One other thought: this may seem obvious but it's worth double checking that you do have an element on your page with the chart_div id? <div id='chart_div'></div>
Displaying values from a database (using mySQL) on a Flot graph
I'm trying to read in values from a db using php (mySQL) then have them show on a graph in flot. I know the values are read in correctly and I'm not getting any errors but the graph won't show. Little help? Thanks in advance. <?php while ($row = mysql_fetch_array($result, MYSQL_NUM)) { $graphdata[] = array( (int)$row[0], (int)$row[1] ); } ?> ///// <div id="placeholder" style="width:600px;height:300px"></div> <script language="javascript" type="text/javascript"> var dataset1 = <?php echo json_encode($graphdata);?>; var data = [ { label: "Random Values", data: dataset1 } ]; var plotarea = $("#placeholder"); $.plot( plotarea , data); </script>
The contents of your pastebin show that the JSON string you're outputting is invalid JSON. var data = [{ label: "Random Values",data: dataset1}]; will validate if it's changed to: var data = [{"label": "Random Values","data": "dataset1"}] That's just an example, but I suspect that Flot is looking for a slightly different format, so you'll have to verify exactly what they're looking for against their documentation. I'm going through the same exercise right now with FusionCharts, so I'm feeling your pain. jsonlint.com is your friend on this one, output your JSON and verify it frequently. I'd also recommend that to initially get it working, start with just a string of JSON (even one that you copy from their examples) that you put right in your code. Get the chart working first, then work on getting your PHP to duplicate the example JSON string separately.
Try delaying creating the graph until the DOM is loaded: jQuery(document).ready(function ($){ var plotarea = $("#placeholder"); $.plot( plotarea , data); });
Simple Javascript MYSQL checking function
I'm not very skilled in web developing by the moment but i've managed to create a web application with PHP that queries a MYSQL Database and shows data in HTML. I would like to check if the table has changed using a timestamp field that I already created and that updates on every insertion. Comparing two timestamps (the previous and the current) is the key, but I don't handle javascript that much. How can I pass a parameter to my hastablechanged.php file (the previous timestamp) and simply return a flag (1: changed, 0: not changed) to javascript? and... how would be a basic javascript function to run a timer and call hastablechanged.php posting old_timestamp and receiving the flag and then update the div? I've been googling but the solutions I have found are very complex and I know i just need a javascript function that I don't find out how to write. This is hastablechanged.php: <?php include 'config.php'; include 'opendb.php'; $table = "data_table"; $query_timestamp = "select timestamp from {$table} where id = 0;"; $timestamp = mysql_query("{$query_timestamp}"); if (!$timestamp) { die("query failed"); } $row_timestamp = mysql_fetch_array($timestamp); echo $row_timestamp['timestamp']; ?> And this is my index.php <!DOCTYPE HTML PUBLIC> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta http-equiv="Content-Style-Type" content="text/css"> <title>Data values</title> </head> <body> <div id=data> <? include("table.php");?> </div> </body> </html> where "table.php" is the php code that selects the data and displays it drawing a html table. I would thank a lot any help, as I'm stuck in this issue for finishing my degree project
You need Ajax and setInterval. Here is how SetInterval works http://www.elated.com/articles/javascript-timers-with-settimeout-and-setinterval/ SetInterval basically just tells the browser to call a javascript function every x milliseconds. Here is a few Ajax Examples http://www.w3schools.com/Ajax/ajax_examples.asp Ajax is basically a way for javascript to request a page and get its contents without reloading the page. In the example below it tries to create an xmlhttprequest for all the browsers (sadly it's done like this) and then sends in the request. We define state_change as the function to be called when we get a reply back. In this example it just takes the response and displays it, but you can do whatever you want with that. Below is a modified example. It should work. <html><head> <script type="text/javascript"> var xmlhttp; function loadPage() { xmlhttp=null; if (window.XMLHttpRequest) {// code for IE7, Firefox, Opera, etc. xmlhttp=new XMLHttpRequest(); } else if (window.ActiveXObject) {// code for IE6, IE5 xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); } if (xmlhttp!=null) { xmlhttp.onreadystatechange=state_Change; xmlhttp.open("GET","hastablechanged.php?tablename=awesometable",true); xmlhttp.send(null); } else { alert("Your browser does not support XMLHTTP."); } } function state_Change() { if (xmlhttp.readyState==4) {// 4 = "loaded" if (xmlhttp.status==200) {// 200 = "OK" document.getElementById('A1').innerHTML=xmlhttp.responseText; } else { alert("Problem retrieving ata:" + xmlhttp.statusText); } } } </script> </head> <body onLoad="setInterval('loadPage()', 10000)"> <p><b>Status:</b> <span id="A1"></span> </p> <button onclick="loadPage()">Check Updates</button> </body> </html>
Just to be clear: you don't have to use ajax. Just reloading the page on regular interval will give you what you want. BUT if you want the application to be smooth - then you'll have to dig into AJAX as outlined in the other answers. -CF
I finally figured out how to do it. Posting it so it can be useful for anybody. It's a combination of php and javacript where: php file return_timestamp.php simply returns the timestamp of a row with ID=0 (no real ID, it simply updates its timestamp in each insertion with a trigger) javascript compares the received timestamp with the one previously received (the very first one is set to 0 so it updates the div in the beginning) so: javascript code which is the important thing (i assume you guys can code php retrieving data from mysql): <script type="text/javascript"> $(document).ready(function() { $timestamp1='0'; var refreshId = setInterval(function() { $.get(('return_timestamp.php', function(data) { $timestamp2 = data; } ) if ( $timestamp2 != $timestamp1 ) { $('#data').load('data.php'); $timestamp1 = $timestamp2; } }, 1000); }); </script> Hope it helps, and thanks as well for YOUR help!