Google App Script setTimeout Function problem - javascript

I have a typical Google App Html form that records the data entered in a spreasheet.
Here are the files.
HTML Form:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<?!= include("css");?>
</head>
<body>
<h2>Feedback Form</h2>
<div id="message"></div>
<!--- BUTTON New registration --->
<br /><input id="button-responder" type ="button" value = "New registration"
onclick="submitResponder('button-responder'),
submitTransition('message');" style="display:none;" />
<!--- FORM --->
<form id="my-form">
<br /><input id="name" type="text" name="name" placeholder="Your Name">
<br /><input id="email" type="email" name="email" placeholder="Your Email">
<br /><textarea id="comment" rows="10" cols="40" name="comment"></textarea>
<!--- BUTTON submitForm --->
<br /><input id="btn" type="button" value="Submit"
onclick="submitForm(this.parentNode),
document.getElementById('my-form').style.display='none',
submitResponder('button-responder'),submitTransition('message');" />
</form>
<?!= include("test-js");?>
</body>
</html>
Google Script:
function doGet(request) {
return HtmlService.createTemplateFromFile('index')
.evaluate();//not all caps but it has to match the name of the file and it doesn't - Change to PAGE
}
function include(filename) {
return HtmlService.createHtmlOutputFromFile(filename)
.getContent();
}
function submitData(form) {
var subject='New Feedback';
var body=Utilities.formatString('name: %s <br />Email: %s<br />Comment: %s', form.name,form.email,form.comment);
var folderId = "my-folder-ID"; // Please set the folder ID. // Added
var blob = Utilities.newBlob(body, MimeType.HTML, form.name).getAs(MimeType.PDF); // Added
var file = DriveApp.getFolderById(folderId).createFile(blob); // Added
return Utilities.formatString('name: %s <br />Email: %s<br />Comment: %s<br />
PDF: <a target="_blank" href="%s">see your PDF file</a>',
form.name,form.email,form.comment,file.getUrl());
function userClicked(userInfo){
var url = "https://docs.google.com/spreadsheets/d/my-spreadsheet-ID";
var ss = SpreadsheetApp.openByUrl(url);
var ws = ss.getSheetByName("Data");
ws.appendRow([userInfo.name, userInfo.email, userInfo.comment]);
}
test-js
<script>
function submitForm(form) {
google.script.run
.withSuccessHandler(function(value){
document.getElementById('message').innerHTML = value;
document.getElementById('name').value = '';
document.getElementById('email').value = '';
document.getElementById('comment').value = '';
})
.submitData(form);
}
function submitResponder() {
var x = document.getElementById("button-responder");
var xx = document.getElementById("my-form");
var xxx = document.getElementById("message");
if (x.style.display === "none") {
x.style.display = "block";
xx.style.display = "none";
xxx.style.display = "block";
} else {
x.style.display = "none";
xx.style.display = "block";
xxx.style.display = "none";
}
}
function submitTransition() {
setTimeout(function() {
document.getElementById('message').style.color = 'blue';}, 2500);
}
document.getElementById("btn").addEventListener("click",doStuff);
function doStuff(){
var userInfo = {}
userInfo.name = document.getElementById("name").value;
userInfo.email = document.getElementById("email").value;
userInfo.comment = document.getElementById("comment").value;
google.script.run.userClicked(userInfo);
document.getElementById("name").value= "";
document.getElementById("email").value= "";
document.getElementById("comment").value= "";
}
</script>
css:
<style>
#message {
color: transparent;
}
</style>
QUESTION
Now in Google Script file function
function submitData (form)
and in test-js file function
function doStuff ()
they do their job well but with a latency of around 2.5s
then for Google Script to file the function
return Utilities.formatString
can show the result (name - email - comment - PDF Url)
its conclusion must be awaited, 2.5s.
Functions in variables.
In test-js file function
function submitResponder ()
makes the fields linked to the ID (message) visible with variables
name: example-name
email: example-email
comment: example-comment
PDF: see your example-PDF file
and the field linked to the ID (button-responder)
"New registration" button
Then upon loading the index.html page
the form and the "submit" button are shown,
edit the fields by clicking on submit
the form is hidden, the "New registration" button appears
and after about 2.5s the edited fields (name-email ....) also appear.
Click on the button "New registration" below
the form reappears as at the beginning, clearly not with a reload page, but simply with
display = "none"
display = "block"
Now here's the problem I can't solve:
By re-editing the fields and clicking again on submit-form
the fields edited the previous time appear again immediately
name: example-name
email: example-email
comment: example-comment
PDF: see your example-PDF file
and after about 2.5s they update with the new edited fields
name: new-name
email: new-email
comment: new-comment
PDF: see your new-PDF file
Now with the function
function submitTransition () {
setTimeout (function () {
document.getElementById ('message'). style.color = 'blue';}, 2500); }
and with style
#message { color: transparent; }
I'm trying to find a solution to delay (hide) the display of the old fields until the new ones are updated.
It is certainly not the right way.
I hope I have been clear in the explanation, your help will be very much able.
Thanks in advance.

You want to show the texts and button of "New registration" after "submit" button was clicked and the script of submitData was finished.
If my understanding is correct, how about this modification?
The reason of your issue is that google.script.run is run with the asynchronous process. By this, before the script of submitData is finished, document.getElementById('my-form').style.display='none', submitResponder('button-responder') and submitTransition('message') are run.
Modified script:
Please modify your script as follows.
From:
<br /><input id="btn" type="button" value="Submit"
onclick="submitForm(this.parentNode),
document.getElementById('my-form').style.display='none',
submitResponder('button-responder'),submitTransition('message');" />
To:
<br /><input id="btn" type="button" value="Submit" onclick="submitForm(this.parentNode)" />
And
From:
function submitForm(form) {
google.script.run
.withSuccessHandler(function(value){
document.getElementById('message').innerHTML = value;
document.getElementById('name').value = '';
document.getElementById('email').value = '';
document.getElementById('comment').value = '';
})
.submitData(form);
}
To:
function submitForm(form) {
google.script.run
.withSuccessHandler(function(value){
document.getElementById('message').innerHTML = value;
document.getElementById('name').value = '';
document.getElementById('email').value = '';
document.getElementById('comment').value = '';
document.getElementById('my-form').style.display='none'; // Added
submitResponder('button-responder'); // Added
submitTransition('message'); // Added
})
.submitData(form);
}
And, by above modification, you can also remove setTimeout as follows.
From:
function submitTransition() {
setTimeout(function() {
document.getElementById('message').style.color = 'blue';}, 2500);
}
To:
function submitTransition() {
document.getElementById('message').style.color = 'blue';
}
Reference
Class google.script.run (Client-side API)
google.script.run is an asynchronous client-side JavaScript API available in HTML-service pages that can call server-side Apps Script functions.
If I misunderstood your question and this was not the result you want, I apologize.

Related

I want to display google script single cell value in html text box on button event

I am totally new and try to learn the script...pls someone help to resolve this issue
simply i wanna to get google script cell value and show to this in text box
GS code
function doGet(e) {
return HtmlService.createHtmlOutputFromFile('WebAppSecure');
htmlOutput.message = '';
return htmlOutput.evaluate();
}
function getValues(){
var url = "url link";
var ss = SpreadsheetApp.openByUrl(url);
var webAppSheet = ss.getSheetByName("Sheet4");
var getRange=webAppSheet.getRange(2,1).getValues();
console.log(getRange);//output value :23:43 PM Info Sunil
}
html side
function getresult(){
google.script.run.withSuccessHandler(function(output) {
var iterm=document.getElementById("dname").value;
}).getValues(name);
console.log(name);
}
<input type="text" id="dsrn" />
<input type="button" id="button2" value="ID_Search1" onclick="getresult()"/>
I don't wish to create a doGet() so here's the same thing done with a dialog:
GS:
function launchMyDialog() {
SpreadsheetApp.getUi().showModelessDialog(HtmlService.createHtmlOutputFromFile('ah1'),'Dialog Title');
}
function getMyValue() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName('Sheet0');
return sh.getRange(2,1).getValue();
}
html:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<input type="text" id="txt"/>
<br /><input type="button" value="Get Data" onClick="getValue();" />
<script>
function getValue() {
google.script.run
.withSuccessHandler((v) => {document.getElementById("txt").value = v;})
.getMyValue();
}
console.log("my code")
</script>
</body>
</html>

use variable from js file into another js file

I am doing an autofill extension for chrome. I made the html file where user put his information and i want that these information will be saved, because i need to use that information as a variable from a js file.
This is the html popup:
<html>
<head></head>
<body>
<div class="simple-form">
<form method="post">
<input type="text" name="fname" id="full_name" placeholder="Write here your full name"><br><br>
<input type="email" name="email" id="email" placeholder="Write here your email"><br><br>
<input id="save" type="button" value="Salva">
</form>
</div>
<script type="text/javascript" src="scriptExport.js"></script>
</body>
</html>
and this is the js file:
const button = document.getElementById('save');
button.addEventListener('click', updateButton);
function updateButton() {
if (button.value === 'Save') {
button.value = 'Done';
var full_name_E = document.getElementById('full_name').value;
var email_E = document.getElementById('email').value;
}
else {
button.value = 'Save';
}
}
I need to load full_name_E and email_E in another js file that is the autofiller.
I tried with import and export but it doesn't work.
Your problem is, that full_name_E and email_E are only available in the local scope of the function updateButton. To make the available at the global scope, initialize them at the top of your code:
const button = document.getElementById('save');
var full_name_E;
var email_E;
button.addEventListener('click', updateButton);
function updateButton() {
if (button.value === 'Save') {
button.value = 'Done';
full_name_E = document.getElementById('full_name').value;
email_E = document.getElementById('email').value;
}
else {
button.value = 'Save';
}
}
If you want to learn more about this topic:
https://developer.mozilla.org/en-US/docs/Glossary/Scope
https://scotch.io/tutorials/understanding-scope-in-javascript
Also you can pass these variable in a function which you can define in your other js file.

How to get the value of a checkbox using getelementbyID inside a form

I have a code which worked fine while I was testing it now I decided it to include it inside a form and it just does not want to work. If I remove the form tag it works and with the form tag it does not.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title of the document</title>
<script>
function action() {
var checkBox = document.getElementById("UPCheck");
if (checkBox.checked == true){
window.localStorage['username'] = document.getElementById('username').value;
window.localStorage['password'] = document.getElementById('password').value;
window.localStorage['unpwchecked'] = "yes";
alert("Saved!");
}
else
{
window.localStorage['username'] = "";
window.localStorage['password'] = "";
window.localStorage['unpwchecked'] = "";
}
}
function action2() {
document.getElementById('username').value = window.localStorage['username'];
document.getElementById('password').value = window.localStorage['password'];
}
</script>
</head>
<body>
<form>
<input type="text" id="username" name="username" value="">
<input type="text" id="password" name="password" value="">
Save username / password in cookies: <input type="checkbox" id="UPCheck" name="savelocalunpw">
<p><button onclick="action()" type="button">Save values!</button></p>
<p><button onclick="action2()" type="button">Load values!</button></p>
</form>
<script>
var alerted = localStorage.getItem('unpwchecked');
if (alerted == 'yes') {
document.getElementById('username').value = window.localStorage['username'];
document.getElementById('password').value = window.localStorage['password'];
document.getElementById("UPCheck").checked = true;
}
</script>
</body>
</html>
Remove the form tag and values are properly saved in localstorage.
The problem comes from the function name. If you rename
function action()
to
function action1()
and also modify
<button onclick="action1()" type="button">Save values!</button>
then your code will work.
I notices that without the form tag, the code works ok. If you add the form element, then you will get a console error, stating that action() is not a function. I'm just guessing that there is a conflict between the function name action() and the form attribute action
Try:
var isChecked = document.getElementById("UPCheck").checked;
Probably better practice to add an event handler for the buttons, that works with the form tags. Kind of interesting that it works with renaming the function.
JS
document.getElementById("save").addEventListener("click", function(){
var checkBox = document.getElementById("UPCheck");
if (checkBox.checked == true){
window.localStorage.username = document.getElementById('username').value;
window.localStorage.password = document.getElementById('password').value;
window.localStorage.unpwchecked = "yes";
alert("Saved!");
}
else
{
window.localStorage.username = "";
window.localStorage.password = "";
window.localStorage.unpwchecked = "";
}
});
document.getElementById("load").addEventListener("click", function(){
document.getElementById('username').value = window.localStorage.username;
document.getElementById('password').value = window.localStorage.password;
});
var alerted = localStorage.getItem('unpwchecked');
if (alerted == 'yes') {
document.getElementById('username').value = window.localStorage.username;
document.getElementById('password').value = window.localStorage.password;
document.getElementById("UPCheck").checked = true;
}
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title of the document</title>
</head>
<body>
<form>
<input type="text" id="username" name="username" value="">
<input type="text" id="password" name="password" value="">
Save username / password in cookies: <input type="checkbox" id="UPCheck" name="savelocalunpw">
<p><button id = "save" type="button">Save values!</button></p>
<p><button id = "load" type="button">Load values!</button></p>
</form>
</body>
</html>
You can use "dot" notation for localStorage.

Fill textbox from url query and call function

<input type="text" id="tnum" maxlength="50" placeholder="Enter Your Tracking ID" />
<input class="btn" type="button" value="TRACK" onclick="doTrack()" />
<div id="YQContainer"></div>
So basically, I have a page that can track packages for my customers. I want to be able to send them a link in their email that will automatically track their package from the link. ( they don't have to type in their tracking id and click track when they go to my tracking page )
example.com/track?tnum=3298439857
This is what i'm using to track packages.
https://www.17track.net/en/externalcall/single
The basic idea is as follows:
Wait for page to load
Parse the URL and extract needed query parameter
Set the value of the form element
Call the doTrack() function
// Handy function to parse the URL and get a map of the query parameters
function parseQueryParameters(url) {
var qp = {};
if (!url) {
return qp;
}
var queryString = url.split('?')[1];
if (!queryString) {
return qp;
}
return queryString.split('&')
.reduce(function(m, d) {
var splits = d.split('=');
var key = splits[0];
var value = splits[1];
if (key && value) {
m[key] = value;
}
return m;
}, qp);
}
//Wait for page to load
window.onload = function() {
//Extract tnum query parameter
var qp = parseQueryParameters(window.location.href);
//If no parameter is provided, do nothing
if (!qp.tnum) return;
//Set the value of the form element
document.getElementById("tnum").value = qp.tnum;
// Call doTrack
doTrack();
}
//Temporary doTrack function - remove when integrating ;)
function doTrack() {
console.log(document.getElementById("tnum").value)
}
<input type="text" id="tnum" maxlength="50" placeholder="Enter Your Tracking ID" />
<input class="btn" type="button" value="TRACK" onclick="doTrack()" />
<div id="YQContainer"></div>
<html>
<head>
<script>
function setURL(){
var dt_value = document.getElementById("tnum").value;
//just test here ..what is coming..
alert(dt_value );
var sjdurl = "example.com/track?tnum="+dt_value;
popup = window.open(sjdurl,"popup"," menubar =0,toolbar =0,location=0, height=900, width=1000");
popup.window.moveTo(950,150);
}
</script>
</head>
<body>
<input type="Text" id="tnum" maxlength="25" size="25"/>
<input type='button' onclick='setURL()' value='SUBMIT'>
</body>
</html>
function doTrack(tnum) {
var trackNumber = tnum;
window.open("example.com/track?tnum="+trackNumber);
}
$(".btn").on('click',function(e) {
e.preventDefault();
var tnum = $('#tnum').val();
if (tnum!="") {
doTrack(tnum);
} else {
return false;
}
});

Separating HTML and JS

I am trying to separate some JS code that is embedded in to a HTML file. I do not own this code, it is for a remote support landing page but I'm not sure how to separate them out.
I have tried copying the JS code in to a different .js file and then adding the script tags to link but no luck.
<script type="text/javascript" src="https://www.islonline.net/webapi/api.js?
libs=join"></script>
<div class="isl-connect-form">
<form id="isl-connect-form" action="#" method="get" onsubmit="return
isl_connect();">
<fieldset>
<legend>Enter your session code and click Connect</legend>
<div>
<label for="isl-code-field">Session code</label>
<input type="text" name="code" id="isl-code-field" value="" />
</div>
<input type="submit" name="submit" value="Connect" />
</fieldset>
</form>
<div id="isl-feedback"></div>
</div>
<script type="text/javascript">
function isl_connect() {
var doc = document,
f = doc.getElementById('isl-connect-form'),
r = doc.getElementById('isl-feedback'),
is_msie = navigator.userAgent.indexOf('MSIE') >= 0,
b = null;
ISLOnline.Join.getSessionInfoByCode(
f.code.value,
function (info) {
r.className = 'isl-success';
r.innerHTML = 'Connecting to session ' +
info.getAttribute('sessionCode');
if (is_msie) {
r.innerHTML += ', please click the button below:<br />';
r.appendChild(doc.createElement('br'));
var b = doc.createElement('input');
b.type = 'button';
b.name = 'join';
b.value = 'Start';
b.onclick = function () {
info.join();
};
r.appendChild(b);
} else {
info.join();
}
},
function (error) {
r.className = 'isl-error';
r.innerHTML = 'Invalid session code!';
/* comment the line above and uncomment the line below if you
wish to
display the error that is sent by the server */
//r.innerHTML += error.getDescription();
}
);
return false;
}
Create a new JS file and put the original full javascript within it then load it after the islonline.net API call. I have shown an example.
<script type="text/javascript" src="https://www.islonline.net/webapi/api.js?libs=join"></script>
<div class="isl-connect-form">
<form id="isl-connect-form">
<fieldset>
<legend>Enter your session code and click Connect</legend>
<div>
<label for="isl-code-field">Session code</label>
<input type="text" name="code" id="isl-code-field" value="" />
</div>
<input type="submit" name="submit" value="Connect" />
</fieldset>
</form>
<div id="isl-feedback"></div>
</div>
<!-- your new external JS file -->
<script type="text/javascript" src="https://www.example.com/path/to/your/file.js"></script>
Your new Javascript file will contain the original JS code, with a slight modification to help separate HTML and JavaScript by using addEventListener instead of onsubmit:
document.getElementById('isl-connect-form').addEventListener('submit', function isl_connect(event) {
if (typeof event.preventDefault == 'function') event.preventDefault();
var doc = document,
f = this,
r = doc.getElementById('isl-feedback'),
is_msie = navigator.userAgent.indexOf('MSIE') >= 0,
b = null;
ISLOnline.Join.getSessionInfoByCode(
f.code.value,
function (info) {
r.className = 'isl-success';
r.innerHTML = 'Connecting to session ' +
info.getAttribute('sessionCode');
if (is_msie) {
r.innerHTML += ', please click the button below:<br />';
r.appendChild(doc.createElement('br'));
var b = doc.createElement('input');
b.type = 'button';
b.name = 'join';
b.value = 'Start';
b.onclick = function () {
info.join();
};
r.appendChild(b);
} else {
info.join();
}
},
function (error) {
r.className = 'isl-error';
r.innerHTML = 'Invalid session code!';
/* comment the line above and uncomment the line below if you wish to
* display the error that is sent by the server
*/
//r.innerHTML += error.getDescription();
}
);
return false;
});

Categories

Resources