I have a timesheet that several of my employees use and fill out daily. I'd like to add the feature for them to be able hit 'Save' and then later on they can load what they saved back into the time sheet.
I have the save part working just fine. It just saves the data in the sheet to some tables in a database. The real issue/question I have is what is the best way to get this loaded back into the database? I've done some very simple save/load stuff before but only with a single field. I used an ajax call like this:
function grabTransportNum(strURL) {
var req = getXMLHTTP();
if (req) {
req.onreadystatechange = function() {
if (req.readyState == 4) {
// only if "OK"
if (req.status == 200) {
document.getElementById('tandt1').innerHTML=req.responseText;
} else {
alert("There was a problem while using XMLHTTP:\n" + req.statusText);
}
}
}
req.open("POST", strURL, true);
req.send(null);
}
}
All this does is pull out a single number and sets the value of 'tandt1' to whatever number is returned. Doing this for every field sounds easy enough, but depending on how much is saved, I may need to load data into 100+ fields. Having a function like this for every single field sounds absolutely awful, so I figure there must be a better way to go about this. Could I get some suggestions?
What you could do is instead of sending a single field from the server, send a JSON that has multiple fields, like:
{
"fields": [
{ "id": "tandt1", "value": "persisted value"},
//in here you'd have the rest of the fields in the same format
]
}
then change your function to something more like this:
function reloadFields(strURL) {
var req = getXMLHTTP();
if (req) {
req.onreadystatechange = function () {
if (req.readyState == 4) {
// only if "OK"
if (req.status == 200) {
var data = JSON.parse(req.responseText);
if (data && data.fields && data.fields.length > 0) {
for (var field,i=0;i<data.fields.length;i++) {
field = data.fields;
document.getElementById(field.id).innerHTML = field.value;
}
}
} else {
alert("There was a problem while using XMLHTTP:\n" + req.statusText);
}
}
}
req.open("POST", strURL, true);
req.send(null);
}
}
A tidy way to do it would be for the javascript on the page to set a flag for any field that is changed. Then when the employee submits the data, the only data which is actually sent is the change(s) made. So if you're using ajax, here's what I would suggest: for each edit the user makes, add the changes to an object which you will send via ajax when the user hits submit.
Related
I am creating a few functions related to creating and updating custom schema values for both the domain and its users. I have set a variable for the custom schema that needs to be updated, but, for a specific function, I can't seem to use it. It works for the Logger.log part, but not for the update request. It looks like I must use a hard-coded vale.
This is my function (the variable in question is "schemaSafeName"):
`
function updateUserSchemaNew() {
var myEmailAdress = Session.getActiveUser().getEmail();
var schemaSafeName = 'Test_Schema_Group';
try{
AdminDirectory.Users.update({
'customSchemas': {
schemaSafeName: {
'Test_field1':false,
'Test_field2':true
}
}
},
myEmailAdress);
Logger.log(AdminDirectory.Users.get(myEmailAdress,{fields: 'customSchemas',projection: 'Custom',customFieldMask: schemaSafeName}));
} catch(error){
const {code, message} = error.details;
if(code === 400 || code === 404 || code === 409 || code === 412){
console.log("Error 400 or 404 or 409 or 412");
} else {
console.log(`${code} - ${message}`);
}
}
}
`
Note that everything works if I keep it harcoded (without using a variable), as shown below, but that defies the purpose of what I'm trying to achieve (a spreadsheet to manage bulk actions on Google Workspace, without having to edit the script every time I need to update a diferent schema).
So, this works, but it's static:
`
function updateUserSchema() {
var myEmailAdress = Session.getActiveUser().getEmail();
try{
AdminDirectory.Users.update({
'customSchemas': {
'Test_Schema_Group': {
'Test_field2':false,
'Test_field2':true
}
}
},
myEmailAdress);
Logger.log(AdminDirectory.Users.get(myEmailAdress,{fields: 'customSchemas',projection: 'Custom',customFieldMask: 'Test_Schema_Group'}));
} catch(error){
const {code, message} = error.details;
if(code === 400 || code === 404 || code === 409 || code === 412){
console.log("Error 400 or 404 or 409 or 412");
} else {
console.log(`${code} - ${message}`);
}
}
}
`
Is there a way to do this, or do you think that this is a limitation of the schema update process for users? Or of the way that the values and sub-values are structured?
Thanks in advance for any help.
In your script, how about the following modification?
From:
AdminDirectory.Users.update({
'customSchemas': {
schemaSafeName: {
'Test_field1':false,
'Test_field2':true
}
}
},
myEmailAdress);
To:
AdminDirectory.Users.update({
'customSchemas': {
[schemaSafeName]: { // <--- Modified
'Test_field1':false,
'Test_field2':true
}
}
},
myEmailAdress);
In this modification, schemaSafeName is modified to [schemaSafeName]. By this, var schemaSafeName = 'Test_Schema_Group'; is used as the key.
Reference:
Computed property names
I'm trying to create a script that sends an email when someone submits a google form. The form includes an optional file upload that the script will then attach to the email as a pdf.
The issue I'm facing is how to ignore the process that creates the attachment if the response is empty.
Sample code below
function getIdFrom(url) {
var id = '';
var parts = url.split(
/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/
);
if (url.indexOf('?id=') >= 0) {
id = parts[6].split('=')[1].replace('&usp', '');
return id;
} else {
id = parts[5].split('/');
var sortArr = id.sort(function (a, b) {
return b.length - a.length;
});
id = sortArr[0];
return id; //returns google doc id.
}
}
function onFormSubmit(response) {
var link = response.namedValues['Upload file'];
if (typeof link !== "undefined" && link.length > 0) { // I think it's here that's the issue
var uploadFileId = getIdFrom(link[0]);
var uploadFile = DriveApp.getFileById(uploadFileId);
var uploadFileType = (function () {
if (uploadFile.getMimeType().includes('image')) {
return uploadFile.getMimeType();
} else {
return 'application/pdf';
}
};
var attachArr = [uploadFile.getAs(uploadFileType)];
}
// etc etc send email.
}
Works fine if the user submits a form with an uploaded file.
However if the form is submitted without entering anything in the "Upload File" question, I'm getting a "TypeError: Cannot read property 'split' of undefined" at the getIdFrom(url) function I assume because it's still trying to pass link through getIdFrom() even though it shouldn't because it's undefined.
Weirdly it works perfectly fine when I use the two test inputs I have, one of which 'Upload File' exists but is empty and the other it doesn't exist at all.
I'm not sure what I'm missing here.
Also I have no doubt it's a messy way to do things but I'm getting there.
response.namedValues['Upload file'] is an object
even if it's empty it will have at least the length of >0
Workaround
Modify your if statement to
if (link[0].length > 0) {
...
}
As a starter in html world, i would like to know and start using simple APIs to insert into my blog posts.
I tried to include as html values some simple API like: https://bitcoinfees.earn.com/api/v1/fees/recommended and I used examples given here: Display Json data in HTML table using javascript and some others more like: http://jsfiddle.net/sEwM6/258/
$.ajax({
url: '/echo/json/', //Change this path to your JSON file.
type: "post",
dataType: "json",
//Remove the "data" attribute, relevant to this example, but isn't necessary in deployment.
data: {
json: JSON.stringify([
{
id: 1,
firstName: "Peter",
lastName: "Jhons"},
{
id: 2,
firstName: "David",
lastName: "Bowie"}
]),
delay: 3
},
success: function(data, textStatus, jqXHR) {
drawTable(data);
}
});
function drawTable(data) {
var rows = [];
for (var i = 0; i < data.length; i++) {
rows.push(drawRow(data[i]));
}
$("#personDataTable").append(rows);
}
function drawRow(rowData) {
var row = $("<tr />")
row.append($("<td>" + rowData.id + "</td>"));
row.append($("<td>" + rowData.firstName + "</td>"));
row.append($("<td>" + rowData.lastName + "</td>"));
return row;
}
but the result is always blank.
Please, can you give me some hint to can use that API and insert that numbers values for "fastestFee","halfHourFee","hourFee" as html values?
Thank you all!
Welcome to the html world. You are certainly right in assuming that data from APIs is a great way to make your websites more dynamic.
There is an example on W3 Schools on how to handle a http request. I think this is a good place to start https://www.w3schools.com/xml/xml_http.asp. You create a http object that does some sort of data fetching. In this example it is done with the xhttp.send(). At the same time you have a listener that monitors if the onreadystatechange property of the xhttp has changed. And if that change is status 200 (success) then perform some actions.
Here is my JSfiddle with example from your API
http://jsfiddle.net/zvqr6cxp/
Typically these actions would be to structure the returned data and then do something with the data, like show them in a table.
The example shows the native html xhttp object in use with an event listener. Typically as you learn more about this you would probably start using a framework such as jquery or Angular that can handle http requests smoother, keyword here is callback functions.
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
//In this example, I used your API link..first I would do is turn the JSON into a JS object
myObject = JSON.parse(xhttp.responseText)
document.getElementById("fast").innerHTML = myObject.fastestFee
document.getElementById("half").innerHTML = myObject.halfHourFee
document.getElementById("hour").innerHTML = myObject.hourFee
}
};
xhttp.open("GET", "https://bitcoinfees.earn.com/api/v1/fees/recommended", true);
xhttp.send();
I am working on a check in app, that uses a SQL server database to store and get the People
if the app is online, and uses local storage to store people when it is offline , which will push these changes into the database once it comes back online.
my controller currently goes like this
function DemoController($scope,localStorageService,$http,$resource,$interval)
{
$scope.online = "";
$scope.checkConnection=function()
{
check=window.navigator.onLine;
if(!check)
{
$scope.online="offline";
return false;
}
else
{
$scope.online="online";
return true;
}
}
if($scope.checkConnection() == true){
$scope.Get = function(){
$http.get(url).success{function(res)
{
$scope.People = res;
$scope.setPeople();
}
}
//basically the edit and delete function for those people
$scope.setPeople = function() {};
$scope.deletePeople = function(){};
}
else if ($scope.checkConnection == false)
{
// use same methods/functions but with local storage
$scope.pushAll = function (){ %http.put(url)}
//here is the part i do not understand
if checkConnection switches from offline to online
{
$scope.pushAll();
}
}
$scope.intervalCheck = function()
{
var intervalPromise;
intervalPromise = $interval($scope.checkConnection(), 250);
};
$scope.intervalCheck();
}
And the other problem is that even if it switches from online to offline or vise-versa I doesn't switch the methods it uses (online/offline methods).
I am not sure if there is a proper way to actually write this but i Hope there is, if this is too vague I can edit the post with more details.
I think you should try using cookies for that. to store offline data
but large data in cookies, is discouraged so be careful.
I have been searching how to put more than one function in onchange and I found how something like this for example: onchange = "function1(); function2();".
My problem here is I have followed what does the example like, but only function1 is working, function2 is not working. If I make it otherwise to onchange = "function2(); function1();", only function2 is working, function1 is not working, the same.
Any ideas guys?
Thanks.
The functions, I used Ajax:
function1(test)
{
var kode = test.value;
if (!kode) return;
xmlhttp.open('get', '../template/get_name-opr.php?kode='+kode, true);
xmlhttp.onreadystatechange = function() {
if ((xmlhttp.readyState == 4) && (xmlhttp.status == 200))
{
//alert(kode);
document.getElementById("code").innerHTML = xmlhttp.responseText;
}
return false;
}
xmlhttp.send(null);
}
function2(test)
{
var kode = test.value;
if (!kode) return;
xmlhttp**1**.open('get', '../template/get_name2-opr.php?kode='+kode, true);
xmlhttp**1**.onreadystatechange = function() {
if ((xmlhttp**1**.readyState == 4) && (xmlhttp**1**.status == 200))
{
//alert(kode);
document.getElementById("code2").innerHTML = xmlhttp**1**.responseText;
}
return false;
}
xmlhttp**1**.send(null);
}
To solve my problem, I created two xmlhttp different. (xmlhttp and xmlhttp1).
Go through the link I gave, it seems to be problem with the way you are managing the xmlhttprequest objects, manage their instances properly, in your case because you are using the same xmlhttprequest for two simultaneous AJAX requests, only one of them is getting served. Either wait for one of them to get served or create two instances of the xmlhttprequest.
The statement xmlhttp.readystate = function() {...} obviously replaces the readystate property of that xmlhttprequest object, so on your second function, that is being replaced( because you are using the xmlhttprequest for both of them ). This is why you are seeing the funny behaviour.
Call function2() at the end of function1().
onchange = "function1()"
function1(){
...
function1 body;
...
function2()
}
Wrap the two function calls in one and call that function!
function myFirstFunction() {
//body
}
function mySecondFunction() {
//body
}
//Call this guy.
function myWrappedFunction() {
myFirstFunction();
mySecondFunction();
}