The functionality listed below executes properly when I submit content back to the server through google.script.run however it does not work for my coworkers in the same file. These coworkers are on the same domain and have edit access to the spreadsheet and are able to load the first portion of the feature, the rough-sketch modal, from the template I built (html shown below).
Our experiences seem to diverge when they hit the "Submit" button - their client should be calling google.script.run.userSubmissions. On the back-end executions view, however, I do not receive any indication that their client side script is properly calling the userSubmission function - shown below I would expect it to show up at the top, line item 3 is when I performed the same action and my client called google.script.run as expected. Also, I cannot seem to see any errors being reported of any kind.
Full html being presented in a floating modal window:
Note: I have 3 scriptlets printing in the function call and have verified that these are working properly in my co-workers clients
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Provide Comment</title>
</head>
<body>
<h3>Provide comment for content item #</h3>
<div>
<span>Title</span>
<p>Content</p>
</div>
<div>
<label style="display: block;" for="commentInput">Comment:</label>
<textarea
id="userComment"
style="display: block; margin: 1em 0 1em 0; width: 99%;"
name="commentInput"
rows="10"
placeholder="Please provide your comment here..."
></textarea>
<button style="float: right;" onclick="submitComment()">
Submit
</button>
</div>
<script>
function submitComment() {
let comment = document.getElementById("userComment").value;
google.script.run
.withSuccessHandler(closeModal)
.withFailureHandler(onFailure)
.userSubmission(
comment,
"comment",
parseInt(<?= contentIDColumn; ?>),
parseInt(<?= eventContentID; ?>),
parseInt(<?= statusColumn; ?>)
);
function closeModal() {
google.script.host.close();
}
function onFailure(error) {
console.log(error);
let message = "There was an error processing that form. Perhaps try again?"
document.getElementById("errorMessage").textContent = message;
}
}
</script>
</body>
</html>
Related
to demonstrate what im trying to do using a simple example:
<html>
<head>
<base target="_top">
</head>
<body>
<form id="uploaderForm" action="https://script.google.com/macros/.......exec Method="POST">
<input type="text" name="applicantName" id="applicantName">
<input type="text" name="applicantEmail" id="applicantEmail">
<input type="button" value="Submit">
</form>
<script>
.
.
.
google.script.run.withSuccessHandler(onFileUploaded)
.uploadFile(content, file.name, folderId);
</script>
so this is an example of the html and js page that is in my pc, not in the google app, i just called the google app in the form, and in the javascript part im calling a function called uploadFile, which is located in the google script, but obviously i get an error in the console , it says :
Uncaught ReferenceError: google is not defined
at uploadFiles (6166bff606ac6fee1994e592:67)
at HTMLInputElement.onclick
is it possible to call a GAS function inside JS that is not in the GAS html.
is what im trying to do even possible, the whoel reason im doing this is so that i can pass the username and email automatically from the database to the app, the app works if the html part is hosted in the google app script, but then i cant figure out how to pass the email and username to it because in this case i call the app using , so is it possible to pass the username and email through the iframe call, i dunno im very new to this i have so many questions, honestly the documentation wasn't helpful to me. please feel free to comment anything, everythign is helpful
Since you're just posting the form data, you can name the function you want to call as doPost()(instead of uploadFile) and it will receive the posted data. You have to republish the webapp as a new version after the modification.
I just ran it as a dialog. I returned the data back into the success handler and loaded by into the html to insure it was working.
HTML:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<body>
<form>
<input type="text" name="applicantName" id="applicantName"/>
<input type="text" name="applicantEmail" id="applicantEmail"/>
<input type="button" value="Submit" onclick="uploadfile(this.parentNode);" />
</form>
<div id="msg"></div>
<script>
function uploadfile(form) {
google.script.run
.withSuccessHandler((m) => document.getElementById("msg").innerHTML = m)
.uploadMyFile(form);
}
</script>
</body>
</html>
gs:
function uploadMyFile(obj) {
return `Applicant Name: ${obj.applicantName}<br />Applicant Email: ${obj.applicantEmail}`;
}
function launchFormDialog() {
SpreadsheetApp.getUi().showModelessDialog(HtmlService.createHtmlOutputFromFile('ah2'),'Test Dialog');
}
Dialog:
I would like to get information when I put buttons, for this I use DOM, but I have errors, how can I solve this problems?
I tried to confirm if name is correct, and search about DOM, but I couldn't figure out it.
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset="uft-8">
<title>Pomodoro Timer</title>
</head>
<body>
<p class="menu">menu</p>
<p class="timer">0.00</p>
<button data-option='start' class="timer_button" >start</button>
<button data-option='stop' class="timer_button">stop</button>
<button data-option='reset' class="timer_button">reset</button>
<script>
const buttons = document.querySelectorAll('[data-option]');
function test(e){
console.log(e);
}
buttons.forEach(()=>buttons.addEventListener('click',test));
</script>
</body>
I would like to see the results in the console when I put the buttons.
buttons.forEach((button)=>button.addEventListener('click',test))
The buttons is a list. When you iterate over it with forEach you can get each button as the first argument of the method. And that is where you must attach the event handler.
Im in the process of adding the reCaptcha from google to my form. The problem is that even though I have followed the instructions from google. I can still press the Submit button without doing the recaptcha. Any Ideas please heres the relevant code snippets.
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>webpage title</title>
<link rel="stylesheet" type="text/css" href="view.css" media="all">
<script type="text/javascript" src="view.js"></script>
<script src='https://www.google.com/recaptcha/api.js'></script>
</head>
And the this snippet in the form part of the webpage
<div class="g-recaptcha" data-sitekey="xxxxxxmyapikeyxxxxxxx_xxxxxxmyapikeyxxxxxxx"></div>
<li class="buttons">
<input type="hidden" name="form_id" value="1136056" />
<input id="saveForm" class="button_text" type="submit" name="submit" value="Submit" />
</li>
</ul>
</form>
As far as I'm aware I have placed the code in the specified areas of my webpage. One before the closing tag on your HTML template and the snippet at the end of the where I want the reCAPTCHA widget to appear.
I have put the recaptcha before the submit button. There is a part about the server side integration that I do not understand.
[QUOTE]
When your users submit the form where you integrated reCAPTCHA, you'll
get as part of the payload a string with the name "g-recaptcha-response".
In order to check whether Google has verified that user,
send a POST request with these parameters:
URL: https://www.google.com/recaptcha/api/siteverify
secret (required) xxxxxmysecretkeyxxxxxxx
response (required) The value of 'g-recaptcha-response'.
remoteip The end user's ip address.
[/QUOTE]
Can anyone please shed some light on this please.
Thankyou
So we set up the form and make sure your library is included, I prevent the submit button from being clicked while the recaptcha has not been completed and show a tooltip to notify the user it is needed to continue. Then enable it when it has been complete using the callback methods.
login.php
<div class="formContainer">
<script src='https://www.google.com/recaptcha/api.js'></script>
<form action="loginHandler.php" method="post" name="login_form" id="loginForm" class="loginForm">
<h2>Login</h2>
<p><input type="text" required placeholder="Email" name="email"></p>
<p><input type="password" required placeholder="Password" name="password" id="password"></p>
<div class="g-recaptcha" data-callback="captcha_filled"
data-expired-callback="captcha_expired"
data-sitekey="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX">
</div>
<div>
<p class="show-tt" data-toggle="tooltip" title="Complete the reCAPTCHA to login." data-placement="bottom">
<input id="submitLogin" type="submit" value="Login">
</p>
</div>
</form>
</div>
<script>
//prevent submit and show tooltip until captch is complete.
var submit = false;
$("#submitLogin").prop('disabled', true);
function captcha_filled() {
submit = true;
$("#submitLogin").prop('disabled', false);
$(".show-tt").tooltip('destroy');
}
function captcha_expired() {
submit = false;
$("#submitLogin").prop('disabled', true);
showTooltip();
}
function showTooltip () {
$(".show-tt").tooltip('show');
}
</script>
Now we post to loginHandler.php, or wherever your form submits too and then there we will assign your secret key and then verify the request with google.
loginHandler.php
$secret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
if (isset($_POST["g-recaptcha-response"])) {
$url = 'https://www.google.com/recaptcha/api/siteverify?secret=' . urlencode($secret) .
'&response=' . urlencode($_POST['g-recaptcha-response']) . '&remoteip=' . urlencode($_SERVER['REMOTE_ADDR']);
//ip address is optional
$result = json_decode(file_get_contents($url), true);
if ($result != null && $result['success'] === true) {
//success, handle login/submit data or whatever
} else {
//response is bad, handle the error
header('Location: login.php?error=4');
}
} else {
//captcha response is not set, handle error
header('Location: login.php?error=5');
}
In HTML5, i have an orphaned form control submitting my form. To support IE10, i use the following:
jQuery(document).delegate('input[form][type="submit"], button[form][type="submit"]', 'click', function() {
form_selector = "form#" + jQuery(this).attr("form") + "";
console.log("submitting IE10 form from an orphaned control:" + form_selector);
jQuery(form_selector).submit();
});
chrome and firefox submit without this bit of code fine and handle inputs with the required attribute as usual, stopping the submit and showing a pop-up message if any one required input is empty.
<input required/>
IE10 needs the above javascript to submit the form, HOWEVER, if any inputs with the required attribute are empty, the usual pop-up messages do not appear over the empty controls. If i move the control under the form and DO NOT USE the submit() function, then the pop-up messages appear fine.
any advice on how to get the pop-ups to show up when calling submit() in IE10?
EDIT: here's a jsfiddle to demo what's happening: http://jsfiddle.net/2YYvh/5/
Try it both in IE10 and chrome/firefox
If you use the $.trigger method you can activate the submit button that you need to in order to fire the validation.
The following is an updated version of your example using the .trigger.
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script type="text/javascript">
$( document ).ready( function() {
$('.btn-primary').click(function(event) {
$("form#test_form input[type=submit]").trigger( "click" );
});
});
</script>
</head>
<body>
<h2>
Try this in chrome and then in IE10
<button type="submit" class="btn btn-primary" form="test_form">
im outside the form
</button>
</h2>
<div class="dashWidget autoHeight" data-pagination='true'>
<form id="test_form">
Leave me blank:<input type="text" value="" required />
<input type="submit" value="im in the form!"/>
</form>
</div>
</body>
</html>
This is not directly related but is an alternative.
You could always create your own validation, for example if you want to validate an input of type=email. You could listen for the input event on the email field. If HTML5 validation throws a typeMismatch, then override the default message with something more useful and/or sarcastic.
$('.email').bind('input', function () {
//We need to reset it to blank or it will throw an invalid message.
this.setCustomValidity('');
if (!this.validity.valid) {
this.setCustomValidity("Dude '" + this.value + "' is not a valid email. Try something like "+
"jim#jboss.org. And no we are not checking if it actually works, we are just looking "+
"for the # sign. ");
}
});
I'm coding a Windows 8 application in JavaScript and HTML5. I wish to show a dialog box when clicking a button.
I have specified the event handler in the default.js file like so:
// For an introduction to the Blank template, see the following documentation:
// http://go.microsoft.com/fwlink/?LinkId=232509
(function () {
"use strict";
var app = WinJS.Application;
var activation = Windows.ApplicationModel.Activation;
WinJS.strictProcessing();
app.onactivated = function (args) {
if (args.detail.kind === activation.ActivationKind.launch) {
if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
// TODO: This application has been newly launched. Initialize
// your application here.
} else {
// TODO: This application has been reactivated from suspension.
// Restore application state here.
}
args.setPromise(WinJS.UI.processAll().done(function () {
// Get the login button on the home page
var login_button = document.getElementById("login_submit");
// Set an event handler on the login button
login_button.addEventListener("click", UserActionLogin, false);
}));
}
};
app.oncheckpoint = function (args) {
// TODO: This application is about to be suspended. Save any state
// that needs to persist across suspensions here. You might use the
// WinJS.Application.sessionState object, which is automatically
// saved and restored across suspension. If you need to complete an
// asynchronous operation before your application is suspended, call
// args.setPromise().
};
function UserActionLogin(mouseEvent) {
var message_dialog = new Windows.UI.Popups.MessageDialog("Sorry, we were unable to log you in!" + mouseEvent.y.toString()).showAsync();
}
app.start();
})();
My HTML markup is below:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>HelloWorld</title>
<!-- WinJS references -->
<link href="//Microsoft.WinJS.1.0.RC/css/ui-dark.css" rel="stylesheet" />
<script src="//Microsoft.WinJS.1.0.RC/js/base.js"></script>
<script src="//Microsoft.WinJS.1.0.RC/js/ui.js"></script>
<!-- HelloWorld references -->
<link href="/css/default.css" rel="stylesheet" />
<script src="/js/default.js"></script>
<script type="text/javascript">
</script>
</head>
<body>
<div id="wrapper">
<div class="login_box">
<form method="post">
<input type="text" name="login_username" />
<input type="password" name="login_password" />
<input type="submit" id="login_submit" name="login_submit" />
</form>
</div>
</div>
</body>
</html>
When I click the login_submit button when the application loads, it shows the dialog box just fine.
But when I click it for a second time it doesn't work, it's like it's forgotten about the Event Handler.
The problem is having the element in there, which you don't need in an app because you won't want to have the submit button repost/reload the page with the form contents. You're effectively reloading the page but the activated handler isn't called in that case (the page is loaded as a post rather than a request), so you lose the event handler.
If you delete the element, then it works just fine. I'm also told that if you use type="button" instead of type="submit" then it should work. But in an app, you'll typically collect the data from the controls and save that in other variables, navigating to another "page" in the app using the WInJS navigation and page control mechanisms, which keeps you on default.html without changing script context.
Also, I notice that you're still referring to the RC version of WinJS. Since Win8 is officially released now, be sure to develop against the released version of the system and using the most recent tools.
The problem is your use of the form element, which is causing your HTML to be reloaded when you click the button - this replaces the element you set up the event handler for, meaning that subsequent clicks don't invoke your handler function.
Remove the form element and you will get the behavior you expect, as follows:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>App7</title>
<link href="//Microsoft.WinJS.1.0.RC/css/ui-dark.css" rel="stylesheet" />
<script src="//Microsoft.WinJS.1.0.RC/js/base.js"></script>
<script src="//Microsoft.WinJS.1.0.RC/js/ui.js"></script>
<link href="/css/default.css" rel="stylesheet" />
<script src="/js/default.js"></script>
</head>
<body>
<div id="wrapper">
<div class="login_box">
<input type="text" name="login_username" />
<input type="password" name="login_password" />
<input type="submit" id="login_submit" name="login_submit" />
</div>
</div>
</body>
</html>
If you really need the form element for some reason (perhaps because you are using a JS library which expects it), then you can prevent the problem by stopping the form being submitted in your event handler function, as follows:
function UserActionLogin(mouseEvent) {
var message_dialog = new Windows.UI.Popups.MessageDialog("Sorry, we were unable to log you in!" + mouseEvent.y.toString()).showAsync();
mouseEvent.preventDefault();
}
The call to preventDefault stops the form being posted but allows you to keep the form element in the document.