I'm working in apps script right now and want to show an array in my html select dropdown. I've tried connecting it but the dropdown shows up blank when I do. Here's what I have:
EDIT
I've realised that the issue is that the GmailApp function does not work in the html file, and can't figure out how to run it.
<div class ="custom-select"><td class="standard"><select id="select"></select> </td></div>
<script>
// get drafts
var drafts = GmailApp.getDrafts();
var drafty = [];
for(var i = 0; i < drafts.length; i++)
{
drafty.push(drafts[i].getMessage().getSubject());
}
var select = document.getElementById("select"),
arr = drafty
for(var i = 0; i < arr.length; i++)
{
var option = document.createElement("OPTION"),
txt = document.createTextNode(arr[i]);
option.appendChild(txt);
option.setAttribute("value",arr[i]);
select.insertBefore(option,select.lastChild);
}
</script>
Are you getting the right value here?
txt = document.createTextNode(arr[i]);
Try with something like this
var option = document.createElement("OPTION"),
txt = document.createTextNode(arr[i]);
option.innerHTML.appendChild(txt);
option.value(arr[i]);
select.insertBefore(option,select.lastChild);
How about this?
var option = document.createElement("OPTION"),
txt = document.createTextNode(arr[i]);
option.setAttribute("value", arr[i]);
option.appendChild(txt);
document.getElementById("select").appendChild(option);
GmailApp is an Apps Script class that must be called serverside
There are several ways to do it, I recommend in your case:
If you have a code.gs and an html filed in your WebApp, you can call from within the <script> ... </script> part from the html part the code.gs part with the method google.script.run.
Sample:
code.gs
function doGet(){
return HtmlService.createHtmlOutputFromFile('index');
}
function getDrafts(){
var drafts = GmailApp.getDrafts();
var drafty = [];
for(var i = 0; i < drafts.length; i++)
{
drafty.push(drafts[i].getMessage().getSubject());
}
return drafty;
}
index.html
...
<script>
...
google.script.run.withSuccessHandler(onSuccess).getDrafts();
function onSuccess(drafty) {
var select = document.getElementById("select"),
arr = drafty;
for(var i = 0; i < arr.length; i++)
{
...
}
...
</script>
...
Alternatively, you could also use scriptlets to call Apps Script functions inside your HTML code.
Related
Here i have code for taking info about attached files:
<ul id="result"></ul>
<script>
var elem = document.getElementById('upload-field');
elem.addEventListener('change', getFileData);
function getFileData() {
const files = this.files;
const list = document.getElementById("result");
let child;
for ( let i = 0; i < files.length; i++) {
child = document.createElement("li")
child.textContent = files[i].name;
list.append(child);
}
}
</script>
but when I click on the button and attach the file - it shows this file info.
When I do it again code added this file info again under the previous text, and I would like to "reset" the list of files when I attach files again, but I don't know how to improve this code :(
You forgot to add the <input type="file" id="upload-field"> to your example. If you wanted to reset the file control you would use a form around it. But since you wanted to "reset" the element, setting it's innerHTML to empty would suffice.
var elem = document.getElementById('upload-field');
elem.addEventListener('change', getFileData);
function getFileData() {
const files = this.files;
const list = document.getElementById("result");
// empty list
list.innerHTML = "";
let child;
for (let i = 0; i < files.length; i++) {
child = document.createElement("li")
child.textContent = files[i].name;
list.append(child);
}
}
<input type="file" id="upload-field">
<ul id="result"></ul>
I have this problem here
The problem has been solved, but my question is how can I get the second value from that, or the third one. The sheet will have many tables and at some point I will need a total for each table. Also, is there any solution to automatically find the the array number which contain date row for each table (instead defining this manually). Hope my explanation make sense.
Thank you!
Kind regards,
L.E. Test file
If I understood your question correctly, instead of breaking the loop when a match to "Total" is found do whatever is needed to be done within the loop like so...
var today = toDateFormat(new Date());
var todaysColumn =
values[5].map(toDateFormat).map(Number).indexOf(+today);
var emailDate = Utilities.formatDate(new Date(today),"GMT+1",
"dd/MM/yyyy");
for (var i=0; i<values.length; i++){
if (values[i][0]=='Total'){
nr = i;
Logger.log(nr);
var output = values[nr][todaysColumn];
// Do something with the output here I"m assuming you email it
}
}
The loop will keep going and find every "Total" and do the same thing. This answer assumes that the "Totals" are in the same column. You can get fancier with this if you only want certain tables to send and not others, but this should get you started.
I didn't quite understand the second part of your question...
"Also, is there any solution to automatically find the the array
number which contain date row for each table (instead defining this
manually). Hope my explanation make sense."
I'm guessing you want all the rows that contain "Total" in the specific column. You could instantiate a variable as an empty array like so, var totals = [];. Then instead of sending the email or whatever in the first loop you would push the row values to the array like so, totals.push(nr+1) . //adding 1 gives you the actual row number (rows count from 1 but arrays count from 0). You could then simply loop through the totals array and do whatever you wanted to do. Alternatively you could create an array of all the values instead of row numbers like totals.push(values[nr][todaysColumn]) and loop through that array. Lots of ways to solve this problem!
Ok based on our conversation below I've edited the "test" sheet and updated the code. Below are my edits
All edits have been made in your test sheet and verified working in Logger. Let me know if you have any questions.
Spreadsheet:
Added "Validation" Tab
Edited "Table" tab so the row with "Email Address" in Column A lines up with the desired lookup values (dates or categories)...this was only for the first two tables as all the others already had this criteria.
Code:
Create table/category selector...
In the editor go to File >> New >> HTMLfile
Name the file "inputHTML"
Copy and paste the following code into that file
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<form class="notice_form" autocomplete="off" onsubmit="formSubmit(this)" target="hidden_iframe">
<select id="tables" onchange="hideunhideCatagory(this.value)" required></select>
<p></p>
<select id="categories" style="display:none"></select>
<hr/>
<button class="submit" type="submit">Get Total</button>
</form>
<script>
window.addEventListener('load', function() {
console.log('Page is loaded');
});
</script>
<script
src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript">
// The code in this function runs when the page is loaded.
$(function() {
var tableRunner = google.script.run.withSuccessHandler(buildTableList);
var catagoryRunner = google.script.run.withSuccessHandler(buildCatagoryList);
tableRunner.getTables();
catagoryRunner.getCategories();
});
function buildTableList(tables) {
var list = $('#tables');
list.empty();
list.append('<option></option>');
for (var i = 0; i < tables.length; i++) {
if(tables[i]==''){break;}
list.append('<option>' + tables[i] + '</option>');
}
}
function buildCatagoryList(categories) {
var list = $('#categories');
list.empty();
list.append('<option></option>');
for (var i = 0; i < categories.length; i++) {
if(categories[i]==''){break;}
list.append('<option>' + categories[i] + '</option>');
}
}
function hideunhideCatagory(tableValue){
var catElem = document.getElementById("categories");
if(tableValue == "Total Calls By Date" || tableValue == "Total Appointments by Date"){
catElem.style.display = "none"
document.required = false;
}else{
catElem.style.display = "block"
document.required = true;
}
}
function formSubmit(argTheFormElement) {
var table = $("select[id=tables]").val(),
catagory = $("select[id=categories]").val();
console.log(table)
google.script.run
.withSuccessHandler(google.script.host.close)
.getTotal(table,catagory);
}
</script>
</body>
<div id="hiframe" style="display:block; visibility:hidden; float:right">
<iframe name="hidden_iframe" height="0px" width="0px" ></iframe>
</div>
</html>
Edits to Code.gs file
Replace code in Code.gs with this...
//This is a simple trigger that creates the menu item in your sheet
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Run Scripts Manually')
.addItem('Get Total','fncOpenMyDialog')
.addToUi();
}
//This function launches the dialog and is launched by the menu item
function fncOpenMyDialog() {
//Open a dialog
var htmlDlg = HtmlService.createHtmlOutputFromFile('inputHTML')
.setSandboxMode(HtmlService.SandboxMode.IFRAME)
.setWidth(200)
.setHeight(150);
SpreadsheetApp.getUi()
.showModalDialog(htmlDlg, 'Select table to get total for');
};
//main function called by clicking "Get Total" on the dialogue...variables are passed to this function from the formSubmit in the inputHTML javascript
function getTotal(table,catagory) {
function toDateFormat(date) {
try {return date.setHours(0,0,0,0);}
catch(e) {return;}
}
//get all values
var values = SpreadsheetApp
.openById("10pB0jDPG8HYolECQ3eg1lrOFjXQ6JRFwQ-llvdE2yuM")
.getSheetByName("Tables")
.getDataRange()
.getValues();
//declare/instantiate your variables
var tableHeaderRow, totalRow, tableFound = false;
//begin loop through column A in Tables Sheet
for (var i = 0; i<values.length; i++){
//test to see if values have already been found if so break the loop
if(tableFound == true){break;}
//check to see if value matches selected table
if (values[i][0]==table){
//start another loop immediately after the match row
for(var x=i+1; x<values.length; x++){
if(values[x][0] == "Email Address"){ //This header needs to consistantly denote the row that contains the headers
tableHeaderRow = x;
tableFound = true;
}else if(values[x][0] == "Total"){
totalRow = x;
break;
}
}
}
}
Logger.log("Header Row = "+tableHeaderRow)
Logger.log("Total Row = "+ totalRow)
var today = toDateFormat(new Date())
var columnToTotal;
if(catagory==''){
columnToTotal = values[tableHeaderRow].map(toDateFormat).map(Number).indexOf(+today);
}else{
columnToTotal = values[tableHeaderRow].indexOf(catagory);
}
var output = values[totalRow][columnToTotal];
Logger.log(output);
var emailDate = Utilities.formatDate(new Date(today),"GMT+1", "dd/MM/yyyy");
//here is where you would put your code to do something with the output
}
/** The functions below are used by the form to populate the selects **/
function getTables(){
var cFile = SpreadsheetApp.getActive();
var cSheet = cFile.getSheetByName('Validation');
var cSheetHeader = cSheet.getRange(1,1,cSheet.getLastRow(),cSheet.getLastColumn()).getValues().shift();
var tabelCol = (cSheetHeader.indexOf("Tables")+1);
var tables = cSheet.getRange(2,tabelCol,cSheet.getLastRow(),1).getValues();
return tables.filter(function (elem){
return elem != "";
});
}
function getCatagories(){
var cFile = SpreadsheetApp.getActive();
var cSheet = cFile.getSheetByName('Validation');
var cSheetHeader = cSheet.getRange(1,1,cSheet.getLastRow(),cSheet.getLastColumn()).getValues().shift();
var catagoriesCol = (cSheetHeader.indexOf("Catagory")+1);
var catagories = cSheet.getRange(2,catagoriesCol,cSheet.getLastRow(),1).getValues();
return catagories.filter(function (elem){
return elem != "";
});
}
I created a function which contains a string that I want to add to a in HTML. But when I test it, it won't show me the options declared in my table.
function test(){
// table already defined
var choices = "<option selected>Select...</option>";
for (var i=0; i<tableOptions.length; i++) {
choices += "<option>" + tableOptions[i][0] +"</option>";
}
document.getElementById("theOptions").innerHTML = choices;
}
and in my HTML I have
<select id="theOptions"></select>
What am I doing wrong?
By the way, my test() is automatically loaded after my page is displayed.
<body onload="test()">
See How to populate the options of a select element in javascript for detail on creating and appending options to an existing <select> element.
Using that method, this seems closest to what you're getting at:
var select = document.getElementById("theOptions");
opt = document.createElement("option");
opt.innerHTML = "Select...";
select.appendChild(opt);
for(var i = 0; i < tableOptions.length; i++)
{
var opt = document.createElement("option");
opt.innerHTML = tableOptions[i][0];
select.appendChild(opt);
}
I have dynamic multiple check boxes which is used to restore multiple files. It works perfectly when I have more than 1 check boxes. Here is my php code for check boxes:
<form name="RestoreFile">
<input type="checkbox" title="'.$FldDoc['FldDocumentName'].'" name="restore_checkbox" value="'.$FldDoc['FldDocumentID'].'" id="restore_'.$NodeId.'_'.$FldDoc['FldDocumentID'].'"/>
<input type="button" value="Restore" onclick="RestoreDocFile(\''.$NodeId.'\',this.form.restore_checkbox);" />
</form>
And the definition of function RestoreDocFile() is given below:
function getSelected(opt)
{
var selected = new Array();
var index = 0;
for (var intLoop = 0; intLoop < opt.length; intLoop++) {
if (opt[intLoop].checked)
{
index = selected.length;
selected[index] = new Object;
selected[index].value = opt[intLoop].value;
selected[index].index = intLoop;
}
}
return selected;
}
function RestoreDocFile(nodeid, opt)
{
var getSelectDocIds = getSelected(opt);
//alert(nodeid+','+getSelectDocIds);
var strSelectedDocIds = "";
var i=0;
for (var item in getSelectDocIds)
{
if(i!=0)
{
strSelectedDocIds+=":";
}
strSelectedDocIds += getSelectDocIds[item].value ;
i++;
}
}
The problem is that if there has 1 checkbox at the time of form load it doesn't work properly.
Try replacing
onclick="RestoreDocFile(\''.$NodeId.'\',this.form.restore_checkbox);"
with
onclick="RestoreDocFile(\''.$NodeId.'\',this.form.getElementsByName(\'restore_checkbox\'));"
This will ensure you get a NodeList regardless of how many checkboxes there are.
I'm trying to create a dropdown list from an array on my overlay (div element) using javascript.
In this example,
spcodelist = [u'CA125', u'HCM112', u'HCM147', u'HCM97', u'HKI128', u'HKI158', u'HKS161', u'HKS231', u'TKA230']
Here are related lines of code:
var pcode_form = document.createElement('form');
div.appendChild(pcode_form);
var pcode_select = document.createElement('select');
pcode_form.appendChild(pcode_select);
var i = 0;
var spcodelist = document.getElementById('spcodelist').value;
spcodelist = spcodelist.replace("[","");
spcodelist = spcodelist.replace("]","");
var spcodearr = new Array();
spcodearr = spcodelist.split(', ');
for (i=0;i<=spcodearr.length;i++){
spcodearr[i] = spcodearr[i].replace(/u'/g,"");
spcodearr[i] = spcodearr[i].replace(/'/g,"");
var pcode_option = document.createElement('option');
pcode_option.text = spcodearr[i];
pcode_option.value = spcodearr[i];
pcode_select.appendChild(pcode_option);
}
With this code, the dropdown list works fine but code after it will not work any more. I don't know what's the problem? How can I solve it? Or is there any better solution? Thank you very much.
I don't know what you are doing wrong, but the following works fine and should work in any browser. I've added a remove button so you can add and remove the select as often as you like.
<script type="text/javascript">
function addSelect(id) {
var div = document.getElementById(id);
var pcode_form = document.createElement('form');
pcode_form.id = 'f0';
div.appendChild(pcode_form);
var pcode_select = document.createElement('select');
pcode_form.appendChild(pcode_select);
var spcodelist = document.getElementById('spcodelist').value;
// Do replaces in one go
spcodelist = spcodelist.replace(/[\[\]\'u ]/g,'');
var spcodearr = spcodelist.split(',');
for (var i=0, iLen=spcodearr.length; i<iLen; i++) {
pcode_select.options[i] = new Option(spcodearr[i],spcodearr[i]);
}
}
</script>
<button onclick="addSelect('d0');">Add select</button>
<button onclick="
var el = document.getElementById('f0');
el.parentNode.removeChild(el);
">Remove form</button>
<div id="d0"></div>
<textarea id="spcodelist" style="display:none">[u'CA125', u'HCM112', u'HCM147', u'HCM97', u'HKI128', u'HKI158', u'HKS161', u'HKS231', u'TKA230']</textarea>