Apps Script:
//Triggered when the page is navigated to, serves up HTML
function doGet(){
var template = HtmlService.createTemplateFromFile('index');
return template.evaluate()
.setTitle('Example App')
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
//Called from the client with form data, basic validation for blank values
function formSubmit(formData){
for(var field in formData){
if(formData[field] == ''){
return {success: false, message: field + ' Cannot be blank'}
}
}
return {success: true, message: 'Sucessfully submitted!'};
}
HTML
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<link href="/?originalUrl=https%3A%2F%2Friptutorial.com%2F%26quot%3Bhttps%3A%2F%2Fssl.gstatic.com%2Fdocs%2Fscript%2Fcss%2Fadd-ons1.css%26quot%3B%2520rel%3D%26quot%3Bstylesheet%26quot%3B%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3Bscript%2520src%3D%26quot%3Bhttps%3A%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fjquery%2F2.1.4%2Fjquery.min.js%26quot%3B%2520type%3D%26quot%3Btext%2Fjavascript%26quot%3B%26gt%3B%26lt%3B%2Fscript%26gt%3B%2520%2520%2520%2520%26lt%3B%2Fhead%26gt%3B%2520%2520%2520%2520%26lt%3Bbody%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3Bdiv%2520id%3D%26quot%3BmainForm%26quot%3B%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3Bh1%26gt%3BExample%2520Form%26lt%3B%2Fh1%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3Bform%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3Bdiv%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3Bdiv%2520class%3D%26quot%3Binline%2520form-group%26quot%3B%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3Blabel%2520for%3D%26quot%3Bname%26quot%3B%26gt%3BName%26lt%3B%2Flabel%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3Binput%2520id%3D%26quot%3BnameInput%26quot%3B%2520style%3D%26quot%3Bwidth%3A%2520150px%3B%26quot%3B%2520type%3D%26quot%3Btext%26quot%3B%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3B%2Fdiv%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3B%2Fdiv%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3Bdiv%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3Bdiv%2520class%3D%26quot%3Binline%2520form-group%26quot%3B%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3Blabel%2520for%3D%26quot%3Bcity%26quot%3B%26gt%3BCity%26lt%3B%2Flabel%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3Binput%2520id%3D%26quot%3BcityInput%26quot%3B%2520style%3D%26quot%3Bwidth%3A%2520150px%3B%26quot%3B%2520type%3D%26quot%3Btext%26quot%3B%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3B%2Fdiv%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3Bdiv%2520class%3D%26quot%3Binline%2520form-group%26quot%3B%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3Blabel%2520for%3D%26quot%3Bstate%26quot%3B%26gt%3BState%26lt%3B%2Flabel%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3Binput%2520id%3D%26quot%3BstateInput%26quot%3B%2520style%3D%26quot%3Bwidth%3A%252040px%3B%26quot%3B%2520type%3D%26quot%3Btext%26quot%3B%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3B%2Fdiv%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3Bdiv%2520class%3D%26quot%3Binline%2520form-group%26quot%3B%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3Blabel%2520for%3D%26quot%3Bzip-code%26quot%3B%26gt%3BZip%2520code%26lt%3B%2Flabel%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3Binput%2520id%3D%26quot%3Bzip-codeInput%26quot%3B%2520style%3D%26quot%3Bwidth%3A%252065px%3B%26quot%3B%2520type%3D%26quot%3Bnumber%26quot%3B%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3B%2Fdiv%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3B%2Fdiv%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3Bdiv%2520class%3D%26quot%3Bblock%2520form-group%26quot%3B%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3Blabel%2520for%3D%26quot%3BtypeSelect%26quot%3B%26gt%3BType%26lt%3B%2Flabel%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3Bselect%2520id%3D%26quot%3BtypeSelect%26quot%3B%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3Boption%2520value%3D%26quot%3B%26quot%3B%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3B%2Foption%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3Boption%2520value%3D%26quot%3BType%25201%2520%26quot%3B%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520Type%25201%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3B%2Foption%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3Boption%2520value%3D%26quot%3BType%25202%2520%26quot%3B%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520Type%25202%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3B%2Foption%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3Boption%2520value%3D%26quot%3BType%25203%2520%26quot%3B%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520Type%25203%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3B%2Foption%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3Boption%2520value%3D%26quot%3BType%25204%2520%26quot%3B%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520Type%25204%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3B%2Foption%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3B%2Fselect%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3B%2Fdiv%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3Bbutton%2520class%3D%26quot%3Baction%26quot%3B%2520id%3D%26quot%3BsubmitButton%26quot%3B%2520type%3D%26quot%3Bbutton%26quot%3B%26gt%3BSubmit%26lt%3B%2Fbutton%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3Bbutton%2520class%3D%26quot%3Bclear%26quot%3B%2520id%3D%26quot%3BclearFormButton%26quot%3B%2520type%3D%26quot%3Bbutton%26quot%3B%26gt%3BClear%2520Form%26lt%3B%2Fbutton%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3B%2Fform%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3Bdiv%2520class%3D%26quot%3Bhidden%2520error%2520message%26quot%3B%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3Bdiv%2520class%3D%26quot%3Btitle%26quot%3B%26gt%3BError%3A%26lt%3B%2Fdiv%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3Bdiv%2520class%3D%26quot%3Bmessage%26quot%3B%26gt%3B%26lt%3B%2Fdiv%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3B%2Fdiv%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3Bdiv%2520class%3D%26quot%3Bhidden%2520success%2520message%26quot%3B%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3Bdiv%2520class%3D%26quot%3Btitle%26quot%3B%26gt%3BMessage%3A%26lt%3B%2Fdiv%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3Bdiv%2520class%3D%26quot%3Bmessage%26quot%3B%26gt%3BSucessfully%2520submitted%26lt%3B%2Fdiv%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3B%2Fdiv%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3B%2Fdiv%26gt%3B%2520%2520%2520%2520%2520%2520%2520%2520%26lt%3B%3F!%3D%2520HtmlService.createHtmlOutputFromFile("JavaScript').getContent(); ?>
<?!= HtmlService.createHtmlOutputFromFile('Stylesheet').getContent(); ?>
</body>
</html>
CSS
<style>
.hidden {
display: none;
}
.form-group {
margin: 2px 0px;
}
#submitButton {
margin: 4px 0px;
}
body {
margin-left: 50px;
}
.message {
padding: 2px;
width: 50%;
}
.message > * {
display: inline-block;
}
.message .title {
font-weight: 700;
font-size: 1.1em;
}
.success.message {
border: 1px solid #5c9a18;
background: #e4ffe4;
color: #2a8e2a;
}
.error.message {
background: #f9cece;
border: 1px solid #7d2929;
}
.error.message .title {
color: #863030;
}
button.clear {
background: -moz-linear-gradient(top, #dd6e39, #d17636);
background: -ms-linear-gradient(top, #dd6e39, #d17636);
background: -o-linear-gradient(top, #dd6e39, #d17636);
background: -webkit-linear-gradient(top, #dd6e39, #d17636);
background: linear-gradient(top, #dd6e39, #d17636);
border: 1px solid transparent;
color: #fff;
text-shadow: 0 1px rgba(0, 0, 0, .1);
}
button.clear:hover {
background: -moz-linear-gradient(top, #ca602e, #bd6527);
background: -ms-linear-gradient(top, #ca602e, #bd6527);
background: -o-linear-gradient(top, #ca602e, #bd6527);
background: -webkit-linear-gradient(top, #ca602e, #bd6527);
background: linear-gradient(top, #ca602e, #bd6527);
border: 1px solid transparent;
color: #fff;
text-shadow: 0 1px rgba(0, 0, 0, .1);
}
</style>
JavaScript
<script>
var inputs = [
'nameInput',
'cityInput',
'stateInput',
'zip-codeInput',
'typeSelect'
];
$(function(){
var pageApp = new formApp();
$('#submitButton').on('click', pageApp.submitForm);
$('#clearFormButton').on('click', pageApp.clearForm);
});
var formApp = function(){
var self = this;
//Clears form input fields, removes message, enables submit
self.clearForm = function(){
for(var i = 0; i < inputs.length; i++){
$('#'+inputs[i]).val('');
}
toggleSubmitButton(false);
setErrorMessage(false);
setSuccessMessage(false);
}
//Submits the form to apps script
self.submitForm = function(){
toggleSubmitButton(true);
setSuccessMessage(false);
setErrorMessage(false);
google.script.run
.withSuccessHandler(self.sucessfullySubmitted)
.withFailureHandler(self.failedToSubmit)
.formSubmit(self.getFormData());
};
//Retrieves the form data absed on the input fields
self.getFormData = function(){
var output = {};
for(var i = 0; i < inputs.length; i++){
output[inputs[i]] = $('#'+inputs[i]).val();
}
console.log(output)
return output;
}
//When the apps script sucessfully returns
self.sucessfullySubmitted = function(value){
if(value.success){
setSuccessMessage(true, value.message);
} else {
setErrorMessage(true, value.message);
toggleSubmitButton(false);
}
}
//When the apps script threw an error
self.failedToSubmit = function(value){
toggleSubmitButton(false);
setErrorMessage(true, value.message);
}
}
//Disables/enables the submit button
function toggleSubmitButton(disabled){
$('#submitButton').prop('disabled', disabled);
}
//Sets the general message box's message and enables or disabled the error box
function setSuccessMessage(show, message){
if(show){
$('.success.message').removeClass('hidden');
$('.success.message .message').text(message);
} else {
$('.success.message').addClass('hidden');
$('.success.message .message').text('');
}
}
//Sets the error message box's message and enables or disabled the error box
function setErrorMessage(show, message){
if(show){
$('.error.message').removeClass('hidden');
$('.error.message .message').text(message);
} else {
$('.error.message').addClass('hidden');
$('.error.message .message').text('');
}
}
function getFormData(){
var output = {};
for(var i = 0; i < inputs.length; i++){
output[inputs[i]] = $('#'+inputs[i]).val();
}
return output;
}
</script>