I'm writing a web app under google sheets and can't get an input field to work. What am I doing wrong?
everything works but uname is always empty (not undefined).
edit: I'm adding the full code after simplifying it as much as I could.
In the log I get "name" regardless of the input I type in.
In the file code.gs:
function doGet () {
var participant = {};
var templ = HtmlService.createTemplateFromFile('out');
return templ.evaluate();;
}
function formSubmit(name) {
Logger.log("name " + name);
}
In out.html
<!DOCTYPE html>
<html>
<head>
<base target ="_top">
</head>
<body dir="rtl"; background-color: #92a8d1;>
<label> Name 1 </label> <input type="text" id="firstname"><br>
<label> Name 2 </label> <input type="text" id="lastname"> <br><br>
<button type="button" id="send">Send</button>
<script>
document.getElementById("send").addEventListener("click", getData());
function getData(){
var uname = document.getElementById("firstname").value;
google.script.run.formSubmit(uname);
}
</script>
</body>
</html>
You want to retrieve the value of <input type="text" id="firstname"> when the button is clicked.
In your current situation, when you see the log with the script editor, only name is retrieved. This is your current issue.
You want to know the reason of the issue.
If my understanding is correct, how about this answer? Please think of this as just one of several possible answers.
Modification points:
In your script, document.getElementById("send").addEventListener("click", getData()); is used. In this case, when the HTML is loaded, getData() is run by () of getData(). By this, uname becomes "" and "" is sent to formSubmit(uname), then, when you see the log, you see name. And also, in this case, even when the button is clicked, google.script.run.formSubmit(uname); cannot be run. I think that this is the reason of the issue of your script in your question.
In order to avoid this, please modify your script as follows.
Modified script:
From:
document.getElementById("send").addEventListener("click", getData());
To:
document.getElementById("send").addEventListener("click", getData);
By the above modification for your script, when sample is inputted to "Name 1" and click "Send" button, you can see name sample at the log with the script editor.
Reference:
addEventListener()
If I misunderstood your question and this was not the result you want, I apologize.
Here's an example form that you can probably use to accomplish your needs. This form is used as a simple receipt collection system. You can actually take and upload images from a mobile device with it. I also has text and button input types and upload a form node.
Code.gs
var receiptImageFolderId='';
var SSID='';
function onOpen() {
SpreadsheetApp.getUi().createMenu('Receipt Collection')
.addItem('Run as Dialog', 'showAsDialog')
.addItem('Run as Sidebar', 'showAsSidebar')
.addToUi();
var sh=SpreadsheetApp.getActive().getSheetByName("Sheet1");
sh.getRange(sh.getLastRow()+1,1).activate();
}
function uploadTheForm(theForm) {
var rObj={};
rObj['vendor']=theForm.vendor;
rObj['amount']=theForm.amount;
rObj['date']=theForm.date;
rObj['notes']=theForm.notes
var fileBlob=theForm.receipt;
var fldr = DriveApp.getFolderById(receiptImageFolderId);
rObj['file']=fldr.createFile(fileBlob);
rObj['filetype']=fileBlob.getContentType();
Logger.log(JSON.stringify(rObj));
var cObj=formatFileName(rObj);
Logger.log(JSON.stringify(cObj));
var ss=SpreadsheetApp.openById(SSID);
ss.getSheetByName('Sheet1').appendRow([cObj.date,cObj.vendor,cObj.amount,cObj.notes,cObj.file.getUrl()]);
var html=Utilities.formatString('<br />FileName: %s',cObj.file.getName());
return html;
}
function formatFileName(rObj) {
if(rObj) {
Logger.log(JSON.stringify(rObj));
var mA=rObj.date.split('-');
var name=Utilities.formatString('%s_%s_%s.%s',Utilities.formatDate(new Date(mA[0],mA[1]-1,mA[2]),Session.getScriptTimeZone(),"yyyyMMdd"),rObj.vendor,rObj.amount,rObj.filetype.split('/')[1]);
rObj.file.setName(name);
}else{
throw('Invalid or No File in formatFileName() upload.gs');
}
return rObj;
}
function doGet() {
var output=HtmlService.createHtmlOutputFromFile('receipts').setTitle('thehtml');
return output.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL).addMetaTag('viewport', 'width=360, initial-scale=1');
}
function showAsDialog() {
var ui=HtmlService.createHtmlOutputFromFile('thehtml');
SpreadsheetApp.getUi().showModelessDialog(ui, 'Receipts')
}
function showAsSidebar() {
var ui=HtmlService.createHtmlOutputFromFile('thehtml');
SpreadsheetApp.getUi().showSidebar(ui);
}
function initForm() {
var datestring=Utilities.formatDate(new Date(),Session.getScriptTimeZone(), "yyyy-MM-dd")
return {date:datestring};
}
The Html:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<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(){
google.script.run
.withSuccessHandler(function(rObj){
$('#dt').val(rObj.date);
})
.initForm();
});
function fileUploadJs(frmData) {
var amt=$('#amt').val();
var vndr=$('#vndr').val();
var img=$('#img').val();
if(!amt){
window.alert('No amount provided');
$('#amt').focus();
return;
}
if(!vndr) {
window.alert('No vendor provided');
$('#vndr').focus();
return;
}
if(!img) {
window.alert('No image chosen');
$('#img').focus();
}
document.getElementById('status').style.display ='inline';
google.script.run
.withSuccessHandler(function(hl){
document.getElementById('status').innerHTML=hl;
})
.uploadTheForm(frmData)
}
console.log('My Code');
</script>
<style>
input,textarea{margin:5px 5px 5px 0;}
</style>
</head>
<body>
<h3 id="main-heading">Receipt Information</h3>
<div id="formDiv">
<form id="myForm">
<br /><input type="date" name="date" id="dt"/>
<br /><input type="number" name="amount" placeholder="Amount" id="amt" />
<br /><input type="text" name="vendor" placeholder="Vendor" id="vndr"/>
<br /><textarea name="notes" cols="40" rows="2" placeholder="NOTES"></textarea>
<br/>Receipt Image
<br /><input type="file" name="receipt" id="img" />
<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>
</body>
</html>
Here's what the dialog looks like:
Hey guys what am I doing wrong here?? I'm sorry if this has been posted before, but I couldn't find a good example with a form input.
Thank you.
I really don't understand why output.value.toUpperCase() doesn't work, or toUpperCase(output.value) wouldn't work.
<html>
<head>
<link href="https://fonts.googleapis.com/css?family=Barlow" rel="stylesheet">
</head>
<body>
<h1 id="title">Capitalize a String</h1>
<form>
<input type="text" id="entry" placeholder="Enter a string to be capitalized">
</form>
<h1 id="title">Output</h1>
<form>
<input type="text" id="output" placeholder="Output">
</form>
<div id="goBtn">
<h1 id="goBtnText">
GO
</h1>
</div>
</body>
</html>
var goBtn = document.getElementById('goBtn');
var entry = document.getElementById('entry');
var output = document.getElementById('output');
goBtn.addEventListener('click', capitalizeStr);
function capitalizeStr () {
output.value = entry.value;
return output.value.toUpperCase();
}
You will need to do
function capitalizeStr () {
output.value = entry.value.toUpperCase();
}
Calling output.value.toUpperCase() does not change the output.value property, it just returns a new string (and the value returned by an event listener is ignored).
Disclaimer: I am not looking for someone to code this for me just some pointers to help me fix this problem :)
I have the following web page that allows me to add fields dynamically to a form. The current page works. What I want to do is figure out how to make the javascript at the bottom of the page more generic. example I want to pass the templet id and the target id to the function without hard coding the templet id and the target id into the script. Here is the code that I have and works just fine.
I want to make the morefields function so that I can reuse. I want to pass to the function the template and the target. example function moreFields ( templete, target). this way I can use the same function without editing over and over in different web pages. if you look in to the moreFields function you will see that it is hard coded for "readroot" and "writeroot" I want to change the function so it will take parameters and do the same thing it is doing now.
<HTML>
<HEAD>
<META NAME="generator" CONTENT=
"HTML Tidy for Linux/x86 (vers 25 March 2009), see www.w3.org">
<TITLE></TITLE>
<STYLE TYPE="text/css">
div.c1 {display: none}
</STYLE>
</HEAD>
<BODY >
<DIV ID="readroot" CLASS="c1">
Variable Name <INPUT NAME="VarName"><BR>
</DIV>
<FORM METHOD="post" ACTION="/cgi-bin/show_params.cgi">
Function Name: <INPUT NAME="CFunction"> <BR>
Function Alias: <INPUT NAME="AFunction"><BR>
<BR>
<SPAN ID="writeroot"></SPAN>
Function return: <INPUT NAME="AFunction"><BR>
<INPUT TYPE="button" ID="AddMoreFields" VALUE="Give me more fields!" ONCLICK= "moreFields()"> <INPUT TYPE="submit" VALUE="Send form">
</FORM>
<SCRIPT >
var counter = 0;
function moreFields() {
counter++;
var newFields = document.getElementById("readroot").cloneNode(true);
newFields.id = '';
newFields.style.display = 'block';
var newField = newFields.childNodes;
for (var i=0;i<newField.length;i++) {
var theName = newField[i].name
if (theName)
newField[i].name = theName + counter;
}
var insertHere = document.getElementById("writeroot");
insertHere.parentNode.insertBefore(newFields,insertHere);
}
window.onload = moreFields()
</SCRIPT>
</BODY>
</HTML>
I need to enforce character count limit in my application. I found some JavaScripts from web but they are not working, Here is my code. I would be very thankful if someone can kindly see the code & correct whats causing problem.
<HTML>
<HEAD>
<script type="text/javascript" src="http://ajax.googleapis.com/
ajax/libs/jquery/1.4.2/jquery.min.js">
</script>
<script type="text/javascript">
$(document).ready(function()
{ $("#update").keyup(function()
{
var box=$(this).val();
var main = box.length *100;
var value= (main / 140);
var count= 140 - box.length;
if(box.length <= 140)
{
$('#count').html(count);
}
else
{
alert('Character Limit Exceeded!');
return false;
}
});});
</script>
</HEAD>
<BODY>
<textarea id="update" rows="10" cols="3"></textarea>
<div align="left" id="character-count">
<div id="count">140</div>
</div>
</BODY>
</HTML>
You have a space in between http://ajax.googleapis.com/ and ajax
Your code will not handle someone keeping a key pressed (as it will not fire keyup events until you release the key). It will also not handle pasting text with more chars than the allowed number..
Have a look at this plugin http://remysharp.com/2008/06/30/maxlength-plugin/ which handles most cases..
Script of counting characters in a text box/textarea using Javascript
<script type="text/javascript">
var count = "175";
function limiter() {
var tex = document.myform.comment.value;
var len = tex.length;
if(len > count) {
tex = tex.substring(0,count);
document.myform.comment.value =tex;
return false;
}
document.myform.limit.value = count-len;
}
</script>
<body>
<form name="myform" METHOD=POST>
<textarea name=comment wrap=physical rows=3 cols=40 onkeyup=limiter()></textarea><br>
<script type="text/javascript">
document.write("<input type=text name=limit size=4 readonly value="+count+">");
</script>
</form>
</body>
I'm having a problem with this form I'm working on. Whenever I add, or refresh the page, the values are still there. I believe this is because the clone method copies the value attribute from the textBox. Is there any way I can get rid of them when I add another textBox?
<html>
<head>
<title>JQuery Example</title>
<script type="text/javascript" src="jquery-1.4.js"></script>
<script type="text/javascript">
function removeTextBox()
{
var childCount = $('p').size() //keep track of paragraph childnodes
//this is because there should always be 2 p be tags the user shouldn't remove the first one
if(childCount != 2)
{
var $textBox = $('#textBox')
$textBox.detach()
}
}
function addTextBox()
{
var $textBox = $('#textBox')
var $clonedTextBox = $textBox.clone()
//document.getElementById('textBox').setAttribute('value', "")
$textBox.after($clonedTextBox)
}
</script>
</head>
<body>
<form id =
method="POST"
action="http://cs.harding.edu/gfoust/cgi-bin/show">
<p id= "textBox">
Email:
<input type = "text" name="email" />
<input type ="button" value ="X" onclick = "removeTextBox()"/>
</p>
<p>
Add another email
</p>
<input type="submit" value="submit"/>
</form>
</body>
</html>
The Following addition should work:
var $clonedTextBox = $textBox.clone();
$($clonedTextBox).val('');