Apps Script dialog box - HTML Service - Apply "withSuccessHandler" Properly - google.script.run - html

Background
I'm fairly new to coding in general and as I've gone through building this little UI for Google Sheets using GAS, this is one of the concepts that has just has me stumped. I've tried and tried reading, understand conceptually and apply withSuccessHandler(function) to all sorts of examples but I just can't seem to get it to work.
Here's what I understand so far:
When you run the following on the client side (e.g. Index.html):
google.script.run.withFailureHandler(CallbackFunction).ServerSideFunction(aVariable)
a. ServerSideFunction(aVariable): This function from your Code.gs is first called and returns a value, "OutputA," back to Index.html.
b. CallbackFunction: Then, this function is called and uses "OutputA" as its input and returns another value which you can use for whatever purpose.
Goal
Open Dialog Box asking for "Name" and "E-mail." DONE
Once user hits "Submit" the input is populated in the spreadsheet. DONE
The form is then cleared so they can potentially add another person or exit if they want.
Question
For that last piece, I can't seem to get withSuccessHandler to return a value back from my script, confirming that the inputs were entered properly, and I really don't know how to proceed.
I've included a working version of the code below without withSuccessHandler for reference. Any help at all in better understanding this and how I can incorporate it into the code below would be greatly appreciated!
Google Script
function onOpen(e) {
SpreadsheetApp.getUi()
.createMenu('Menu')
.addItem('Add Member', 'createDialog')
.addToUi();
}
function createDialog() {
var htmlOutput = HtmlService
.createHtmlOutputFromFile('Index')
.setWidth(300)
.setHeight(300);
SpreadsheetApp.getUi().showModalDialog(htmlOutput, " ");
}
function addAName(bName, bEmail) {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var ControlSheet = sheet.getSheetByName('Control Sheet');
var lRow = ControlSheet.getRange(1, 1, ControlSheet.getLastRow(), 1).getValues().filter(String).length;
var Name = ControlSheet.getRange(lRow + 1, 1);
var Email = ControlSheet.getRange(lRow + 1, 2);
var ValidName = /(^[A-Za-z]+)\s([A-Za-z]{1}[.]{1}\s)?([A-Za-z]+$)/g;
var ValidEmail = /(^[A-Za-z]+)([.]{1})([A-Za-z]{1}[.]{1})?([A-Za-z]+)(#google.com|#yahoo.com)$/g;
if (bName.match(ValidName) && bEmail.match(ValidEmail)) {
Name.setValue(bName);
Email.setValue(bEmail);
}
}
HTML
<body>
<h2>Add New Member</h2>
<div class="mdc-layout-grid">
<div class="mdc-layout-grid__cell mdc-layout-grid__cell--span-12">
<div class="mdc-text-field mdc-text-field--upgraded" data-mdc-auto-init="MDCTextField">
<input class="mdc-text-field__input" id="Name" type="text" aria-controls="name-validation-message" pattern="(^[A-Za-z]+)\s([A-Za-z]{1}[.]{1}\s)?([A-Za-z]+$)">
<label for="Name" class="mdc-floating-label">Name</label>
<div class="mdc-line-ripple"></div>
</div>
<p class="mdc-text-field-helper-text mdc-text-field-helper-text--validation-msg" id="name-validation-message" aria-hidden="true">
Please enter your full name.
</p>
</div>
<div class="mdc-layout-grid__cell mdc-layout-grid__cell--span-12">
<div class="mdc-text-field" data-mdc-auto-init="MDCTextField">
<input class="mdc-text-field__input" id="Email" type="text" aria-controls="name-validation-message" pattern="(^[A-Za-z]+)([.]{1})([A-Za-z]{1}[.]{1})?([A-Za-z]+)(#google.com|#yahoo.com)$">
<label for="Email" class="mdc-floating-label">Email Address</label>
<div class="mdc-line-ripple"></div>
</div>
<p class="mdc-text-field-helper-text mdc-text-field-helper-text--validation-msg" id="name-validation-message" aria-hidden="true">
Please enter a valid Google or Yahoo email address.
</p>
</div>
</div>
<div class="Right_Side">
<button class="mdc-button mdc-button--unelevated secondary-filled-button" OnClick="google.script.host.close()">Cancel
</button>
<button class="mdc-button mdc-button--unelevated primary-filled-button" OnClick="sendInputToGS()">Submit
</button>
</div>
<script>
window.sendInputToGS = function() {
var aName = document.getElementById("Name").value;
var aEmail = document.getElementById("Email").value;
google.script.run.addAName(aName, aEmail);
}
</script>
<script type="text/javascript">
window.mdc.autoInit();
</script>
</body>

Only one parameter can be added to the server function being called. But you can use an array as the one parameter and put multiple values into the array.
var data_Array = [aName, aEmail];
google.script.run
.withSuccessHandler(myClientSideFunction)
.addAName(data_Array);
A value is not automatically returned, you must add a return myValue statement.
function addAName(data) {
var bName, bEmail;
bName = data[0];//Arrays in JavaScript are zero indexed
bEmail = data[1];
//code
return "something";
}
Client Code
<script>
window.sendInputToGS = function() {
var aName = document.getElementById("Name").value;
var aEmail = document.getElementById("Email").value;
var data_Array = [aName, aEmail];
google.script.run
.withSuccessHandler(confirmationBack)
.addAName(data_Array);
}
window.confirmationBack = function(rtrn) {
if (rtrn === 'success') {
}
}
</script>

The success and failure handlers for the async communication between the Apps Script instance and the client-side HTML code are functions in the client-side code, not written in Apps Script (.gs).
When calling your server-side function foo(input), it can be used to call other server-side functions (bar(), baz()) as desired, and use their outputs to form the value that is sent to the client-side success handler.
Example:
.gs
function foo(valFromClient) {
var firstPart = bar(valFromClient);
var secondPart = baz(valFromClient);
return {input: valFromClient, first: firstPart, second: secondPart};
}
function bar(input) {
return "'bar' called, input '" + String(input) + "'.";
}
function baz(val) {
return "'baz' called, input '" + String(val) + "'.";
}
.html
...
<script>
function getServerStuff() {
google.script.run
.withFailureHandler(serverThrewException)
.withSuccessHandler(serverFunctionCalledReturn)
.foo("Hi");
}
function serverThrewException(err) {
console.log(err);
}
function serverFunctionCalledReturn(value) {
console.log(value);
}
</script>
In this example, because our code does not throw any exceptions, the failure handler will never be called, and only the success handler will be called. The browser console would log the object {input: "Hi", first: "'bar' called, input 'Hi'.", second: "'baz' called, input 'Hi'."}.

Related

How to pass file upload blob from HTML form to server-side Apps Script?

The Google support article example under the Forms heading is broken. From the article:
If you call a server function with a form element as a parameter, the form becomes a single object with field names as keys and field values as values. The values are all converted to strings, except for the contents of file-input fields, which become Blob objects.
I tested this by passing a Form element containing 5 text inputs and a file, then logging Object.keys() on the form object. It returned only the 5 text fields, the file was stripped from the form object. Attempting to assign the file blob directly returned Exception: Invalid argument: blob
How do I pass the file blob from the client-side Form to the server-side Apps Script?
EDIT: To clarify, I also copy-pasted the example provided by Google verbatim. It errors with Exception: Invalid argument: blob.
To reproduce:
Create new Google Apps Script project
Index.html contents:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script>
// Prevent forms from submitting.
function preventFormSubmit() {
var forms = document.querySelectorAll('form');
for (var i = 0; i < forms.length; i++) {
forms[i].addEventListener('submit', function(event) {
event.preventDefault();
});
}
}
window.addEventListener('load', preventFormSubmit);
function handleFormSubmit(formObject) {
google.script.run.withSuccessHandler(updateUrl).processForm(formObject);
}
function updateUrl(url) {
var div = document.getElementById('output');
div.innerHTML = 'Got it!';
}
</script>
</head>
<body>
<form id="myForm" onsubmit="handleFormSubmit(this)">
<input name="myFile" type="file" />
<input type="submit" value="Submit" />
</form>
<div id="output"></div>
</body>
</html>
Code.gs contents:
function doGet() {
return HtmlService.createHtmlOutputFromFile('Index');
}
function processForm(formObject) {
var formBlob = formObject.myFile;
var driveFile = DriveApp.createFile(formBlob);
return driveFile.getUrl();
}
Publish as Web App
Submit the form with any file
Observe error in View -> Stackdriver Logging -> Apps Script Dashboard
Here's an example:
html:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script>
function fileUploadJs(frmData) {
document.getElementById('status').style.display ='inline';
google.script.run
.withSuccessHandler(updateOutput)
.uploadTheFile(frmData)
}
function updateOutput(info) {
var br='<br />';
var outputDiv = document.getElementById('status');
outputDiv.innerHTML = br + 'File Upload Successful.' + br + 'File Name: ' + info.name + br + 'Content Type: ' + info.type + br + 'Folder Name: ' + info.folder;
}
console.log('My Code');
</script>
<style>
body {background-color:#ffffff;}
input{padding:2px;margin:2px;}
</style>
</head>
<body>
<h1 id="main-heading">Walking Tracks</h1>
<h3>Upload GPS Tracks Files</h3>
<div id="formDiv">
<form id="myForm">
<input name="fileToLoad" type="file" /><br/>
<input type="button" value="Submit" onclick="fileUploadJs(this.parentNode)" />
</form>
</div>
<div id="status" style="display: none">
<!-- div will be filled with innerHTML after form submission. -->
Uploading. Please wait...
</div>
<div id="controls">
<input type="button" value="Close" onClick="google.script.host.close();" />
</div>
</body>
</html>
server code:
function uploadTheFile(theForm) {
var fileBlob=theForm.fileToLoad;
var fldr = DriveApp.getFolderById('FolderId');
var file=fldr.createFile(fileBlob);
var fi=formatFileName(file);
var fileInfo={'name':fi.getName(),'type':fileBlob.getContentType(), 'size':fileBlob.getBytes(), 'folder':fldr.getName()};
return fileInfo;
}
I can confirm that this doesn't work in G-Suite Enterprise. I don't know why because I cannot find documentation that says how Google is serializing the data. It could be a browser/computer security setting or something in G-Suite.
However, there is an easier way to accomplish your need. You can use a Google Form with a file upload question and then create an on form submit trigger/event on it to copy the file to a team/shared drive. Here is sample code if you want to attach the trigger to the Google Form itself:
// ID of the destnation folder to save the file in
var destinationFolderID = "10gkU_2V9iYy-VKudOCOjydEpoepPTgPv"
function saveFileToTeamDrive(e)
{
// a place to save the URL of the uploaded file
var fileID;
// go through all of the responses to find the URL of the uploaded file
e.response.getItemResponses().forEach(function(itemResponse){
// once we find the question with the file
if(itemResponse.getItem().getTitle() == "File Upload Test")
{
// get the file ID from the response
fileID = itemResponse.getResponse();
return;
}
});
// stop if we didn't have one
if(!fileID.length) return;
// get the first index in the array
fileID = fileID[0];
// get the file
var file = DriveApp.getFileById(fileID);
// get the destination folder
var destinationFolder = DriveApp.getFolderById(destinationFolderID);
// make a copy
var newFile = file.makeCopy(destinationFolder);
Logger.log(newFile.getUrl());
}
You can also attach to the on form submit event of a Google Sheet that is linked to a Google Form. I find that way easier cause the Google Sheet on form submit trigger/event includes a JSON of the question/answers so you don't have to iterate all of them to find it. It also means you can re-run a submission if it failed.
WARNING
One important note, if you do either of these things do not give anyone else edit access to the code. This is because as soon as you create and authorize the trigger, anyone who has edit access to the code would be able to use it to gain access to your Google Drive (and anything else the trigger is authorized for). Please see securing a Google Apps Script linked to an authorized trigger so others can edit for more information.

How to call server-script function on HTML Service button click

I have a library and have imported into my spreadsheet.
Library file contains these 2 files (sona)
customHtml.gs // UI
customScript.gs // Code
Spreadsheet file
code.gs
In customHtml.gs code (my library)
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"> </script>
<input id="txt1" type="text" />
<input id="txt2" type="text" />
<input id="Button1" class="btnSave" type="button" value="Save" />
<script>
$("#Button1").on('click',function(){
var param1=$("#txt1").val();
var param2=$("#txt2").val();
google.script.run.getCars(param1, param2);
});
</script>
customScript.gs
function sonatask_Assign(){
var html = HtmlService.createHtmlOutputFromFile('customHtml')
.setSandboxMode(HtmlService.SandboxMode.IFRAME)
.setWidth(900)
.setHeight(500);
return html;
}
function getCars(param1, param2){
// code logic
Logger.log(param1,param2);
}
Spreadsheet (code.gs)
function onOpen() {
var ui = SpreadsheetApp.getUi();
// Or DocumentApp or FormApp.
ui.createMenu('► BOT')
.addSeparator()
.addItem('Task Assign ', 'fn_task_Assign')
.addItem('☎ Help ', 'helpMethod')
.addToUi();
}
// display dialog box with custom HTML (which is stored in library)
function fn_task_Assign(){
// get html from library (reason behind using HTML from library, is to acces only specific user. As spreadsheet is availabe to all any one can make a copy of it, but functions will not work unless i acces them to this library )
var showHTML = sona.sonatask_Assign();
Logger.log(abc);
SpreadsheetApp.getUi().showModalDialog(showHTML, " ");
}
On fn_task_Assign it display modelbox. i.e. 2 txtbox and a button.
Now on button click I try to call getCars function, but its not working.
Create getCars inside your code.gs and call sona.getCars();
function getCars(param1, param2) {
sona.getCars(param1, param2);
}
Also in oder this all to work, your library needs tobe a Stand alone script. Otherwise it wont work.

Getting Form Data from a Sidebar in Google Apps?

I am trying to get data from using a form in a sidebar, but I can't use normal way in javascript where I get it from the document in javascript.
i.e.
var form = document.getElementById("treasurerForm");
So, how should I go about getting data from a form in a sidebar?
You have to communicate between the sidebar (client-side) and the Google Apps Script (server-side). You can do this by using google.script.run in your sidebar javascript.
function openSidebarForm() {
var htmlOutput = HtmlService.createHtmlOutputFromFile("sendForm");
htmlOutput.setSandboxMode(HtmlService.SandboxMode.IFRAME).setTitle("Form");
var ui = SpreadsheetApp.getUi();
ui.showSidebar(htmlOutput);
}
function processForm(data) {
// here you can process the data from the form
Browser.msgBox(data);
}
And add a html file to the project named sendForm.html
<script>
function sendForm() {
var data = document.forms[0].elements[0].value;
google.script.run.withSuccessHandler(ready).processForm(data);
document.getElementById("all").innerHTML = "Processing..";
}
function ready() {
document.getElementById("all").innerHTML = "Processed!"
}
</script>
<div id="all">
<form id="form"><input type="text"></form>
<button onclick="javascript:sendForm();">Submit</button>
</div>
A button within a form automatically triggers the submit of the form, and here we want only the javascript to do the work. So we have put it outside the form.
The sendForm() function takes the value of the first element of the form. Then it runs a function in your google script. By putting google.script.run. before the function name you can do this. The withSuccessHandler(functionName) will run a callback function in your sidebar after the function has completed.
You can also type in your HTML as a string and then use HtmlService, which is much less elegant, but it will also work if you have problems adding a html file to your project.
function openSidebarForm() {
var html = '<script>function sendForm() {'
+ 'var data = document.forms[0].elements[0].value;'
+ 'google.script.run.withSuccessHandler(ready).processForm(data);'
+ 'document.getElementById("processing").innerHTML = "Processing.."; }'
+ 'function ready() {'
+ 'document.getElementById("all").innerHTML = "Processed!" }'
+ '</script>'
+ '<div id="all"><div id="processing"></div>'
+ '<form id="form"><input type="text"></form>'
+ '<button onclick="javascript:sendForm();">Submit</button></div>';
htmlOutput = HtmlService.createHtmlOutput(html).setSandboxMode(HtmlService.SandboxMode.IFRAME).setTitle("Form");
var ui = SpreadsheetApp.getUi();
ui.showSidebar(htmlOutput);
}
function processForm(data) {
// here you can process the data from the form
Browser.msgBox(data);
}
Good luck !

Checkbox value always returns true, Google script HTML service

I have created a google sheets sidebar using the google script HTML service which has various text boxes and checkboxes. i have no problem passing the variables through to the google script. The problem i have is that the value of my checkbox is always true or "Y" in my case whether is is checked or not. I really would like to know how to set the value as "Y" or "N". I wont upload complete script just the important bits because they are quite long.
This is my checkbox within my sidebar HTML...
</div>
<div class="block form-group" id="Headset">
<label for="headset-Check">Headset?:</label><br>
<input id= "headset-Check" type="checkbox" value="Y">
</div>
this is my javascript calling various google script functions the bit that uses the checkbox is near the bottom,
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"> </script>
<script>
$(function() {
// Assign handler functions to sidebar elements here, if needed.
$('#GetSerial-button').click(onGetSerialClick);
$('#Submit-button').click(onSubmitClick);
});
function onGetSerialClick() {
this.disabled = true;
google.script.run
.withSuccessHandler(
function(msg, element) {
$('#Serial-value').val(msg);
showStatus('Pulled Serial Successfully.');
element.disabled = false;
})
.withUserObject(this)
.getSerialValue();
}
function onSubmitClick() {
this.disabled = true;
var serial = $('#Serial-value').val();
var warrantyNotes = $('#warrantyNotes-value').val();
var warrantyRepair = $('#Warranty-Repair').val();
var headsetCheck = $('#headset-Check').val();
google.script.run
.withSuccessHandler(
function(msg, element) {
showStatus('Submitted ');
element.disabled = false;
})
.withUserObject(this)
.setHeadsetValues(warrantyRepair,headsetCheck,warrantyNotes,serial)
google.script.run
.addNewRow();
}
function showStatus(msg, classId) {
$('#sidebar-status').removeClass().html(msg);
if (classId) {
$('#sidebar-status').addClass(classId);
}
}
i then have a GS function to put the variables into correct sheet.
UPDATE
i am now able to get true or false by doing this in the java script
var headsetCheck = $('#headset-Check').is(':checked');
does anybody know how i can get "Y" or "N" thanks

Alternatives to suggestBox in a Google UiApp

I'm trying to create a relatively simple app (or at least it seemed that way two weeks ago) to catalog periodical intake in a library. I need a form with two boxes: text input for periodical titles and date input for publication date. I then need this form to submit to a Google Spreadsheet. I could just use a generic form, but I need it to autocomplete the periodical title as the information is being entered.
I'm using Google Apps, Spreadsheets, and Sites because they're free and do most of what I want. Here's the sticking point. I can create an HTMLService that autocompletes perfectly from a Google sheet. I basically followed this post exactly.
I can create a script that is a UiApp for submitting to a sheet. I just can't do both with one project. The code follows:
function doGet() {
var doc = SpreadsheetApp.openById(SPREADSHEET_ID);
var app = UiApp.createApplication().setTitle('Periodical Intake');
// Create a grid with 3 text boxes and corresponding labels
var grid = app.createGrid(3, 2);
grid.setWidget(0, 0, app.createLabel('Title:'));
// Text entered in the text box is passed in to pTitle
// The setName method will make those widgets available by
// the given name to the server handlers later
grid.setWidget(0, 1, app.createTextBox().setName('pTitle').setId('pTitle'));
grid.setWidget(1, 0, app.createLabel('Date:'));
grid.setWidget(1, 1, app.createDateBox().setName('date').setId('date'));
// Text entered in the text box is passed in to city.
// Create a vertical panel..
var panel = app.createVerticalPanel();
// ...and add the grid to the panel
panel.add(grid);
// Here's where this script diverges from the previous script.
// We create a horizontal panel called buttonPanel to hold two buttons, one for submitting the contents of the form
// to the Spreadsheet, the other to close the form.
var buttonPanel = app.createHorizontalPanel();
// Two buttons get added to buttonPanel: button (for submits) and closeButton (for closing the form)
// For the submit button we create a server click handler submitHandler and pass submitHandler to the button as a click handler.
// the function submit gets called when the submit button is clicked.
var button = app.createButton('submit');
var submitHandler = app.createServerClickHandler('submit');
submitHandler.addCallbackElement(grid);
button.addClickHandler(submitHandler);
buttonPanel.add(button);
// For the close button, we create a server click handler closeHandler and pass closeHandler to the close button as a click handler.
// The function close is called when the close button is clicked.
var closeButton = app.createButton('close');
var closeHandler = app.createServerClickHandler('close');
closeButton.addClickHandler(closeHandler);
buttonPanel.add(closeButton);
// Create label called statusLabel and make it invisible; add buttonPanel and statusLabel to the main display panel.
var statusLabel = app.createLabel().setId('status').setVisible(false);
panel.add(statusLabel);
panel.add(buttonPanel);
app.add(panel);
return app;
}
// Close everything return when the close button is clicked
function close() {
var app = UiApp.getActiveApplication();
app.close();
// The following line is REQUIRED for the widget to actually close.
return app;
}
// function called when submit button is clicked
function submit(e) {
// Write the data in the text boxes back to the Spreadsheet
var doc = SpreadsheetApp.openById(SPREADSHEET_ID);
var lastRow = doc.getLastRow();
var cell = doc.getRange('a1').offset(lastRow, 0);
cell.offset(0, 1).setValue(e.parameter.pTitle);
cell.offset(1, 2).setValue(e.parameter.date);
// Clear the values from the text boxes so that new values can be entered
var app = UiApp.getActiveApplication();
app.getElementById('pTitle').setValue('');
app.getElementById('date').setValue('');
// Make the status line visible and tell the user the possible actions
app.getElementById('status').setVisible(true).setText('The periodical ' + e.parameter.pTitle + ' was entered.' +
'To add another, type in the information and click submit. To exit, click close.');
return app;
}​
I could use my getAvailableTags function if it's possible to use jQuery in a UiApp (I don't think it is). The other suggestion is to use suggestBox but it seems that has been deprecated. I'm at my wit's end. It's been two weeks and I feel I haven't gotten anywhere. Can anyone please help a librarian out?
Here is an example of a form built with HTMLService that keeps data in a spreadsheet. I has also a file upload that you don't need but I thought it could interest someone else...
The autocomplete feature should be easy to integrate using you existing code borrowed from Mogsdad.
code.gs:
function doGet() {
return HtmlService.createHtmlOutputFromFile('index');
}
function serverFunc(theForm) {
var fileBlob = theForm.theFile; // This is a Blob.
var name = theForm.name;
var number = theForm.number;
var adoc = DocsList.createFile(fileBlob);
var sh = SpreadsheetApp.openById('1dx0mr4Dy64jqmliTjFyHF7rZW4TZ_PPkWyA_H3WTRcA').getSheetByName('Sheet1');
sh.getRange(sh.getLastRow()+1,1,1,4).setValues([[adoc.getName(),adoc.getUrl(),name,number]]);
return adoc.getUrl();
}
index.html :
<style>
p {
margin:40px;
font-family:arial,sans-serif;
font-size:10pt;
color:#AAA
}
</style>
<p>
Test this file upload form :
<br><br>
<form>
Enter you name <input type="text" name="name" ><br>
Enter your number <input type="text" name="number"><br>
select your file <input type="file" name="theFile"><br>
<input type="button" value="UpLoad" id="button" onclick="google.script.run.withSuccessHandler(cliHandler).serverFunc(this.parentNode)">
</form>
</div><br>
<div id="url" >
</div><br>
<div id="urlText" >
</p>
<script>
function cliHandler(e){
document.getElementById('button').value = "Your file has been uploaded" ;
var divUrl = document.getElementById('url');
divUrl.innerHTML = 'Open the file';
document.getElementById('urlText').innerHTML = "url : "+e;
}
</script>
EDIT : Here is a version based on your code with a working form and autocomplete:
code.gs
function doGet() {
return HtmlService.createTemplateFromFile('Autocomplete').evaluate().setTitle('Periodical Intake');
}
function getAvailableTags() {
var ss = SpreadsheetApp.openById("0Agz7u97dbdECdGh6QVcyb2NVeFByTnlYeU5KcDdSRWc");
var s = ss.getSheetByName("Cataloging Key");
var data = s.getDataRange().getValues();
var headers = 0; // number of header rows to skip at top
var tagColumn = 0; // column # (0-based) containing tag
var availableTags = [];
for (var row=headers; row < data.length; row++) {
availableTags.push(data[row][tagColumn]);
}
return( availableTags );
}
function doPost(e) {
var title = e.title;
var date = e.date;
Logger.log(title+' '+date);
}
Autocomplete.html
<link rel="stylesheet" href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" />
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<style>
p {
margin:40px;
font-family:arial,sans-serif;
font-size:10pt;
color:#AAA
}
</style>
<p>
Test this file upload form :
<br><br>
<div>
<form class="ui-widget" >
<input id="title" type=text placeholder="Periodical Title:" name="title" /><br />
<input id="date" type=date placeholder="Publication Date: " name="date" /><br>
<input type="button" value="Submit"
onclick="google.script.run.doPost(this.parentNode)" />
</form>
</div><br>
<div id="url" >
</div><br>
<div id="urlText" >
</p>
<script>
// This code in this function runs when the page is loaded.
$(function() {
google.script.run.withSuccessHandler(buildTagList).getAvailableTags();
});
function buildTagList(availableTags) {
$( "#title" ).autocomplete({
source: availableTags
});
}
</script>