currently I am trying to show 3 Google Charts on a page, but the page is blank, it does not display any of the charts. Originally the 1st chart was displayed, then it worked but ever since I attached the 2nd one (even if I deleted that so only the 1st one would be shown again), the page I have is totally blank and I don't know why.
Could you please help me?
Here is my code (I set the $conn and $_SESSION variables at the top of my page):
EDIT: Here is a picture about the source code in my browser:
[![sourcecode][1]][1] What I don't understand is that it looks like it would expect other values to data1 and data2 and that is why the charts are not displayed...
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Dashboard</title>
<link rel="stylesheet" href="styles.css">
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
// Load Charts and the corechart package.
google.load('current', callback: drawCharts, {packages:['column', 'pie']});
// Set a callback to run when the Google Visualization API is loaded.
google.setOnLoadCallback(drawCharts);
// Callback that creates and populates a data table, instantiates the pie chart, passes in the data and draws it.
function drawCharts() {
var data1 = google.visualization.arrayToDataTable([
['Classification', 'Number of assets'],
<?php
if ($_SESSION['user_type'] == 'admin') {
$sql = "SELECT Classification, count('Classification') as count FROM `assets` GROUP BY Classification ORDER BY FIELD(Classification, 'high', 'medium', 'low')";
}else{
$sql = "SELECT Classification, count('Classification') as count FROM `assets` WHERE Responsible =".$_SESSION['name']." GROUP BY Classification ORDER BY FIELD(Classification, 'high', 'medium', 'low')";
}
$result = mysqli_query($conn,$sql);
while ($result2=mysqli_fetch_array($result)) {
echo "['".$result2['Classification']."',".$result2['count']."],";
}
?>
]);
var data2 = google.visualization.arrayToDataTable([
['Risks', 'Percentage'],
<?php
if ($_SESSION['user_type'] == 'admin') {
$sql = "SELECT Compliant = (SELECT count('id') FROM `risks` WHERE targetrisk >= residualrisk), Non-compliant = (SELECT count('id') FROM `risks` WHERE targetrisk < residualrisk) FROM risks ";
}else{
$sql = "SELECT Compliant = (SELECT count('id') FROM `risks` WHERE responsible =".$_SESSION['name']." AND targetrisk >= residualrisk), Non-compliant = (SELECT count('id') FROM `risks` WHERE ".$_SESSION['name']." AND targetrisk < residualrisk) FROM risks ";
}
$results = mysqli_query($conn,$sql);
while ($result2=mysqli_fetch_array($results)) {
echo "['".$result2['Compliant']."',".$result2['Non-compliant']."],";
}
?>
]);
var data3 = google.visualization.arrayToDataTable([
['Assets', 'Percentage'],
<?php
if ($_SESSION['user_type'] == 'admin') {
$sql = "SELECT count('Asset_name') as Assets, count(`risks`.`assettag`) as Compliant assets FROM `assets`, `risks` JOIN `assettag` ON `assets`.`Tag` = `risks`.`assettag` ";
}else{
$sql = "SELECT count('Asset_name') as Assets, count(`risks`.`assettag`) as Compliant assets FROM `assets`, `risks` JOIN `assettag` ON `assets`.`Tag` = `risks`.`assettag` AND responsible =".$_SESSION['name']."";
}
$results = mysqli_query($conn,$sql);
while ($result2=mysqli_fetch_array($results)) {
echo "['".$result2['Assets']."',".$result2['Compliant assets']."],";
}
?>
]);
var options1 = {
title: 'Asset classification',
legend: { position: 'none' },
width: 900,
height: 500
};
var options2 = {
title: 'Risk compliance',
legend: { position: 'none' },
width: 900,
height: 500
};
var options3 = {
title: 'Asset compliance',
legend: { position: 'none' },
width: 900,
height: 500
};
var chart1 = new google.visualization.ColumnChart(document.getElementById("columnchart"));
chart1.draw(data1, options1);
var chart2 = new google.visualization.PieChart(document.getElementById("piechart"));
chart2.draw(data2, options2);
var chart3 = new google.visualization.PieChart(document.getElementById("piechart2"));
chart3.draw(data3, options3);
}
</script>
</head>
<body>
<div id="columnchart"></div>
<br>
<div id="piechart" ></div>
<br>
<div id="piechart2" ></div>
</body>
</html>
[1]: https://i.stack.imgur.com/f2u3D.png
Related
I'm trying to create my own Activity in moodle where students can take pictures of their Drivers License and that pictures get stored in moodle, then later opended and shown to the teacher.
My Problem is to store the picture on the moodle side and not downloading it.(like i'm doing right now)
Hopfully someone can help me figure out a way to use the file_storage given by moodle to safe the pictures.
kind regards
J
This is my code for now (view.php) ... I know its not realy in a moodle way but im trying to get it to work first then then clean up the code
require_once('../../config.php');
require_once($CFG->dirroot . '/mod/driverslicense/lib.php');
require_once($CFG->dirroot . '/mod/assign/locallib.php');
require_once($CFG->dirroot . '/mod/driverslicense/classes/submit/submit.php');
require_once("$CFG->libdir/formslib.php");
$id = required_param('id', PARAM_INT);
list ($course, $cm) = get_course_and_cm_from_cmid($id, 'driverslicense');
require_login($course, true, $cm);
$context = context_module::instance($cm->id);
require_capability('mod/driverslicense:view', $context);
$driverslicense = new assign($context, $cm, $course);
$urlparams = array('id' => $id,
'action' => optional_param('action', '', PARAM_ALPHA),
'rownum' => optional_param('rownum', 0, PARAM_INT),
'useridlistid' => optional_param('useridlistid', $driverslicense->get_useridlist_key_id(), PARAM_ALPHANUM));
$url = new moodle_url('/mod/driverslicense/view.php', $urlparams);
$PAGE->set_url($url);
// Update module completion status.
$driverslicense->set_module_viewed();
// Apply overrides.
$driverslicense->update_effective_access($USER->id);
// Get the driverslicense class to
// render the page.
//echo $driverslicense->view(optional_param('action', '', PARAM_ALPHA));
$mform = new submit();
echo $OUTPUT->header();
echo '<body>
<div id="container">
<video autoplay="true" id="video"></video>
<button id="btn"> Take Picture </button>
<canvas id="canvas" class="hidden"></canvas>
<a id="dl-btn" href="frontpic" download="image.png" class="hidden"></a>
</div>
</body>';
$fs = get_file_storage();
// Prepare file record object
$fileinfo = array(
'contextid' => $context->id, // ID of context
'component' => 'mod_driverslicense', // usually = table name
'filearea' => 'driverslicense', // usually = table name
'itemid' => 0, // usually = ID of row in table
'filepath' => '/', // any path beginning and ending in /
'filename' => 'driverslicensefront.png'); // any filename
$fs->create_file_from_url($fileinfo, imgURL );
echo $OUTPUT->footer();
?>
<script type="text/javascript">
const video = document.querySelector('#video')
const btn = document.querySelector('#btn')
const canvas = document.querySelector('#canvas')
if ('mediaDevices' in navigator && 'getUserMedia' in navigator.mediaDevices) {
navigator.mediaDevices.getUserMedia({video: true})
.then(stream => {
video.srcObject = stream
})
.catch(error => {
console.log('An error occured while accessing webcam.')
})
}
btn.addEventListener('click', () =>{
const width = video.videoWidth, height = video.videoHeight
const context = canvas.getContext('2d')
canvas.width = width
canvas.height = height
context.drawImage(video, 0, 0, width, height)
const imgURL = canvas.toDataURL('image/png')
document.querySelector('#dl-btn').href = imgURL
document.querySelector('#dl-btn').click()
})
</script>
I create a pie chart using google services. the problem is that i want to show credit and debit in pie chart, but output comes only in one color. Here is my query.
$data = mysqli_query($link, "select SUM(pay_payable) as debit, SUM(pay_paid) as credit from purchasers_payment where p_id = '$pur_id'");
and here is my chart setting.
var data = google.visualization.arrayToDataTable([
['Debit', 'Credit'],
<?php
while($row = mysqli_fetch_array($data))
{
echo "['".$row['debit']."',".$row['credit']."],";
}
?>
]);
var options = {
is3D: true,
};
var chart = new google.visualization.PieChart(document.getElementById('piechart'));
here is mine code output
enter image description here
and i want output like this:
enter image description here
the data format for a PieChart uses rows for each slice
to get two slices, you need two rows of data...
['Label', 'Value'],
['Debit', 10000],
['Credit', 2000]
see following working snippet...
google.charts.load('current', {
packages: ['corechart']
}).then(function () {
var data = google.visualization.arrayToDataTable([
['Label', 'Value'],
['Debit', 10000],
['Credit', 2000]
]);
var options = {
is3D: true,
height: 300
};
var chart = new google.visualization.PieChart(document.getElementById('piechart'));
chart.draw(data, options);
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="piechart"></div>
try the following php...
var data = google.visualization.arrayToDataTable([
['Label', 'Value'],
<?php
while($row = mysqli_fetch_array($data))
{
echo "['Debit',".$row['debit']."],['Credit',".$row['credit']."],";
}
?>
]);
I implemented Isotope.js into my WordPress site. I use it to display gallery with Easy Fancybox plugin to add zooming functionality for images. Problem is with Isotope filtering. I added rel attribute to my images but when I filter categories Fancybox still cycles through all images.
I need to add rel attribute dynamically based on category I'm filtering. I'm struggling with this problem for 3 days now. I've read bunch of post, tried view things but still can't make it work.
Most of posts give solution with data-fancybox-group attribute but I can't use it I must use rel attribute (it doesn't work for me anyway).
Here's my WP code:
<ul id="filters">
<li>All</li>
<?php
$terms = get_terms("polygraphy-categories");
$count = count($terms);
if ( $count > 0 ){
foreach ( $terms as $term ) {
echo "<li><a class='filterbutton' href='#' data-filter='.".$term->slug."'>" . $term->name . "</a></li>\n";
}
}
?>
</ul>
<?php $the_query = new WP_Query( 'post_type=polygraphy' ); ?>
<?php if ( $the_query->have_posts() ) : ?>
<div id="isotope-list">
<?php while ( $the_query->have_posts() ) : $the_query->the_post();
$termsArray = get_the_terms( $post->ID, "polygraphy-categories" );
$termsString = "";
foreach ( $termsArray as $term ) {
$termsString .= $term->slug.' ';
}
?>
<div class="<?php echo $termsString; ?> poli">
<?php
if ( has_post_thumbnail()) {
$full_image_url = wp_get_attachment_image_src( get_post_thumbnail_id(), 'full');
echo '<a class="fancybox" href="' . $full_image_url[0] . '" title="' . the_title_attribute('echo=0') . '" >';
the_post_thumbnail('thumbnail');
echo '</a>';
}
?>
</div>
<?php endwhile; ?>
</div>
<?php endif; ?>
And JS code:
jQuery(function ($) {
$(window).load(function(){
var $container = $('#isotope-list');
$container.isotope({
itemSelector : '.poli',
layoutMode : 'masonry'
});
var $optionSets = $('#filters'),
$optionLinks = $optionSets.find('a');
$optionLinks.click(function(){
var $this = $(this);
if ( $this.hasClass('selected') ) {
return false;
}
var $optionSet = $this.parents('#filters');
$optionSets.find('.selected').removeClass('selected');
$this.addClass('selected');
var selector = $(this).attr('data-filter');
$container.isotope({ filter: selector });
return false;
});
});
});
I was told that this code should work but it doesn't:
$('.filterbutton').on("click", function(){
var selector = $(this).attr('data-filter');
if(selector == "*"){
$(".fancybox").attr("rel", "gallery");
} else{
$(selector).find(".fancybox").attr("rel", selector);
}
return false;
});
I am using the code below to generate a line chart for a projected financial balance. Data is generated from information in a MySQL database. What I would like to be able to do is to have a form with an input field on the page that allows the user to set the starting balance dynamically once the page is loaded, such that the chart is redrawn with the correct starting balance, but I can't work out how to do this:
$rows = array();
$table = array();
$table['cols'] = array(
array('label' => 'Date', 'type' => 'string'),
array('label' => 'Amount', 'type' => 'number')
);
[code to generate data goes here - i.e. calculating a balance for each date in the chart]
$balance = $balance - $monthly - $weekly + $session_total;
$temp = array();
$temp[] = array('v' => (string) $date_display);
$temp[] = array('v' => (string) $balance);
$rows[] = array('c' => $temp);
}
$table['rows'] = $rows;
$jsonTable = json_encode($table);
//echo $jsonTable;
?>
<script type="text/javascript">
// Load the Visualization API and the piechart package.
google.load('visualization', '1', {'packages':['corechart']});
// Set a callback to run when the Google Visualization API is loaded.
google.setOnLoadCallback(drawChart);
function drawChart() {
// Create our data table out of JSON data loaded from server.
var data = new google.visualization.DataTable(<?=$jsonTable?>);
var formatter = new google.visualization.NumberFormat({fractionDigits:2,prefix:'\u00A3'});
formatter.format(data, 1);
var options = {
pointSize: 5,
legend: 'none',
hAxis: { showTextEvery:31 },
series: {0:{color:'2E838F',lineWidth:2}},
chartArea: {left:50,width:"95%",height:"80%"},
backgroundColor: '#F7FBFC',
height: 400
};
// Instantiate and draw our chart, passing in some options.
//do not forget to check ur div ID
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
</script>
<div id="chart_div"></div>
Hopefully there's a fairly simple way to refresh the chart when new data is available. It requires a small change to your PHP and a few JavaScript tweaks.
The nice thing about using Google Charts is that you can just re-draw them by calling drawChart() again, you just need to be able to modify the data before you do it.
The change I would make the PHP would be to store the original value, so that when you want to change the value according to the user's input you can always have something to refer back to:
// display the date
$temp[] = array('v' => (string) $date_display);
// the data used by the chart
$temp[] = array('v' => (string) $balance);
// the original value
$temp[] = array('v' => (string) $balance);
I would also make the table data global rather than drawing it directly into the function, this way you can change it and refresh the chart quite easily.
var table = <?php echo $jsonTable; ?>;
function drawChart() {
var data = new google.visualization.DataTable(table);
......
}
I tested this with a basic form that looks like this:
<form method="post" action="#" onsubmit="return false;">
<input type="text" id="balance1" />
<input type="text" id="balance2" />
<button onclick="return refreshChart()">Go</button>
</form>
Clicking on the button cancels the default action and calls a function called refreshChart(). This function takes the value and adds it to the original values on the fly before re-drawing the chart:
function refreshChart() {
var balance1 = document.getElementById('balance1').value;
var balance2 = document.getElementById('balance2').value;
if(!balance1) {
balance1 = 0;
}
if(!balance2) {
balance2 = 0;
}
for(var i = 0, length = table.rows.length; i < length; i++) {
table.rows[i].c['1'].v = parseFloat(table.rows[i].c['2'].v) + parseFloat(balance1) + parseFloat(balance2);
}
drawChart();
return false;
}
It takes the balance entered and adds it to the original value stored in table.rows[i].c['2'].v and overwrites the value in table.rows[i].c['1'].v which is used by the chart. It then calls the original drawChart() function but the new data is used.
I played around with some default data and this is the output I tested it with on JSFiddle.
I've spent several hours looking at examples and docs trying to figure out how to POST additional parameters to editurl, and have yet to figure this out. I'm using Perl Catalyst.
Though I don't have it all coded in the controller, I am getting what I need POSTed to add and edit, but not to delete records. I need inv_id to be POSTed to the server for my controller to delete a record.
Controller/Root.pm:
package MyFirstGrid::Controller::Root;
use Moose;
use namespace::autoclean;
BEGIN {extends 'Catalyst::Controller'}
with 'Catalyst::TraitFor::Controller::jQuery::jqGrid';
__PACKAGE__->config(namespace => '');
sub index :Path :Args(0) {
my ($self, $c) = #_;
$c->detach($c->view("TT"));
}
sub getdata :Local {
my ($self, $c) = #_;
my $inv_rs = $c->model('DB::Inventory')->search({});
$inv_rs = $self->jqgrid_page($c, $inv_rs);
my #row_data;
while (my $inv = $inv_rs->next) {
my $single_row = {
cell => [
$inv->inv_id,
$inv->client_id,
$inv->amount,
$inv->tax,
$inv->total,
$inv->note,
],
};
push #row_data, $single_row;
}
$c->stash->{json_data}{rows} = \#row_data;
$c->detach($c->view("JSON"));
}
sub postrow :Local {
my ($self, $c) = #_;
my $data = $c->req->params;
my $inv_rs = $c->model('DB::Inventory')->search({inv_id => $data->{inv_id}});
$inv_rs->update({
client_id => $data->{client_id},
amount => $data->{amount},
tax => $data->{tax},
total => $data->{total},
note => $data->{note},
});
$c->res->status(204);
}
sub default :Path {
my ($self, $c) = #_;
$c->response->body('Page not found');
$c->response->status(404);
}
sub end : ActionClass('RenderView') {}
__PACKAGE__->meta->make_immutable;
1;
index.tt:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>My First Grid</title>
<link rel="stylesheet" type="text/css" media="screen" href="[% c.uri_for('/static/css/cupertino/jquery-ui-1.8.22.custom.css') %]" />
<link rel="stylesheet" type="text/css" media="screen" href="[% c.uri_for('/static/css/ui.jqgrid.css') %]" />
<style type="text/css">
html, body {
margin: 0;
padding: 0;
font-size: 75%;
}
</style>
<script src="[% c.uri_for('/static/js/jquery-1.7.2.min.js') %]" type="text/javascript"></script>
<script src="[% c.uri_for('/static/js/i18n/grid.locale-en.js') %]" type="text/javascript"></script>
<script src="[% c.uri_for('/static/js/jquery.jqGrid.min.js') %]" type="text/javascript"></script>
<script type="text/javascript">
$(function(){
$("#list").jqGrid({
url: "[% c.uri_for("getdata") %]",
datatype: 'json',
mtype: 'GET',
colNames:['Inv No', 'Client ID', 'Amount','Tax','Total','Notes'],
colModel :[
//{name:'inv_id', index:'inv_id', editable:true, hidden:true, editrules:{edithidden:false}, hidedlg:true},
{name:'inv_id', index:'inv_id', editable:true, hidden:true},
{name:'client_id', index:'client_id', width:55, editable:true, editoptions:{size:10}},
{name:'amount', index:'amount', width:80, align:'right', editable:true, editoptions:{size:10}},
{name:'tax', index:'tax', width:80, align:'right', editable:true, editoptions:{size:10}},
{name:'total', index:'total', width:80, align:'right', editable:true, editoptions:{size:10}},
{name:'note', index:'note', width:150, sortable:false, editable: true, edittype:"textarea", editoptions:{rows:"2",cols:"20"}}
],
pager: '#pager',
rowNum:10,
rowList:[10,20,30],
sortname: 'inv_id',
sortorder: 'desc',
viewrecords: true,
caption: 'My First Grid: Navigator',
editurl: "[% c.uri_for("postrow") %]",
height: 240
});
jQuery("#list").jqGrid('navGrid','#pager',
{}, //options
{height:280,reloadAfterSubmit:false}, // edit options
{height:280,reloadAfterSubmit:false}, // add options
{reloadAfterSubmit:false}, // del options
{} // search options
);
});
</script>
</head>
<body>
<table id="list"><tr><td/></tr></table>
<div id="pager"></div>
</body>
</html>
I suppose that the origin of the problem which you have is in filling of the grid. During filling of the grid all grid's rows (<tr> elements) get the id attribute. During editing and deleting of the rows the value of id attribute of the corresponding row will be send always to the server. It's important to know that the values of id attributes have to be unique on the page. If the values of inv_id are unique, that you can use this values directly as the id. To inform jqGrid about the choice you can either add jsonReader: {id: "inv_id"} as additional grid parameter or just to add key: true property to the definition of the inv_id column.
I don't use Perl Catalyst myself, but the part where you fill the grid data (see my $single_row = { cell => [...]}) seems to me should contain id property additionally to cell property (something like $single_row = {cell => [...], id => $inv->inv_id}). If the inv_id is unique it would be better enough to add key: true to the definition of the inv_id column and your problem will be already solved.
If you already use another value of id and you really need to have both values: the id and inv_id then you can use for example onclickSubmit callback of delete options. The
onclickSubmit: function (options, rowid) {
return {inv_id: $(this).jqGrid("getCell", rowid, "inv_id")};
}
I mean to use the following
$("#list").jqGrid('navGrid', '#pager', {}, //options
{height: 280, reloadAfterSubmit: false}, // edit options
{height: 280, reloadAfterSubmit: false}, // add options
{ // del options
reloadAfterSubmit: false,
onclickSubmit: function (options, rowid) {
return {inv_id: $(this).jqGrid("getCell", rowid, "inv_id")};
}
}
);
As the result the data posted to the server during Delete operation will be extended with additional parameter inv_id.