I have 5 regions: Region1, Region2, Region3, Region4, Region5.
Within each region is a number of Proctors (for testing): For Region1 -- Mary, Jack, and Mark
When a student takes a test, a generated email is sent to all the Proctors in that Region. This is currently handled by a JSON file. I'd like for it to be handled by a table in the database. Here is the code related to gathering the information from the JSON file:
function get_region_proctors($region) {
global $CFG;
$rval = array();
$json_raw = file_get_contents($CFG->dirroot . DIRECTORY_SEPARATOR . 'jca' . DIRECTORY_SEPARATOR . 'data.json');
if (empty($json_raw)) {
throw new Exception("Unable to get json from data.json");
}
$json_data = json_decode($json_raw);
foreach($json_data->proctors as $p) {
if ($p->region == $region) {
$rval[] = $p;
}
}
return $rval;
}
Here is what the JSON file looks like:
{
"proctors" : [
{
"region" : "Region1",
"name" : "Mary Edwards",
"email" : "medwards#example.com"
},
{
"region" : "Region1",
"name" : "Jack Phillips",
"email" : "jphillips#example.com"
},
{
"region" : "Region1",
"name" : "Mark Jensen",
"email" : "mjensen#example.com"
}
]
}
The question is: how do I get the code to look at a database (array) instead of the DATA.JSON file?
EDIT:
After I used the code suggested below, I found that when I went to view or edit the Proctor list there was a javascript file that seems to do the following:
Once a Proctor is chosen, the javascript automatically sets the Region. Here's the script (I am not a javascript pro):
var proctors = [];
$(function () {
//disable region sel as proctor sel will control
$('#id_profile_field_Region').attr('disabled', 'disabled');
$('#mform1').submit(function () {
//need to reenable so php will note changes
$('#id_profile_field_Region').attr('disabled', false);
})
$.getJSON('../jca/data.json', function(json) {
proctors = json.proctors;
}).error(function() { alert("There was an error loading json. "); });
$('#id_profile_field_Proctor').change(function () {
newProctorSelected($(this).find("option:selected").text());
})
});
function newProctorSelected(pName) {
//find proctor object from json
var p = null;
for (var i = 0; i < proctors.length; i++) {
if (proctors[i].name === pName) {
p = proctors[i];
break;
}
}
if (p) {
//set the value of region based on region name of proctor
$('#id_profile_field_Region option').each(function() {
if($(this).text() === p.region) {
this.selected = true;
return;
}
});
}
else {
alert("proctor not found");
}
}
I keep getting the error message "There was an error loading JSON". Is there a way to replicate this function in PHP?
If you have a table called mdl_local_proctors with id, region, name, email
Then just use
function get_region_proctors($region) {
global $DB;
return $DB->get_records('local_proctors', array('region' => $region));
}
Related
I am working on a WebApp Add-on in Google Sheets. Below is the Addon and webapp script. I want to read validation/error message from webapp and display to user.
Like I will send message from doPost(e) like "Check Values" and user should get this as message box.
function copyData() {
var ss_id = SpreadsheetApp.getActive().getId();
//This is the Web App URL.
var url = "https://script.google.com/macros/s/<id>/exec";
var payload = {
"ss_id" : ss_id, // Modified
}
var options = {
"method" : "POST",
"payload" : payload,
"followRedirects" : true,
"muteHttpExceptions" : true,
};
var result = UrlFetchApp.fetch(url, options);
}
function doPost(e) {
var ss_id = e.parameter.ss_id; // Modified
var response = {
"status" : "FAILED",
"ss_id" : ss_id,
};
//var ss_id = ss_id[0];
//Use your spreadsheetID to get Output Sheet
var Manager_SS=SpreadsheetApp.openById('<id>');
var Manager_Sheet=Manager_SS.getSheetByName('Consolidated_Data');
var FrontDesk_ss = SpreadsheetApp.openById(ss_id);
var FrontDesk_sheet = FrontDesk_ss.getSheetByName('Data');
//Get front desk data
var sData = FrontDesk_sheet.getRange("A2:C10").getValues();
//Copy data from Front Desk to Manager Sheet.
Manager_Sheet.getRange("A2:C10").clear();
Manager_Sheet.getRange("A2:C10").setValues(sData);
//Update done after copying data.
FrontDesk_sheet.getRange('D1:D10').setValue('Done');
var response = {
"status" : "SUCCESS",
"sData" : sData,
};
return ContentService.createTextOutput(JSON.stringify(response));
}
For this example I am using a bounded script, but this should be the same for an Editor Add-on
In the spreadsheet we want to validate, we create a custom menu to call a function that makes a POST request to our Web App. Depending on the response, we display one content or another.
const UI = SpreadsheetApp.getUi()
const onOpen = () => {
/* Adds the custom menu */
UI.createMenu('Custom Function').addItem('Is Valid?', 'checkValidity').addToUi()
}
const checkValidity = () => {
const res = UrlFetchApp.fetch
(
/* Change it for your URL */
"https://script.google.com/macros/s/<ID>/exec",
{
"method": "post",
"contentType": "application/json",
/* In this example I only send the ID of the Spreadsheet */
"payload": JSON.stringify(
{
"ss_id": SpreadsheetApp.getActiveSpreadsheet().getId()
}
)
}
)
/* Depending on the response from the Web App */
/* We show different messages */
const { MSG } = JSON.parse(res.getContentText())
UI.alert(MSG === "OK" ? "IS VALID" : "IS NOT VALID")
}
After we create a Web App that validates the ID. In this example I am only validating that the ID is contained in an array of valid IDs, but this should be replaced by whatever you need. As a response I only send a simple "OK" or "NOT OK", but this can be replaced with any kind of data.
const doPost = (e) => {
/* We perform the checks we need */
/* In this example only checking if the id is contained in an array */
/* This should be changed to perform the desired checks */
const validID = ["<VALID_ID_1>","<VALID_ID_2>"]
const { ss_id } = JSON.parse(e.postData.contents)
/* SpreadsheetApp.openById(ss_id).copy("my_new_copy") */
const checker = validID.includes(ss_id)
/* We send back the response */
/* Depending on the checker value */
return ContentService.createTextOutput(JSON.stringify(
{
"MSG": checker ? "OK" : "NOT OK"
}
)).setMimeType(ContentService.MimeType.JSON)
}
Reading Validation Error from Webapp
html:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<form>
<input type="text" id="txt1" name="id" placeholder="Enter Numbers only"/>
<input type="button" value="submit" onClick="processForm(this.parentNode);" />
</form>
<script>
function processForm(obj) {
console.log(obj.id.value);
if(obj.id.value.match(/[A-Za-z]/)) {
google.script.run.displayError("Invalid Characters Found in id field");
} else {
google.script.run.sendData(obj);
}
}
</script>
</body>
</html>
GS:
function doPost(e) {
Logger.log(e.postData.contents);
Logger.log(e.postData.type);
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName("Sheet1");
let data = JSON.parse(e.postData.contents);
let row = [];
Object.keys(data).forEach(k => row.push(data[k]));
Logger.log(JSON.stringify(row))
sh.appendRow(row);
}
function sendData(obj) {
const url = ScriptApp.getService().getUrl();
const params={"contentType":"application/json","payload":JSON.stringify(obj),"muteHttpExceptions":true,"method":"post","headers": {"Authorization": "Bearer " + ScriptApp.getOAuthToken()}};
UrlFetchApp.fetch(url,params);
}
function displayError(msg) {
SpreadsheetApp.getUi().alert(msg);
}
function launchMyDialog() {
SpreadsheetApp.getUi().showModelessDialog(HtmlService.createHtmlOutputFromFile('ah1'),'My Dialog');
}
I posted about this issue not that long ago, and I thought I had figured it out but nothing is happening.
Issue: I am trying to generate a PDF file that captures the signature of a client. Essentially they type in their name in a box and that name gets displayed in the pdf.php file along with all the other information(e.g. date, terms & conditions etc..).
I created a class that extends from FPDF and though JavaScript I am sending the name that gets filled and it gets processed through that pdf.php file and should return a "signed" pdf file.
However my pdf file is not downloading, saving or any of the options (I, D, F, S).
Below is a snippet of that section in my code.
pdf.php
$tempDir = "C:/PHP/temp/";
$thisaction = filter_input(INPUT_POST, 'action', FILTER_SANITIZE_STRING);
$answers = filter_input(INPUT_POST, 'encFormData');
$decFD = json_decode($answers);
$pdf = new WaiverFPDF();
// Pull values from array
$returnVals = array();
$returnVals['result'];
$returnVals['html'] = '';
$returnVals['errorMsg'] = '';
//the name of the person who signed the waiver
$name = $decFD->signWaiver;
$today = date('m/d/Y');
if($thisaction == 'waiverName'){
// Generate a new PDF
$pdf = new WaiverFPDF();
$pdf->AddPage()
$pdfFile = "Waiver". $name . ".pdf";
....
// Output form
$pdf->Write(8, 'I HEREBY ASSUME ALL OF THE RISKS...');
// Line Break
$pdf-> all other info...
$outFile = $tempDir . $pdfFile;
//output pdf
$pdf->Output('D', $pdfFile);
$returnVals['result'] = true;
}
else{
$returnVals['errorMsg'] = "There was an error in waiver.php";
$returnVals['result'] = false;
}
echo json_encode($returnVals);
?>
.js file (JSON)
function sendWaiver(){
var formHash = new Hash();
formHash.signWaiver = $('signWaiver').get('value');
console.log ("name being encoded");
waiverNameRequest.setOptions({
data : {
'encFormData' : JSON.encode(formHash)
}
}).send();
return true;
}
waiverNameRequest = new Request.JSON({
method : 'post',
async : false,
url : 'pdf.php',
data : {
'action' : 'waiverName',
'encFormData' : ''
},
onRequest : function() {
// $('messageDiv').set('html', 'processing...');
console.log("waiver onRequest");
},
onSuccess : function(response) {
$('messageDiv').set('html', 'PDF has been downloaded');
if (response.result == true) {
console.log('OnSuccess PDF created');
} else {
$('messageDiv').set('html', response.errorMsg);
console.log('PDF error');
}
}
});
I know my error handling is very simple, but all I am getting is success messages, but no generated pdf file... I'm not sure what i am doing wrong. I also made sure the file (when i save to a file) is writable.
class_WaiverFPDF.php
class WaiverFPDF extends FPDF
{
// Page header
function Header()
{
// Arial bold 15
$this->SetFont('Arial','B',12);
// Position XY X=20, Y=25
$this->SetXY(15,25);
// Title
$this->Cell(179,10, 'Accident Waiver ','B','C');
// Line break
$this->Ln(11);
}
// Page footer
function Footer()
{
// Position from bottom
$this->SetY(-21);
// Arial italic 8
$this->SetFont('Arial','I',8);
$this->Ln();
// Current date
$this->SetFont('Arial','I',8);
// $this->Cell(179,10,$today,0,1,'R',false);
// $today= date('m/d/Y');
$this->Cell(115,10,' Participant Name',0,0,'C');
$this->Cell(150,10,'Date',0,'C',false);
// Page number
//$this->Cell(0,10,'Page '.$this->PageNo().'/{nb}',0,0,'C');
}
}
Here i am getting my Error Messages from a separate page and i am displaying it in a a div called #stage_error
$('#stage_error').html(error_string);
So, the errors will be displayed like this
The bus no field is required.
The comp id field is required.
The total seats field is required.
But what i want is to display the errors in its respective div's
i.e., the Bus no should be displayed near the div <div id='busno'> like this.
How can i do that ?
Json :
{"busno":["Bus No field is required"],"Comp Id":["Comp Id is required."]}
Update :
Script for request and showing error :
<script>
$(document).ready(function() {
$("#driver").click(function(event) {
var BusNo = $("#BusNo").val();
var CompID = $("#CompID").val();
var TotalSeats = $("#TotalSeats").val();
var _token = $("#_token").val();
$.post("managebus_register", {
_token: _token,
BusNo: BusNo,
CompID: CompID,
TotalSeats: TotalSeats
},
function(data) {
if (data != '') {
obj = JSON.parse(data);
var error_string = '';
$.each(obj, function(entry) {
error_string += obj[entry] + '<br/>';
});
$('#stage_error').html(error_string);
} else {
$('#stage_success').text('Resistered Succesfully');
$("#stage_error").hide();
}
});
});
});
</script>
Laravel Controller :
public function managebusregister()
{
$BusNo = Input::get('BusNo');
$CompID = Input::get('CompID');
$TotalSeats = Input::get('TotalSeats');
$data = Input::except(array('_token')) ;
$rule = array(
'BusNo' => 'required|unique:company_bus',
'CompID' => 'required',
'TotalSeats' => 'required|max:50'
) ;
$validator = Validator::make($data,$rule);
if ($validator->fails())
{
$messages = $validator->messages();
return json_encode($validator->messages()); //php encoded value
}
else
{
DB::insert('insert into company_bus (BusNo, CompID, TotalSeats) values (?, ?, ?)',
array($BusNo, $CompID, $TotalSeats));
return '';
}
}
Html Code :
<div id="stage_error" style="color:red;font-size:15px"></div>
<div id="stage_success" style="color:green;font-size:20px"></div>
and beyond that i have each field input boxes,
<input type="text" id="BusNo" name="BusNo"/>
<input type="text" id="CompID" name="CompID"/>
How can i throw error messages near the respective fields
Below is the approach: Observe I've added spans with error after text boxes.
CSS
<style>
.error { color:red; font-size:15px; }
</style>
Html
<input type="text" id="BusNo" name="BusNo" /><span class="error"></span>
<input type="text" id="CompID" name="CompID" /><span class="error"></span>
JavaScript I did some changes as per the jQuery standard, it should work well, if you're not interested then you can ignore all the changes but can take only below mentioned if logic block.
The error display added in if (!data) {...}
$(function () {
$(document).on("click", "#driver", function (event) {
var BusNo = $("#BusNo").val(),
CompID = $("#CompID").val(),
TotalSeats = $("#TotalSeats").val(),
_token = $("#_token").val();
$.post("managebus_register", {
_token: _token,
BusNo: BusNo,
CompID: CompID,
TotalSeats: TotalSeats
}).done(function (data) {
$("span.error").empty();//All previous error messages cleared here.
if (!data) {
var obj = JSON.parse(data);
//obj = {"busno":["Bus No field is required"],"Comp Id":["Comp Id is required."]}
$.each(obj, function (entry) {
var targetSelector='';
if (entry == "busno") {
targetSelector = "#BusNo";
}
if (entry == "Comp Id") {
targetSelector = "#CompID";
}
if(targetSelector) //Here we're setting error message for respective field
$(targetSelector).next("span.error").html(obj[entry]);
});
} else {
$('#stage_success').text('Resistered Succesfully');
$("#stage_error").hide();
}
});
});
});
you can try like this:
var json = JSON.parse('{"busno":["Bus No field is required"],"Comp Id":["Comp Id is required."]}');
// alert(json['busno']);
$("#busno").html(json.busno);// like this for others also.
change here:
obj = JSON.parse(data);
var error_string = '';
$.each(obj, function(entry) {
error_string += obj[entry] + '<br/>';
if(entry == 'busno'){
$("#busno").html(obj[entry]);// like this for others also.
}
if(entry == 'Comp Id'){
$("#compid").html(obj[entry]);// like this for others also.
}
});
$('#stage_error').html(error_string);
I'm trying to fill a form if I find that the name and the firstname input by the user already exist in my database.
For the moment, I would like to check if the name and the firstname already exist in the database but my javascript program doesn't work. It's seems that the part..." "$.post("../modules/verifier_staff.php",{ nom: ..." is not correct.
Then I would like to fill my form with the data that my database give (array).
Can somenone help me to find my mistakes and to tell me how I can use the data i receive from database to fill my form?
$(document).ready(function(){
var form_nom = $("#staff_nom");
var form_prenom = $("#staff_prenom");
$(form_nom).change(function() {
checkvariable();
});
$(form_prenom).change(function() {
checkvariable();
});
function checkvariable(){
if((form_nom.val().length >0)&&(form_prenom.val().length>0)){
prenom_staff = form_prenom.val();
nom_staff = form_nom.val();
//alert(nom_staff);
$.post("../modules/verifier_staff.php",{ nom: nom_staff, prenom: prenom_staff},
function(data){
if(data)
{
alert('ok');
}
else alert('nok');
});
}
}
});
var form_nom = $("#staff_nom");
var form_prenom = $("#staff_prenom");
$(form_nom).change(function() {
checkvariable(form_nom,form_prenom); //pass arguments into the function
});
$(form_prenom).change(function() {
checkvariable(form_nom,form_prenom);
});
function checkvariable(form_nom,form_prenom){ //innclude argument in function definition
//......
}
thank for your help. Yes I'm sure that the path is correct.
Here is my code from ../modules/verifier_staff.php
<?php
include('../inc/settings.php');
include('../inc/includes.php');
//$_POST['nom']='Doe';
//$_POST['prenom']='John';
$nom=$_POST['nom'];
$prenom=$_POST['prenom'];
$Dbcon = new Db;
$personne_manager = new PersonneManager($Dbcon->dbh);
$personne = $personne_manager->get(array('conditions'=> array('nom' => strtolower($nom),'prenom' => strtolower($prenom))));
if($personne)
{
$result = true;
}
else
{
$result = false;
}
return $result;
?>
this part works well (I tested it) so I think the problem come from my javascript code. I'm a newbie in javascript/jquery.
i'm getting the error : Uncaught ReferenceError: errorHandler is not defined at file:
what am i doing wrong? source code: http://pastebin.com/3203ynUB
i iniate the first piece with onclick="startBackup()"
it seems to go wrong somewhere in retrieving data from the database, but i cant figure out how and where.
the database is as following
DBName: SmartPassDB
Table name: SmartPass
rows: id , name , nickName , passID , Website
// change to your database
var db = window.openDatabase("Database", "1.0", "SmartPassDB", 5*1024); // 5*1024 is size in bytes
// file fail function
function failFile(error) {
console.log("PhoneGap Plugin: FileSystem: Message: file does not exists, isn't writeable or isn't readable. Error code: " + error.code);
alert('No backup is found, or backup is corrupt.');
}
// start backup (trigger this function with a button or a page load or something)
function startBackup() {
navigator.notification.confirm('Do you want to start the backup? This will wipe your current backup. This action cannot be undone.', onConfirmBackup, 'Backup', 'Start,Cancel');
}
// backup confirmed
function onConfirmBackup(button) {
if(button==1) {
backupContent();
}
}
// backup content
function backupContent() {
db.transaction(
function(transaction) {
transaction.executeSql(
// change this according to your table name
'SELECT * FROM SmartPass;', null,
function (transaction, result) {
if (result.rows.length > 0) {
var tag = '{"items":[';
for (var i=0; i < result.rows.length; i++) {
var row = result.rows.item(i);
// expand and change this according to your table attributes
tag = tag + '{"id":"' + row.attribute1 + '","name":"' + row.attribute2 + '","nickName":"' + row.attribute3 + '","passId":"' + row.attribute4 + '","website":"' + row.attribute5 + '"}';
if (i+1 < result.rows.length) {
tag = tag + ',';
}
}
tag = tag + ']}';
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function(fileSystem) {
// Change the place where your backup will be written
fileSystem.root.getFile("backup.txt", {create: true, exclusive: false}, function(fileEntry) {
fileEntry.createWriter(function(writer) {
writer.write(tag);
}, failFile);
}, failFile);
}, failFile);
alert("Backup done.");
} else {
alert("No content to backup.");
}
},
errorHandler
);
}
);
}
// start restore (trigger this function with a button or a page load or something)
function startRestore() {
navigator.notification.confirm('Do you want to start the restore? This will wipe your current data. This action cannot be undone.', onConfirmRestore, 'Restore', 'Start,Cancel');
}
// restore confirmed
function onConfirmRestore(button) {
if(button==1) {
restoreContent();
}
}
// restore content
function restoreContent() {
db.transaction(
function(transaction) {
transaction.executeSql(
// change this according to your table name
'DELETE FROM SmartPass', startRestoreContent()
);
});
}
// actually start restore content
function startRestoreContent() {
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function(fileSystem) {
// Change the place where your backup is placed
fileSystem.root.getFile("backup.txt", null, function(fileEntry) {
fileEntry.file(function(file) {
var reader = new FileReader();
reader.onloadend = function(evt) {
var data = JSON.parse(evt.target.result);
var items = data.items;
count = items.length;
db.transaction(
function(transaction) {
$.each(items, function(index, item) {
transaction.executeSql(
// change and expand this according to your table name and attributes
'INSERT INTO SmartPass (id, name, nickName, passId, website) VALUES (?, ?, ?, ?, ?)',
[item.attribute1, item.attribute2, item.attribute3, item.attribute4, item.attribute5],
null
);
});
});
};
reader.readAsText(file);
alert("Restore done.");
}, failFile);
}, failFile);
}, failFile);
}
As per the error
error : Uncaught ReferenceError: errorHandler is not defined at file:
The function errorHandler is not defined in the code.
In your function backupContent() {..} you have used errorHandler as callback reference for the transaction.executeSql() call.
transaction.executeSql(....,errorHandler)
You need to define the errorHandler function.
Also you need to consider a scenario as to how do you handle initial database load. If you run the code for the first time there will not be any tables. The following sql statement will fail.
SELECT * FROM SmartPass;
The table SmartPass is not yet created. That is the most likely reason of the errorHandler being called.