Google Charts and JSON data - javascript

I'm not a JS guy, I working on a small interface for my weather station. I have a serverside code which generates the JSON data for the graph. It looks like this:
[
{
"temperature": "32.1",
"humidity": "91",
"battery": "100",
"time": "2016-02-21 15:28:56"
},
{
"temperature": "32.1",
"humidity": "99.3",
"battery": "100",
"time": "2016-02-21 15:28:47"
},
{
"temperature": "22.2",
"humidity": "70.2",
"battery": "88.2",
"time": "2016-02-21 15:28:19"
},
{
"temperature": "21.2",
"humidity": "88.1",
"battery": "90.4",
"time": "2016-02-21 15:28:22"
}
]
How can I feed this data into a Line chart using Google's Chart API? I have tried using the example but it does not work. (https://developers.google.com/chart/interactive/docs/gallery/linechart)

First define your array in the format which google charts requires:
$resultsarray = array(
'cols' => array(
array('label' => 'temperature', 'type' => 'number'),
array('label' => 'humidity', 'type' => 'number'),
array('label' => 'battery', 'type' => 'number'),
array('label' => 'time', 'type' => 'date'),
),
'rows' => array()
);
Then add the data to your array:
$resultsarray['rows'][] = array('c' => array( array('v'=> 'tempvalue'), array('v'=>'humidityval'), array('v'=>'batteryval'),array('v'=>'timeval')));
Encode as JSON and write to a file:
$fp = fopen('data.json', 'w');
//JSON encode and write array to file
fwrite($fp, json_encode($resultsarray, JSON_NUMERIC_CHECK));
fclose($fp);
Then in your JavaScript you need: (as per Google Example)
function drawChart() {
var jsonData = $.ajax({
url: "getData.php",
dataType: "json",
async: false
}).responseText;
// Create our data table out of JSON data loaded from server.
var data = new google.visualization.DataTable(jsonData);
Then the contents of getdata.php (as per google example)
<?php
// This is just an example of reading server side data and sending it to the client.
// It reads a json formatted text file and outputs it.
$string = file_get_contents("data.json");
echo $string;
// Instead you can query your database and parse into JSON etc etc
?>

The json isn't formatted properly. Google charts expect a specific json type for its chart. I'm assuming that your database is mysql. If not, I can always modify the following code. I have created a small library to perform these annoying tasks. So here it is :
<?php
function generate_GChart_cols($result) {
$fieldcount = mysqli_num_fields($result);
$stringVal = [253]; // MySQL field type codes -See http://php.net/manual/en/mysqli-result.fetch-field-direct.php
$numericVal = [246, 8]; // MySQL field type codes -See http://php.net/manual/en/mysqli-result.fetch-field-direct.php
$colsarray = array();
for ($i = 0; $i < $fieldcount; $i++) {
$finfo = mysqli_fetch_field_direct($result, $i);
switch ($finfo->type) {
case in_array($finfo->type, $stringVal):
$type = 'string';
break;
case in_array($finfo->type, $numericVal):
$type = 'number';
break;
default:
$type = 'string';
}
// Constructs the column array
$colsarray[] = array(
'label' => $finfo->name,
'type' => $type
);
}
return $colsarray;
}
function generate_GChart_rows($result) {
$fieldcount = mysqli_num_fields($result);
$rows = array();
while ($r = $result->fetch_row()) {
$temp = array();
for ($j = 0; $j < $fieldcount; $j++) {
$temp[] = array(
'v' => $r[$j]
);
}
$rows[] = array(
'c' => $temp
);
};
return $rows;
}
?>
A usage example would be :
<?php
header('content-type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin:*'); //Include this header to make the requests cross-origin
include 'dbconnect.php';
include 'generate_google_json.php';
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$sql = // Your query here - e.g SELECT * FROM TABLE // ;
$result = $conn->query($sql);
$table['data']['rows'] = generate_GChart_rows($result); // Call to function to generate rows
$table['data']['cols'] = generate_GChart_cols($result); // Call to function to generate columns
$conn->close(); // Close db connection
// We echo the json and enforce a numeric check on the values
echo $_GET['callback'] . '(' . json_encode($table, JSON_NUMERIC_CHECK) . ')';
?>
An example output would be :
?(
{
data:{
rows:[
{
c:[
{
v:3123600
},
{
v:3116452
}
]
}
],
cols:[
{
label:2013,
type:"number"
},
{
label:2014,
type:"number"
}
]
}
}
)
In the event where you use other types than bigint, varchart and decimal, you might wanna add more values to the $stringVal and $numericVal arrays :)
Cheers

Google charts is expecting the JSON in this format:
{
"cols": [
{"id":"","label":"temperature","pattern":"","type":"number"},
{"id":"","label":"humidity","pattern":"","type":"number"},
{"id":"","label":"battery","pattern":"","type":"number"},
{"id":"","label":"time","pattern":"","type":"date"}
],
"rows": [
{"c":[{"v":"32.1","f":null},{"v":99.3,"f":null},{"v":100,"f":null},{"v":2016-02-21 15:28:47,"f":null}]}
]
}

Related

Yii2 Kartik FileUpload : Multiupload initialPreviewConfig JSON data from controller seems doesnt work

Before all
I have model for image as simple as
return [
'id' => 'ID',
'parent_id' => 'Parent ID',
'photo' => 'Photo', <= just for filename
];
the case is
Create Parent model then save then redirect to form for uploading images related to its parent.
all uploading function work proprerly but no with delete function
This is my upload image form
echo FileInput::widget([
'model' => $photo,
'attribute' => 'photo',
'options'=>[
'accept'=>'image/*',
'multiple'=>true
],
'pluginOptions' => [
'uploadUrl' => Url::to(['/controller/upload', 'id'=> $parent->id]),
'initialPreview'=>$pre-initViews-data,
'initialPreviewAsData'=>true,
'initialCaption'=>"Foto Tersangka",
'initialPreviewConfig' => $pre-initConfigs-data,
'overwriteInitial'=>true,
//'deleteUrl'=> Url::to(['/controller/deletephoto']), <= case 2
'showPreview' => true,
'showRemove' => false,
'showUpload' => false,
'maxFileSize'=>2800
],
'pluginEvents' => [
'fileuploaded'=>"function(event, data, previewId, index){
console.log(data);
}",
]
]);
And here my controller side
$imageFile = UploadedFile::getInstance($model, 'photo');
$directory = Yii::$app->basePath. '/images/';
if ($imageFile) {
$fileName = Yii::$app->security->generateRandomString(). '.' . $imageFile->extension;
$filePath = $directory . $fileName;
if ($imageFile->saveAs($filePath) && $model->save(false)) {
$path = '/images/temp/' . $fileName;
Image::thumbnail($directory.$fileName, 120, 120)
->save(Yii::$app->basePath.$path, ['quality' => 80]);
$response = [];
$reponse['initialPreview'] = \Yii::$app->request->BaseUrl.'/images/'.$fileName;
$reponse['initialPreviewConfig']=[
'caption'=>'',
'width'=>'90px',
'key'=>$model->id,
'url'=>Url::to(['/controller/deletephoto']),
'extra'=>['id'=>$model->id]
];
echo json_encode($reponse);
}
}
And will produce JSON data like this :
{
"initialPreview": "\/web\/images\/Kl1IJOabLs5ENzzgkuW8ln_TILcDumy9.png",
"initialPreviewConfig": {
"caption": "",
"width": "90px",
"key": 38,
"url": "\/web\/index.php?r=controller%2Fdeletephoto",
"extra": {
"id": 38
}
}
}
The issue
I try different way like :
case 1 :
at form widget withoud pluginOptions => deleteUrl'=> Url::to(['/controller/deletephoto']),
upload process success, response from controller initialPreview overwriting initial as expected, but initialPreviewConfig seems doesnt fit, so delete button doesnt work/ doesnt give any process when clicked.
case 2 :
at form widget with pluginOptions => deleteUrl'=>
Url::to(['/controller/deletephoto']) , upload process as expected, but when i click delete button post action didnt parse key as below
Query string
r : controller/deletephoto
Form data
key : {empty key}
Finally
Ive spend huge amount of hours, Please review my code, is there something wrong?
a Big thanks for your help.
UPDATE ISSUE RESOLVED
after long hours finally i got the way..
replace
$response = [];
$reponse['initialPreview'] = \Yii::$app->request->BaseUrl.'/images/'.$fileName;
$reponse['initialPreviewConfig']=[
'caption'=>'',
'width'=>'90px',
'key'=>$model->id,
'url'=>Url::to(['/controller/deletephoto']),
'extra'=>['id'=>$model->id]
];
echo json_encode($reponse);
with
return Json::encode([
'initialPreview' => \Yii::$app->request->BaseUrl.'/images/'.$fileName,
'initialPreviewConfig' => [
[
'caption'=>'',
'width'=>'90px',
'key'=>$model->id,
'url'=>Url::to(['/controller/deletephoto']),
'extra'=>['id'=>$model->id]
],
],
]);
dont know why this happen,

How to create a fully AJAX based jQuery-dataTable?

the default behaviour of dataTable is good, as long as the number of rows are not 907234. I would like to use Ajax oriented working, so get 10 records per pages, etc. I know I can set AJAX source, but only once, and then paging would be futule. (how would it work, if datatable doesnt know the number of records?) not to mention the searching. So how to start?
The server side approach of Datatable is like so:
$('#dataTable').dataTable({
"sServerMethod": "GET",
"bProcessing": true,
"bServerSide": true,
"sAjaxSource": "data.php",
"aoColumns": [null, null, null, { "bSortable": false }],
"order": [[ 1, "asc" ]],
"oLanguage": {"sZeroRecords": "No Members found", "sEmptyTable": "No members to display"},
});
The backend i.e data.php should be like so:
<?php
$start = $_GET['iDisplayStart'];
$length = $_GET['iDisplayLength'];
$sSearch = $_GET['sSearch'];
$col = $_GET['iSortCol_0'];
$arr = array(1 => 'oe.org_given_id', 2 => 'usr.name');
$sort_by = $arr[$col];
$sort_type = $_REQUEST['sSortDir_0'];
$query = "SELECT usr.id,usr.name,oe.org_given_id FROM users usr JOIN organization_employees oe on usr.id=oe.employee_id WHERE oe.organization_id=".$organization_id." AND (usr.name LIKE '%".$sSearch."%' OR oe.org_given_id LIKE '%".$sSearch."%') ORDER BY ".$sort_by." ".$sort_type." LIMIT ".$start.", ".$length;
$db=new DB();
$resultSet=$db->SelectRead($query);
while($row = mysqli_fetch_assoc($resultSet))
{
$data[] = $row;
}
$counterQuery = "SELECT COUNT(usr.id) as total FROM users usr JOIN organization_employees oe on usr.id=oe.employee_id WHERE oe.organization_id=".$organization_id.";";
$countSet = $db->SelectRead($counterQuery);
$iTotal=0;
while($counterRow = mysqli_fetch_assoc($countSet))
{
$iTotal = $counterRow['total'];
}
$rec = array(
'iTotalRecords' => $iTotal,
'iTotalDisplayRecords' => $iTotal,
'aaData' => array()
);
$k=0;
if (isset($data) && is_array($data))
{
foreach ($data as $item)
{
$rec['aaData'][$k] = array(
0 => $k,
1 => $item['org_given_id'],
2 => $item['name'],
3 => "Delete"
);
$k++;
}
}
header("Content-type:application/json");
echo json_encode($rec);
?>
The parameters like:
iDisplayStart and iDisplayLength etc are default given by Datatables.
Some online working examples are:
https://coderexample.com/datatable-demo-server-side-in-phpmysql-and-ajax/
http://phpflow.com/php/datatables-example-server-side-processing-with-php/
http://phpflow.com/demo/datatable/
A github repository of my code is below with some additional features offcourse:
https://github.com/shaktiphartiyal/DataTable-Editor-Free

Fetching events from database into FullCalendar

I am trying to fetch data from a MySQL database into a calendar. (FullCalendar plugin)
I want to send the fetched data as a json feed to be displayed on the calendar.
This is my Javascript code for displaying the events:
events: {
url: 'http://localhost/Hotel/event_source.php',
error: function() {
alert('There was an error while fetching events.');
}
This is the event_source.php page where I'm fetching the data from the database:
<?php
include('hoteldb.php');
global $conn;
if($stmt = $conn->prepare("SELECT title, startDate, endDate FROM event"))
{
$stmt->execute();
$stmt->bind_result($title, $startDate, $endDate);
while ($stmt->fetch())
{
$rows[] = array('title' => $title, 'startDate' => $startDate, 'endDate' => $endDate);
}
$stmt->close();
echo json_encode($rows);
}
?>
The code should be modified as followed. The statement fetch method will return the next row and you have to catch it as follows. Also the columns are accessed as I have shown in the following code.
$rows=array();
while ($row=$stmt->fetch())
{
$rows[] = array('title' => $row['title'], 'startDate' => $row['startDate'], 'endDate' => $row['endDate']);
}
Try Below one in your while loop
'title' and 'start' must be there in event to load in calendar.
while ($stmt->fetch())
{
$rows[] = array('title' => $title, 'start' => date('Y-m-d H:i:s', strtotime($startDate)), 'end' => date('Y-m-d H:i:s', strtotime($endDate)));
}

Uncaught TypeError: Cannot read property 'length' of undefined JQUERY autocomplete

This scripts are used,
https://www.devbridge.com/sourcery/components/jquery-autocomplete/
I am using jQuery Autocomplete for searching users from my DB.
Below is controller which returns Json:
public function searchusers1() {
if ($_GET) {
$query = $this -> input -> get('query');
$searcharray = $this -> model_usermanage -> searchuser($query);
$a_json = array();
$a_json_row = array();
foreach($searcharray as $row) {
//$user_firstname = htmlentities(stripslashes($row['user_firstname']));
//$user_lastname = htmlentities(stripslashes($row['user_lastname']));
$user_email = htmlentities(stripslashes($row['user_email']));
//$a_json_row["user_firstname"] = $user_firstname;
$a_json_row["user_email"] = $user_email;
array_push($a_json, $a_json_row);
}
echo json_encode($a_json);
}
}
Below is my jQuery:
$('#reply_bcc').autocomplete({
serviceUrl: '<?php echo base_url(); ?>index.php/hi/test/searchusers1',
minChars: 3,
onSelect: function (suggestion) {
console.log('You selected: ' + suggestion.data + ', ' + suggestion.data);
}
});
Here is my JSON response:
[{"user_email":"hi#test.com"},{"user_email":"hello#au.com"},{"user_email":"testing#123.com"},]
My HTML:
<div class="col-md-10">
<input type="text" name="reply_bcc" id="reply_bcc" autocomplete="off" class="form-control">
</div>
My PROBLEM is:
I am getting below error in console and I can not see this searched values as dropdown in my html input:
Uncaught TypeError: Cannot read property 'length' of undefined
What's going wrong with this?
Thanks!
The documentation explains "Response from the server must be JSON formatted following JavaScript object:"
{
// Query is not required as of version 1.2.5
"query": "Unit",
"suggestions": [
{ "value": "United Arab Emirates", "data": "AE" },
{ "value": "United Kingdom", "data": "UK" },
{ "value": "United States", "data": "US" }
]
}
And you are just returning an array without the format value/data. You can change your format in PHP or use the "transformResult" function to create the suggestions property with your array.
You should add an object in your PHP code:
$obj = new stdClass();
$obj->suggestions = $a_json;
echo json_encode($obj);
You don't need to call stdClass(). The function json_encode() converts the associative array to JSON for you. Here's an example:
<?php
$query="";
if (isset($_GET['query'])) $query=$db_handler->real_escape_string($_GET['query']);
$sql="SELECT `user_id`,`user_name` FROM `some_table`
WHERE `user_name` LIKE '%{$query}%' ORDER BY `user_name`";
$res=$db_handler->query($sql);
if ($res->num_rows > 0)
{
$data=array();
while($row = $res->fetch_object())
{
$data[]=array("value" => $row->user_name, "data" => $row->user_id);
}
$res->free();
}
header('Content-Type: application/json');
echo json_encode(array("suggestions" => $data));
?>
The above code will output something like this:
{"suggestions":[{"value":"Joe Blow","data":"1000"},{"value":"Jane Blow","data":"1001"}]}
This is the format .autocomplete expects: JavaScript Object Notation.

foreach-loop generates unwanted <br \>-tag, breaks javascript of canvas.js

I'm trying to replace manually typing in 2 arrays into canvas.js for dynamic chart creation, and in concept want to dynamically build the javascript with PHP.
The code actually works if I comment out this portion:
foreach($dataset as $x => $y){
echo "{label:\"$x\",y: $y},";
}
which would define x,y-Datapairs for the graph. So I have the canvas, but no Data on it.
This code here comes in front:
echo "<script type=\"text/javascript\">
window.onload = function () {
var chart = new CanvasJS.Chart(\"canvasname\", {
title:{
text: \"Arbiträre Mengen ohne Zusammenhang über die Jahre\"
},
data: [
{
type: \"line\",
dataPoints: [";
but parsed, the source looks like this:
data: [
{
type: "line",
dataPoints: [<br />
with the <br /> breaking my Javascript, and generating no output.
I either need a way to get rid of the <br> before the browser accessing the javascript bit, or need to know what the heck went wrong here.
Tested it on my local Windows Apache installation and my Linux remote Apache webserver.
Here is the whole code for reference:
$dataset = array(2010 => 240, 2011 => 73, 2012 => 12,2013 => 240,2014 => 30);
include "make_graph.php";
make_graph();
<?php
function make_graph()
{
echo "<script type=\"text/javascript\">
window.onload = function () {
var chart = new CanvasJS.Chart(\"dingdong\", {
title:{
text: \"Arbiträre Mengen ohne Zusammenhang über die Jahre\"
},
data: [//array of dataSeries
{ //dataSeries object
type: \"line\",
dataPoints: [";
foreach($dataset as $x => $y){
echo "{label:\"$x\",y: $y},";
}
echo "]
}
]
});
chart.render();
}
</script>
<script type=\"text/javascript\" src=\"canvasjs.min.js\"></script>
<div id=\"dingdong\" style=\"height: 300px; width: 400px;\">
</div>";
}
?>
I really dont get why not just build it first (of course follow the rules of the API). Use json_encode(). Then simply concatenate the json string (since its a string). Consider this example: Sample Output
<?php
$dataset = array(2010 => 240, 2011 => 73, 2012 => 12, 2013 => 240 ,2014 => 30);
$new_dataset = array();
foreach($dataset as $key => $value) {
$new_dataset[] = array('label' => $key, 'y' => $value);
}
$new_dataset = json_encode($new_dataset);
echo
'
<script type="text/javascript" src="http://canvasjs.com/assets/script/canvasjs.min.js"></script>
<script type="text/javascript">
window.onload = function () {
var chart = new CanvasJS.Chart("dingdong", {
title:{
text: "Arbiträre Mengen ohne Zusammenhang über die Jahre"
},
data: [
{
type: "line",
dataPoints: '.$new_dataset.'
}
]
});
chart.render();
}
</script>
';
?>
<div id="dingdong"></div>
Format the array to the desired structure and then use json_encode.
<?php
$dataset = array( 2010 => 240, 2011 => 73, 2012 => 12, 2013 => 240, 2014 => 30 );
$dataset = array_map( function( $a, $b ) {
return array( 'label' => $a, 'y' => $b );
}, array_keys($dataset), array_values($dataset) );
?>
<script type="text/javascript">
window.onload = function () {
var chart = new CanvasJS.Chart( "dingdong", {
title:{
text: "Arbiträre Mengen ohne Zusammenhang über die Jahre"
},
data: [{
type: "line",
dataPoints: <?php echo json_encode($dataset); ?>
}]
});
chart.render();
}
</script>

Categories