I am trying to pass a searchterm from a google web app to display the results. I am having trouble on submission I receive a blank screen. When the form is submitted, I would like it to display the results. The main code works within the logger- now I am just working on the UI and getting the form to work.
Any help is appreciated!
So far this is the code I have:
CODE:
function SearchFiles() {
//Please enter your search term in the place of Letter
var searchterm ="'mysearchinput'"; \\ this would be the variable that is passed from the form on index.html
var searchFor ="title contains " + searchterm;
var owneris ="and 'youremail#yourdomain.com' in Owners";
var names =[];
var fileIds=[];
var files = DriveApp.searchFiles(searchFor + owneris);
while (files.hasNext()) {
var file = files.next();
var fileId = file.getId();// To get FileId of the file
fileIds.push(fileId);
var name = file.getName();
names.push(name);
}
for (var i=0;i<names.length;i++){
Logger.log(names[i]);
Logger.log("https://drive.google.com/uc?export=download&id=" + fileIds[i]);
}
}
function doGet() {
return HtmlService.createHtmlOutputFromFile('index');
}
function processForm(formObject) {
Logger.log('I was called!');
// here is where I would like to display results of searthterm.
}
HTML:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script>
function handleFormSubmit(formObject) {
google.script.run.withSuccessHandler(updateUrl).processForm(formObject);
}
function onFailure(error) {
var div = document.getElementById('output');
div.innerHTML = "ERROR: " + error.message;
}
</script>
</head>
<body>
Hello, World!
<form id="myForm" onsubmit="handleFormSubmit(this)">
<input type="text" name="search">
<input type="submit" value="Submit" />
</form>
<input type="button" value="Close"
onclick="google.script.host.close()" />
SEARCH FUNCTION:
function SearchFiles() {
Logger.log('I Searched Files');
//Please enter your search term in the place of Letter
var searchterm ="'Whatevertextisinthesearchbox'";
var searchFor ="title contains " + searchterm;
var owneris ="and 'Youremail#yourdomain' in Owners";
var names =[];
var fileIds=[];
var files = DriveApp.searchFiles(searchFor + owneris);
while (files.hasNext()) {
var file = files.next();
var fileId = file.getId();// To get FileId of the file
fileIds.push(fileId);
var name = file.getName();
names.push(name);
}
for (var i=0;i<names.length;i++){
// Logger.log(names[i]);
// Logger.log("https://drive.google.com/uc?export=download&id=" + fileIds[i]);
var filesreturned = {
name:names[i],
urls:"https://drive.google.com/uc?export=download&id=" + fileIds[i]
}
Logger.log(filesreturned.name + " - " + filesreturned.urls);
return(filesreturned);
}
}
As per your comment above, here is the code to simply show hello world on button click. For your reference, I have also added a code to pass data between javascript and appscript.
Index.html file
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script>
function displayMessage()
{
google.script.run.withSuccessHandler(helloWorld).parseDataFromAppscript();
}
function helloWorld(stringText)
{
document.writeln(stringText);
}
</script>
</head>
<body>
<input type="button" value="submitButton" name="submitButton" onclick="displayMessage()"/>
</body>
</html>
Code.gs file
function doGet(e) {
var template = HtmlService.createTemplateFromFile('Index');
return template.evaluate()
.setTitle('Hello World')
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
function parseDataFromAppscript()
{
return "Hello World!";
}
To run this, go to publish -> deploy as web app -> update. And then click latest code.
If you want explanation for any part, please feel free to ask. I'm assuming you already know html javascript and google.script.run method. :)
Related
I am trying to get the user's name from a form input and display it on the page in the form of a greeting "Hello (user)".
I have already got the solution to do it in 2 separate HTML files but I need to do it all in one file using query string and onload options.
Thanks for your help!
firstpage.html
<input type="text" id="titletxt">
<button onclick="Submit()">Submit</button>
<script>
function Submit() {
let name = document.getElementById("txtname").value;
window.location.href = "secondpage.html?" + name;
}
</script>
secondpage.html
<html>
<head>
<title>Test</title>
<script>
function loadTitle() {
let queryString = window.location.search.split('?')[1];
document.write("<h2>Hello "+queryString+"</h2>")
document.title = "hello "+queryString;
}
</script>
</head>
<body onload="loadTitle()">
</body>
</html>
Change your secondpage.html body to:
<body onload="loadTitle()">
<script>
function loadTitle() {
const queryString = window.location.search;
const name = new URLSearchParams(queryString).get("name");
document.body.innerHTML = "<h2>Hello " + name + "</h2>";
document.title = "hello " + name;
}
</script>
</body>
If I am correct in believing that you wanted all of the code to be in one file, I have a solution for you.
Solution with search params:
It simply checks if there is a search parameter called 'name' and if there is is replaces everything with Hello [name].
<html>
<head>
<title>Hello</title>
</head>
<body>
<input type="text" id="titletxt">
<button onclick="Submit()">Submit</button>
<script>
function loadTitle() {
const queryString = window.location.search;
const name = new URLSearchParams(queryString).get("name");
if (name) {
document.body.innerHTML = "<h2>Hello " + name + "</h2>";
document.title = "Hello " + name;
}
}
document.body.onload = loadTitle;
function Submit() {
let name = document.getElementById("titletxt").value;
window.location.search = "?name=" + name;
}
</script>
</body>
</html>
I created a web form using Google Apps Script, where form visitors would see result.html after data submission. However, the data may be submitted multiple times if visitors reload the result.html by pressing F5, Ctrl + R, ignoring the alert of resubmission. The same concern has already been posted here, and I tried implementing one of the solutions for that, but in vain.
I have now four files in the same project of Google Apps Script:
index.html that produces the form
JavaScript.html that defines functions used in index.html
result.html that is presented after the form submission
code.gs that shows the form by doGet(), and processes the submitted data and presents result.html by doPost(). include() defined in this file enables to input JavaScript.html into index.html
The solution I have tried is adding the following JavaScript code result.html. I also add that to JavaScript.html so that the code is to be executed in index.html, too.
<script>
if ( window.history.replaceState ) {
window.history.replaceState( null, null, window.location.href );
}
</script>
However, the resubmission still occurs when I reload the result.html even after I added that code to both result.html and index.html. What am I missing?
index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<!-- <?!= include("css"); ?> -->
</head>
<body onload="addOptions()"> <!--Execute addOptions function immediately after a page has been loaded-->
<form class="" action="<?!= getScriptUrl(); ?>" method="post" onSubmit="document.getElementById('submit').disabled=true;">
<div>
<h1 id="Question">
Choose either cheesecake or chocolate cake.
</h1>
<select id="dropdownList" name="cake" class="form-control">
</select>
</div>
<div class="form-submit">
<input type="submit" name="" value="Submit">
</div>
</form>
</body>
<?!= include('JavaScript') ?>
</html>
JavaScript.html
<script>
function addOptions() {
/*This will call server-side Apps Script function getAvailableExps and if it is successful,
it will pass the return value to function addListValues which will add options to the drop down menu*/
google.script.run
.withFailureHandler(onFailure)
.withSuccessHandler(addListValues)
.getAvailableExps();
}
function addListValues(values) {
//Add options to drop down menu using the values of parameter 'values'.
for (var i = 0; i < values.length; i++) {
var option = document.createElement("option");
option.text = values[i][0];
option.value = values[i][0];
var select = document.getElementById("dropdownList");
select.appendChild(option);
}
}
function onFailure(err) {
alert('Error: ' + err.message);
}
if ( window.history.replaceState ) {
window.history.replaceState( null, null, window.location.href );
}
</script>
result.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<base />
<title>Thank you for your order!</title>
<!-- <?!= include('css'); ?> -->
</head>
<script>
if ( window.history.replaceState ) {
window.history.replaceState( null, null, window.location.href );
}
</script>
<body>
<p>
Don't forget what you've ordered!
</p>
</body>
</html>
code.gs
var sheetID = "............................................";
var inventory_sheet = "Inventory";
function doGet(){
return HtmlService.createTemplateFromFile("index").evaluate();
}
function include(filename){
return HtmlService.createHtmlOutputFromFile(filename).getContent();
}
function getScriptUrl() {
var url = ScriptApp.getService().getUrl();
Logger.log(url);
return url;
}
function doPost(e){
var ss = SpreadsheetApp.openById(sheetID);
var sh = ss.getSheets()[0];
sh.appendRow([String(e.parameters.cake)]);
//update Inventory
var inventory = ss.getSheetByName(inventory_sheet);
var row = inventory.createTextFinder(e.parameters.cake).findNext().getRow();
var range = inventory.getRange(row, 2);
var data = range.getValue();
range.setValue(parseInt(data - 1))
return HtmlService.createTemplateFromFile("result").evaluate();
}
function getAvailableExps(){
var inventory = SpreadsheetApp.openById(sheetID).getSheetByName(inventory_sheet);
var data = inventory.getRange(2, 1, 2, 2).getValues();
var filtered = data.filter(arr => arr[1] > 0 || arr[1] != ''); //remove exp to array if quantity is 0 or empty
return filtered;
}
In your situation, how about checking the submit using PropertiesService? When your script is modified, it becomes as follows.
Modified script:
In this modification, 2 functions of doGet and doPost of code.gs are modified.
doGet
function doGet() {
PropertiesService.getScriptProperties().setProperty("key", "sample");
return HtmlService.createTemplateFromFile("index").evaluate();
}
doPost
function doPost(e) {
var p = PropertiesService.getScriptProperties();
if (p.getProperty("key") == "sample") {
var ss = SpreadsheetApp.openById(sheetID);
var sh = ss.getSheets()[0];
sh.appendRow([String(e.parameters.cake)]);
//update Inventory
var inventory = ss.getSheetByName(inventory_sheet);
var row = inventory.createTextFinder(e.parameters.cake).findNext().getRow();
var range = inventory.getRange(row, 2);
var data = range.getValue();
range.setValue(parseInt(data - 1))
p.deleteProperty("key");
}
return HtmlService.createTemplateFromFile("result").evaluate();
}
When you access to your Web Apps, sample is stored by setProperty("key", "sample") in doGet(). And, when the HTML form is submitted, the PropertiesService is checked in doPost(e). When sample is existing, the data is put, and the PropertiesService is cleared. By this, even when the submitted page is reopened, the PropertiesService is not existing. By this, the resubmitted can be avoided.
Reference:
Properties Service
tried to find some useful answer in existing threads but nothing is really matching my issue. I guess there is a quick fix to it, i just cannot see it.
I have a HTML form and want to upload the file to my google drive (works great) and save the text fields to my spreadsheet (does not work at all).
I just cannot find any major difference between the two functions, its frustrating!
Below my code, and here is also the [link to my public script][1].
Form:
<!DOCTYPE html>
<form id="myForm">
<input type="text" name="myName" placeholder="Your name..">
<input type="file" name="myFile">
<input type="submit" value="Upload File"
onclick="this.value='Uploading..';
google.script.run.withSuccessHandler(fileUploaded)
.uploadFiles(this.parentNode);
return false;
google.script.run.withSuccessHandler(fileUploaded)
.doPost(this.parentNode);">
</form>
<div id="output"></div>
<script>
function fileUploaded(status) {
document.getElementById('myForm').style.display = 'none';
document.getElementById('output').innerHTML = status;
}
</script>
<style>
input { display:block; margin: 20px; }
</style>
[1]: https://script.google.com/d/1K9jGl7ALHCZ93rz8GoeV8t7PE_7vgbNZlLJed1h6ZWyuoon11gIbik24/edit?usp=sharing
server.gs:
function doGet(e) {
var html = HtmlService.createTemplateFromFile("form");
html = html.evaluate();
html.setSandboxMode(HtmlService.SandboxMode.IFRAME);
return html;
}
function uploadFiles(form) {
try {
var dropbox = "Customer Shapes";
var folder, folders = DriveApp.getFoldersByName(dropbox);
if (folders.hasNext()) {
folder = folders.next();
} else {
folder = DriveApp.createFolder(dropbox);
}
var blob = form.myFile;
var file = folder.createFile(blob);
file.setDescription("Uploaded by " + form.myName);
return "File uploaded successfully " + file.getUrl();
} catch (error) {
return error.toString();
}
}
function doPost(form) { // change to doPost(e) if you are recieving POST data
html.setSandboxMode(HtmlService.SandboxMode.EMULATED);
var name = form.myName;
var url="url...";
var message = 'Ram';
var submitSSKey = '...kHI';
var sheet = SpreadsheetApp.openById(submitSSKey).getActiveSheet();
var lastRow = sheet.getLastRow();
var targetRange = sheet.getRange(lastRow+1, 1, 2, 2).setValues([[name,url]]);
}
Thank You for Your kind help!
Martin
If you are going to use google.script.run, then it's pointless to have a function named doPost(). And it's also pointless to have a submit type input tag: type="submit"
If you want to run a withSuccessHandler(fileUploaded) to change the display, you can't have a button inside of the form. It will cause the display to go blank.
And you don't need two google.script.run calls. You need multiple changes and improvements:
form.html
<form id="myForm">
<input type="text" name="myName" placeholder="Your name..">
<input type="file" name="myFile">
</form>
<input type="button" value="Upload File"
onclick="this.value='Uploading..';
var theForm = document.getElementById('myForm');
google.script.run.withSuccessHandler(fileUploaded)
.processFormData(theForm);">
<div id="output"></div>
<script>
function fileUploaded(status) {
document.getElementById('myForm').style.display = 'none';
document.getElementById('output').innerHTML = status;
}
</script>
<style>
input { display:block; margin: 20px; }
</style>
server.gs
function processFormData(form) {
uploadFiles(form.myFile);//Call first function to process the file
var innerArray = [];
var outerArray = [];
innerArray.push(form.myName);
innerArray.push(form.myFile);
outerArray.push(innerArray);//Call second function to write data to SS
writeDataToSS(outerArray);
};
function uploadFiles(theFile) {
try {
var dropbox = "Customer Shapes";
var folder, folders = DriveApp.getFoldersByName(dropbox);
if (folders.hasNext()) {
folder = folders.next();
} else {
folder = DriveApp.createFolder(dropbox);
}
var blob = theFile;
var file = folder.createFile(blob);
file.setDescription("Uploaded by " + theFile);
return "File uploaded successfully " + file.getUrl();
} catch (error) {
return error.toString();
}
}
function writeDataToSS(values) {
//html.setSandboxMode(HtmlService.SandboxMode.EMULATED);
var url="url...";
var message = 'Ram';
var submitSSKey = '...kHI';
var sheet = SpreadsheetApp.openById(submitSSKey).getActiveSheet();
var lastRow = sheet.getLastRow();
var targetRange = sheet.getRange(lastRow+1, 1, 1, 2).setValues(values);
}
The html file is not a template, it does not have a scriptlet in it. Just use createHtmlOutputFromFile():
function doGet(e) {
var html = HtmlService.createHtmlOutputFromFile("form");
html.setSandboxMode(HtmlService.SandboxMode.IFRAME);
return html;
}
I can't get writeFile to write file. It works find if it's not in a function so it's not the module but when the function is called, it results in an error.
[Uncaught TypeError: Cannot read property 'writeFile' of undefined]
JS Code:
var fs = require('fs');
var input = document.getElementById('filename');
var fileName = input.value;
function recordToFilename() {
var input = document.getElementById('filename');
var fileName = input.value;
var qw = fileName;
if (qw) {
alert('value of: ' + qw);
console.log(qw);
// demo output
var myObject = {
qw: qw,
fullN: function() {
return this.qw;
}
};
document.getElementById("demo").innerHTML = myObject.fullN();
var path = "danny.txt";
var data1 = "jdsfhadj"
fs.writeFile(path,data1)
//end demo output code
} else {
alert('Please enter a filename!');
input.focus();
}
};
HTML Code:
<html>
<head>
<title>writeFile</title>
<script src="jquery.js"></script>
<script src="bonescript.js"></script>
<script src="test_3.js"></script>
</head>
<body>
<label for="filename">Filename</label>
<input name="filename" id="filename" type="text">
<a id="enter_button" onclick="recordToFilename();" href="javascript:void(0);" title="enter">enter name</a>
<br>
<p id="demo"></p>
</body>
</html>
Please upgrade your node version to resolve this issue.
I want to upload a file using the HtmlService of GAS but it doesn't work.
I found informations in this topic Uploading file using Google Apps Script using HtmlService but it doesn't fit with my issue.
Here is an example that describes my problem:
Code.gs:
function doGet() {
return HtmlService.createTemplateFromFile("index").evaluate();
}
//For some reasons, this function has to be in code.gs
funcion getHTML() {
var html = "<form id='myform'>"+
"<input name='myfile'>"+
"</form>"+
"<div data-formname='myform'> Submit form </div>";
return html;
}
function uploadFile(file) {
DriveApp.createFile(file); *//Doesn't work :/*
}
Javascript:
$(document).on("click","div", function(e) {
var idform = $(this).data("formname");
if (idform)
sendForm(idform);
});
function trigger() {
google.script.run.withsuccesshandler(setHTML).getHTML();
}
function setHTML(html) {
$("#myHTML").html(html);
}
function sendForm(idForm) {
var formElements = document.getElementById("idForm").elements;
var form = {};
for (var key in formElements) form[key] = formElements[key];
google.script.run.withsuccesshandler().uploadFile(form["myfile"]);
}
index.html
<body onload="trigger()">
<div id='myHTML'></div>
</body>
Your code seems a bit overcomplicated... try this simple code
code.gs
function doGet() {
return HtmlService.createHtmlOutputFromFile('index');
}
function serverFunc(theForm) {
var fileBlob = theForm.theFile; // This is a Blob.
var adoc = DocsList.createFile(fileBlob);
return adoc.getUrl();
}
index.html
<div>
<script>
function cliHandler(e){
document.getElementById('button').value = "Document is downloadable at url "+e
}
</script>
<form>
<input type="file" name="theFile">
<input type="button" value="UpLoad" id="button" onclick="google.script.run.withSuccessHandler(cliHandler).serverFunc(this.parentNode)">
</form>
</div>