morrisJS Bar chart population using PHP and mysql - javascript

I'm struggling with getting data to populate my MorrisJS bar chart using data from my mySQL database. Could anyone assist in getting it to display on my bar chart?
Below is my current code and pages.
<?php
$link = mysql_connect('127.0.0.1', 'root', 'password')
or die('Could not connect: ' . mysql_error());
mysql_select_db('database') or die('Could not select database');
$dataArray=array();
//get data from database
$sql="SELECT * FROM table";
$result = mysql_query($sql) or die('Query failed: ' . mysql_error());
if ($result) {
while ($row = mysql_fetch_assoc($result)) {
$Version=$row["Version"];
$Live=$row["Live"];
$Preprod=$row["Preprod"];
//add to data areray
$dataArray[$Version]=$count;
}
}
?>
index.php (main page)
div id="morris-bar-chart"></div>
<?php include ('database.php') ?>
<script src="../js/morris-data.js"></script> <----- script on index.php page linking to morris chart page.
morris.js page
Morris.Bar({
element: 'morris-bar-chart',
data: [{
while ($row = mysql_fetch_assoc($result)) {
y:<?=$row['versions']?>,
Live:<?=$row['Live']?>,
PreProd: <?=$row['Preprod']?>
}, {
],
xkey: 'y',
ykeys: ['Live', 'PreProd'],
labels: ['Live', 'PreProd'],
hideHover: 'auto',
resize: true
});
Hope this all makes sense. Thanks in advance.

I think the while is the problem.
Morris expects data line-wise, e.g. { y: '2007', a: 75, b: 65 },
I've adjusted the PHP code part in the morris.js script a bit.
Normally, you can not execute PHP within a JS file. Except, when you added a rule to the server, that JS files should be processed by PHP, too.
The normal way to fetch the data would be an AJAX query to a PHP script, which returns the json_encoded($result). And then add it to Morris with the setData() function.
But this should work, too: generate the JS file by PHP. You could rename the morris-data.js to morris-data.js.php. The file needs <?php header("Content-type: application/javascript"); ?> at the top. And then adjust your <script include to match the new filename.
File morris-data.js.php
<?php header("Content-type: application/javascript"); ?>
Morris.Bar({
element: 'morris-bar-chart',
data: [
<?php
while ($row = mysql_fetch_assoc($result)) {
// output a line like:
// { y: '123', Live: 123, PreProd: 123 },
sprintf(
"{ y: '%s', Live: %s, PreProd: %s },",
$row['version'],
$row['Live'],
$row['Preprod']
);
}
?>
],
xkey: 'y',
ykeys: ['Live', 'PreProd'],
labels: ['Live', 'PreProd'],
hideHover: 'auto',
resize: true
});
that should render something like (see also the bar chart example)
data: [
{ y: '1.2.3', Live: 20, PreProd: 23 },
{ y: '1.2.4', Live: 30, PreProd: 24 },
{ y: '1.2.5', Live: 40, PreProd: 25 },
{ y: '1.2.6', Live: 50, PreProd: 26 }
],
(I'm not sure what the last part in the database.php file is supposed to do.
Maybe you can drop that (the code inside the if($result)). But maybe its for calculations..)

Related

Problems with the x axis in morris.js

I am working on a website. On one of the pages I draw a line chart with morris.js . But the x axis looks like this
It places 190 before the day number so I want it do look like Day 1 , Day 2 ...
Here is my source code for the chart:
var DataForChart1 = [
{x:'1' , a: <?php echo h($day1); ?> },
{x:'2' , a: <?php echo h($day2); ?> },
{x:'3' , a: <?php echo h($day3); ?> },
{x:'4' , a: <?php echo h($day4); ?> },
{x:'5' , a: <?php echo h($day5); ?> },
{x:'6' , a: <?php echo h($day6); ?> },
{x:'7' , a: <?php echo h($day7); ?> },
{x:'8' , a: <?php echo h($day8); ?> },
{x:'9' , a: <?php echo h($day9); ?> },
{x:'10' , a: <?php echo h($day10); ?> }
];
config1 = {
data: DataForChart1,
xkey: 'x',
ykeys: 'a',
xLabelAngle: '70',
labels: 'Кръвно налягане горна граница',
fillOpacity: 0.6,
hideHover: 'auto',
behaveLikeLine: true,
resize: true,
pointFillColors:['#ffffff'],
gridTextSize: 15,
verticalGrid: true,
gridTextColor: '#5cb85c',
pointStrokeColors: ['black'],
padding: 50,
lineColors:['red']
};
config1.element = 'chart1';
Morris.Line(config1);
The reason why x is '1' , '2' ... , '10' is because if i put in front of it something like day then the whole thing would look like this.
If you know a solution to this problem please tell me. Thanks for reading.
Add parseTime: false to your config to disable the date being used.
Despite putting 1, 2, 3 as x, morris.js by default populates x as a date (hence the reason 1901, 1902, 1903, etc is being displayed).
Here's a jsFiddle with the fix

Import data from Database to JS file

I am new to .js files and their use, I am trying to update charts that uses JS. What I need or trying to do is import information from my database to use it in my JS file to populate the chart. Here is the chart code and file name.
File Name charjs_custom.js
/*Polar chart*/
var polarElem = document.getElementById("polarChart");
var data3 = {
datasets: [{
data: [
20,
16,
7,
3,
40
],
backgroundColor: [
"#7E81CB",
"#1ABC9C",
"#B8EDF0",
"#B4C1D7",
"#01C0C8"
],
hoverBackgroundColor: [
"#a1a4ec",
"#2adab7",
"#a7e7ea",
"#a5b0c3",
"#10e6ef"
],
label: 'My dataset' // for legend
}],
labels: [
"Blue",
"Green",
"Light Blue",
"grey",
"Sea Green"
]
};
new Chart(polarElem, {
data: data3,
type: 'polarArea',
options: {
elements: {
arc: {
borderColor: ""
}
}
}
});
I need to alter the "data" and "label" sections using information from my DB, from what I have read I need to create a php file to retrieve the informationbut how do i convert it to JS and how do I tell it what information to use in the JS file. Also linking the "data" and "label" sections so the information will correspond to my tables
Tables I want to use is: make: id~count
File Name chart_test.php
<?php
//database
$host="my_host"; // Host name
$username="my_username"; // Mysql username
$password="my_password"; // Mysql password
$db_name="my_database"; // Database name
//get connection
$mysqli = new mysqli($host, $username, $password, $db_name);
if(!$mysqli){
die("Connection failed: " . $mysqli->error);
}
//query to get data from the table
$query = sprintf("SELECT * FROM bureau GROUP BY make ");
//execute query
$result = $mysqli->query($query);
//close connection
$mysqli->close();
//now print the data
print json_encode($data);
?>
you can interchange data between php backend and js frontend using JSON format. However i urge you to use nodejs as a backend service. it will integrate seamlessly with your js code.
Without really knowing anything about your data source, it would typically work like the following.
<?php
// Lets say your managed to convert your data from your database into something like.
$graph = [
'data' => [20, 16, 7, 3, 40],
'background' => ['#7E81CB', '#1ABC9C', '#B8EDF0', '#B4C1D7', '#01C0C8'],
'hover' => ['#a1a4ec', '#2adab7', '#a7e7ea', '#a5b0c3', '#10e6ef'],
'labels' => ['Blue', 'Green', 'Light Blue', 'Grey', 'Sea Green']
];
?>
var polarElem = document.getElementById("polarChart");
var data3 = {
datasets: [{
data: <?php echo json_encode($graph['data']); ?>,
backgroundColor: <?php echo json_encode($graph['background']); ?>,
hoverBackgroundColor: <?php echo json_encode($graph['hover']); ?>,
label: 'My dataset'
}],
labels: <?php echo json_encode($graph['labels']); ?>
};
So if I understand the mapping of the database, I would do:
<?php
//database
$host="my_host"; // Host name
$username="my_username"; // Mysql username
$password="my_password"; // Mysql password
$db_name="my_database"; // Database name
//get connection
$mysqli = new mysqli($host, $username, $password, $db_name);
if(!$mysqli){
die("Connection failed: " . $mysqli->error);
}
//query to get data from the table
$query = sprintf("SELECT * FROM bureau GROUP BY make ");
//execute query
$result = $mysqli->query($query);
// Define configuration array
$config = array(
'datasets' => array(
array(
'data' => array(),
'backgroundColor' => array(), // This could be statically loaded, or dynamic if the DB has colors
'hoverBackgroundColor' => array(), // This could be statically loaded, or dynamic if the DB has colors
'label' => 'My Dataset'
)
),
'labels' => array()
);
// Loop through database result and add
while($row=mysqli_fetch_assoc($result)){
array_push($config['labels'], $row['make']); // Add label
array_push($config['datasets'][0]['data'], $row['totalValue']); // Add value
}
//close connection
$mysqli->close();
//now print the data
echo json_encode($config);
What you ultimately do with that config depends on how you're loading this chart. It could be an AJAX request that you would then use the result of in place of data3 such as:
$.get( "chart_test.php", function( data ) {
new Chart(polarElem, {
data: data,
type: 'polarArea',
options: {
elements: {
arc: {
borderColor: ""
}
}
}
});
}, "json" );
Or embedded into a php file so that instead of printing the json_encode($config); you would create the entire script:
new Chart(polarElem, {
data: <?= json_encode($config) ?>,
type: 'polarArea',
options: {
elements: {
arc: {
borderColor: ""
}
}
}
});
It all depends on the setup you have thus far.

Trying to pass a php variable into js

I have the $attr array that contains the id and footer caption of each graph (highcharts) in a post. When i print_r the array it groups the id and footer_caption correctly and in the right order as they are in the post. For eg in the current post im working at i have 3 graphs and this is what's inside $attr:
Array
(
[chart] => 23
[footer_caption] => footer test
)
Array
(
[chart] => 22
[footer_caption] => another test
)
Array
(
[chart] => 24
[footer_caption] => And another test
)
I'm passing $attr['footer_caption] to javascript like this:
<script>
var captionLabel = "<?php echo $attr['footer_caption']; ?>";
console.log(captionLabel);
</script>
And its working fine. Then the problem happens when i use captionLabel on te js file. I tried using a for loop but with no luck. If i console.log captionLabel in the js file, it shows the footer caption of the last graph 3 times. This is the highcharts.js where im using captionLabel:
Highcharts.setOptions({
credits: {
enabled: false
},
chart: {
type: 'column',
events: {
load: function () {
var label = this.renderer.label(captionLabel)
.css({
width: '400px',
fontSize: '9px'
})
.attr({
'r': 2,
'padding': 5
})
.add();
label.align(Highcharts.extend(label.getBBox(), {
align: 'center',
x: 0, // offset
verticalAlign: 'bottom',
y: 20 // offset
}), null, 'spacingBox');
}
},
marginBottom: 120
},
legend: {
align: 'center',
verticalAlign: 'bottom',
y: -30
},
My question is how can i pass the right footer_caption string to each graph in this js? Because right now every footer label is getting the last value. All the 3 graphs get the footer caption "And another test" in this post.
Use json_encode()
<?php
$labels = [
[
['chart'] => 23,
['footer_caption'] => 'footer test 1'
],[
['chart'] => 24,
['footer_caption'] => 'footer test 2'
],[
['chart'] => 25,
['footer_caption'] => 'footer test 3 '
]
];
?>
<script>
var captionLabels = "<?php echo json_encode($labels); ?>";
console.log(captionLabels);
var label;
//access each one like this
captionLabels.forEach(function(label) {
label = this.renderer.label(label.footer_caption);
//graph code.
});
</script>
I think you should generate the array of footer_caption text and send it to javascript as a JSON string.
PHP code:
$array = new array();
foreach ($attr as $value) {
array_push($array, $value['footer_caption']);
}
$captionLabel = json_encode($array);
JS code:
<script>
var captionLabel = JSON.parse("<?php echo $captionLabel; ?>");
console.log(captionLabel);
</script>
captionLabel has to be an array, otherwise it will only hold the last value assigned to it. You should also use an array for all the $attr values and then use json_encode when outputting itto the JavaScript.
<?php
$attr = [
['chart' => '23', 'footer_caption' => 'footer test'],
['chart' => '22', 'footer_caption' => 'another test'],
['chart' => '24', 'footer_caption' => 'And another test']
];
?>
<script>
var captionLabel = <?= json_encode($attr) ?>;
</script>

HighChart Line Graph value from database

I want to draw one page with HighChart. I took data from database. I wrote it with json_encode. I can see what my $xxx has value. Its json format. But my graph is not working. I think var data = <?php echo json_encode($xxx); ?> doesnt work and return valur. Where do I mistake?
Here is my php code for database value:
<?php
$var = "SELECT SUBSTRING(KayitTarihi,1,4) AS year,SUBSTRING(KayitTarihi,6,2) AS month,SUBSTRING(KayitTarihi,9,2) AS day,SUBSTRING(KayitTarihi,12,2) AS saat,SUBSTRING(KayitTarihi,15,2) AS dakika,Guc FROM Urun WHERE Date(KayitTarihi)=\"".$link_m."\"";
$result = $mysqli->query($var);
$data = array();
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
$data[] = $row;
}
}
$no = 1;
$total_deger=count($data);
foreach($data as $dat)
{
$xxx ="[Date.UTC(".$dat['year'].",".$dat['month'].",".$dat['day'].",".$dat['saat'].",".$dat['dakika'].",00),".$dat['Guc']."]";
if($no < $total_deger)
{
echo ",";
}
echo json_encode($xxx);
}
//free memory associated with result
$result->close();
//close connection
$mysqli->close();
?>
And here is my highchart script:
<script>
$(function () {
var data = <?php echo $xxx; ?>;
Highcharts.chart('container', {
chart: {
zoomType: 'x'
},
title: {
text: 'USD to EUR exchange rate over time'
},
subtitle: {
text: document.ontouchstart === undefined ?
'Click and drag in the plot area to zoom in' : 'Pinch the chart to zoom in'
},
xAxis: {
type: 'datetime'
},
yAxis: {
title: {
text: 'Exchange rate'
}
},
legend: {
enabled: false
},
plotOptions: {
area: {
fillColor: {
linearGradient: {
x1: 0,
y1: 0,
x2: 0,
y2: 1
},
stops: [
[0, Highcharts.getOptions().colors[0]],
[1, Highcharts.Color(Highcharts.getOptions().colors[0]).setOpacity(0).get('rgba')]
]
},
marker: {
radius: 2
},
lineWidth: 1,
states: {
hover: {
lineWidth: 1
}
},
threshold: null
}
},
series: [{
type: 'area',
name: 'USD to EUR',
data: [data]
}]
});
});
</script>
Edit: I edited json format. When I write just echo. Its just see one value.
Edit2: I have 9 value. My output is:
,,,,,,,,[Date.UTC(2016,11,15,10,28,00),0]
[Date.UTC(2016,11,15,14,25,00),0]
[Date.UTC(2016,11,15,14,25,00),0]
[Date.UTC(2016,11,15,14,27,00),17]
[Date.UTC(2016,11,15,18,32,00),54]
[Date.UTC(2016,11,15,18,32,00),54]
[Date.UTC(2016,11,15,18,33,00),93]
[Date.UTC(2016,11,15,18,33,00),34]
[Date.UTC(2016,11,15,18,34,00),34]
But when ı read docs for highchart my value must be
([
[Date.UTC(2016,11,15,10,28,00),0],
[Date.UTC(2016,11,15,14,25,00),0],
[Date.UTC(2016,11,15,14,25,00),0],
[Date.UTC(2016,11,15,14,27,00),17],
[Date.UTC(2016,11,15,18,32,00),54],
[Date.UTC(2016,11,15,18,32,00),54],
[Date.UTC(2016,11,15,18,33,00),93],
[Date.UTC(2016,11,15,18,33,00),34],
[Date.UTC(2016,11,15,18,34,00),34]
]);
Try wrapping it in quotes
var data = "<?php echo json_encode($xxx); ?>"
You should see this as an error in the console
Also you arent concatenating correctly. This means every time the loop runs you are overwriting the last entry stored in $xxx
$xxx = "[Date.UTC(".$dat['year'].",".$dat['month'].",".$dat['day'].",".$dat['saat'].",".$dat['dakika'].",00),".$dat['Guc']."]";
should be
$xxx .= "[Date.UTC(".$dat['year'].",".$dat['month'].",".$dat['day'].",".$dat['saat'].",".$dat['dakika'].",00),".$dat['Guc']."]";
Finally, change your loop to work like this
$xxx = '';
foreach($data as $dat){
// if not a blank string i.e. something added, add a comma to the end read for the next concatenation
if($xxx != '') $xxx .= ",";
// concatenate
$xxx .= "[Date.UTC(".$dat['year'].",".$dat['month'].",".$dat['day'].",".$dat['saat'].",".$dat['dakika'].",00),".$dat['Guc']."]";
}
// if not blank string, echo
if($xxx != ''){
echo json_encode($xxx);
}

How to include strings in series data to pull for tooltip point formatting?

beginner here, I'm trying to build a column graph that shows a username on the x axis, and a test score on the y axis. In the tooltips box, I'm trying to make it so it shows the test score and the date the test was taken. I'm using PHP to populate the graph based on an oracle sql database, so I'm mixing PHP into my javascript for Highcharts.
I'm not sure if what I'm trying to do is actually possible, but I'm trying to take the test date from the sql database, and plug it into the series data, so I can call it out into the tooltips box (that way when you hover over the column, it'll tell you the user, the score, and the date they took the exam).
This is what I'm trying, and it isn't working, because I'm guessing series data has something against strings instead of numeric. Any help you can offer would be awesome! Thanks!
<br><br><br><br>
<div id="graph1" style="height: 400px; width: <?php echo $chartspace ?>px"></div>
<input id="width" type="range" value="<?php echo $chartspace ?>" min="300" max="<?php echo $chartspacemax ?>" />
<script>
$(function () {
$('#graph1').highcharts({
credits: { enabled:false},
chart: {
type: 'column'
},
title: {
text: 'Most Recent Test Scores'
},
subtitle: {
text: 'Drag slider to change the chart width'
},
xAxis: {
categories: [
<?php
$i = 0;
do {
echo "'";
echo $userinfos[$i]['username'];
echo "',";
$i++;
} while ($i<=$count); ?>
]
},
yAxis: {
plotLines: [{
color: 'red',
dashStyle: 'shortdash',
value: 85,
width: 1,
}],
floor: 0,
ceiling: 100,
title: {
text: 'Test Score (%)'
}
},
series: [{
showInLegend: false,
name: 'Test Score',
data: [
<?php
$i = 0;
do {
if($userinfos[$i]['score'] >= 85){
echo "{y:";
echo $userinfos[$i]['score'];
echo ", testdate:";
echo $userinfos[$i]['most_recent_test_date'];
echo ", color: '#00A6CF'},";}
else{
echo "{y:";
echo $userinfos[$i]['score'];
echo ", testdate:";
echo $userinfos[$i]['most_recent_test_date'];
echo ", color: 'red'},";}
$i++;
} while ($i<=$count-1); ?>]
}],
tooltip: {
shared: true,
useHTML: true,
pointFormat: '<tr><td style="color: {series.color}">Score: </td>' +
'<td style="text-align: right">{point.y} %</td></tr><tr><br><td>Date: </td>' +
'<td style="text-align: right">{point.testdate}</td></tr>'
}
});
$('#width').bind('input', function () {
$('#graph1').highcharts().setSize(this.value, 400, false);
});
});
</script>
What you're trying to do should definitely be possible. Here's an example of that working:
http://jsfiddle.net/thfbx7gb/
However, in this case I pulled out the PHP and replaced it with some hard-coded data.
data: [{y:7, color: '#00A6CF', testdate: '2014-12-12'},{y:2, color:"#FF0000", testdate: '2015-01-03'}, {y:3,color:"#00FF00", testdate:'2014-10-19'}]
So I think the problem is that you're mixing in PHP with javascript and getting some strange results. It's generally a very bad idea to include inline PHP into javascript code like you're doing if for no other reason that it's really, really hard to read and debug.
A few things jump out at me:
You shouldn't be using PHP for this at all, but if you must then you shouldn't be using do-while loops like you are. You're using a do/while with an incrementor instead of a for loop:
$i = 0;
do {
echo "'";
echo $userinfos[$i]['username'];
echo "',";
$i++;
} while ($i<=$count);
This should really be:
for ($i=0; $i<=$count; $i++) {
echo "'{$userinfos[$i]['username']}'";
}
You should be able to see how the other do/while loops you're using could be reduced to a much more succinct for loop.
But that still doesn't eliminate the whole problem of including PHP code in your javascript. You should really be either hard coding this data or loading it from an external source of some kind. The typical way of doing that would be with an AJAX call to load the data and then pass that in to the chart directly.
You would have a file that generates the data object directly and outputs that as as JSON string using json_ecode();
$output = array();
foreach ($userinfos as $user) {
$output['categories'][] = $user['username'];
if ($user['score'] >= 85) {
$color = "#00A6CF";
} else {
$color = "#FF0000";
}
$user['color'] = $color;
$output['seriesdata'][] = $user;
}
echo json_encode($output);
This should give you a JSON object which you can read work with pretty easily. Something along the lines of this (which is untested, it may not work without a bit of fiddling):
$.getJSON('/generate.php', function(data) {
$('#graph1').highcharts({
credits: { enabled:false},
chart: {
type: 'column'
},
title: {
text: 'Most Recent Test Scores'
},
subtitle: {
text: 'Drag slider to change the chart width'
},
xAxis: {
categories: data.categories
yAxis: {
plotLines: [{
color: 'red',
dashStyle: 'shortdash',
value: 85,
width: 1,
}],
floor: 0,
ceiling: 100,
title: {
text: 'Test Score (%)'
}
},
series: [{
showInLegend: false,
name: 'Test Score',
data: data.seriesdata,
tooltip: {
shared: true,
useHTML: true,
pointFormat: '<tr><td style="color: {series.color}">Score: </td>' +
'<td style="text-align: right">{point.y} %</td></tr><tr><br><td>Date: </td>' +
'<td style="text-align: right">{point.testdate}</td></tr>'
}
});
});

Categories

Resources