in my Google Sheets app script, I currently have three template.html files and a few scripts; I'd like to create a preview email and send it to the user once he or she is satisfied; however, the event listeners that (openAI) built for me do not work; when I change the Drop Down Menu or click send Button, nothing happens and the preview does not load. When I ask the AI for help, it keeps modifying my code; My code no longer looks like the original; after a week of trying, I've realized that I need assistance with this. Here's my most recent code as of today. The AI also insisted on using Google Drive, which I declined because I have the HTML files in the app scrip sheet itself and used to obtain it with this.
This code is not used anymore, But use to work when I used it in GmailApp to get the template File Name.
var html = HtmlService.createTemplateFromFile('Proposal Template.html');
var html = HtmlService.createTemplateFromFile('Marketing Template.html');
var html = HtmlService.createTemplateFromFile('Trusted Partner Template.html');
Keep in mind that while I am not an expert in Jave or JS, I am familiar with them.
My code
function showEmailPreview() {
// Get values from the active sheet and active row
var sheet = SpreadsheetApp.getActiveSheet();
var row = sheet.getActiveRange().getRowIndex();
var userEmail = sheet.getRange(row, getColIndexByName("Primary Email")).getValue();
var userFullName = sheet.getRange(row, getColIndexByName("Contact Full Name")).getValue();
var userCompanyName = sheet.getRange(row, getColIndexByName("Company Name")).getValue();
var title = sheet.getRange(row, getColIndexByName("Title")).getValue();
var company_location = sheet.getRange(row, getColIndexByName("Company Location")).getValue();
var company_phone1 = sheet.getRange(row, getColIndexByName("Company Phone 1")).getValue();
var subjectLine = "Company Proposal - " + userCompanyName;
// Create the select element
const select = `
<select id="template-select">
<option value="Proposal Template.html">Proposal Template</option>
<option value="Marketing Template.html">Marketing Template</option>
<option value="Trusted Partner Template.html">Trusted Partner Template</option>
</select>
`;
// Create the button element
const button = `<button id="send-button">Send Email</button>
<div id="preview"></div>`; //This could be a issue? The ai did not know where to place this or cut down before giving me a proper answer.
// Create an HTML output page that displays the email template, the select element, and a button to send the email
var output = HtmlService.createHtmlOutput(`
<script>
var buttonElement;
function getElementById(id) {
return document.getElementById(id);
}
function init() {
// Add a change event listener to the select element
document.getElementById('template-select').addEventListener('change', function() {
// Get the selected template file name
var templateFile = this.value;
// Read the contents of the selected file
var template = readFile(templateFile);
// Set values in the template
var html = HtmlService.createTemplate(template);
html.userFullName = userFullName;
html.userCompanyName = userCompanyName;
html.title = title;
html.company_location = company_location;
html.company_phone1 = company_phone1;
// Get the filled-in email template as a string
var emailTemplate = html.evaluate().getContent();
// Update the preview window with the selected template
document.getElementById('preview').innerHTML = emailTemplate;
});
// Add a click event listener to the button element
buttonElement = getElementById('send-button');
buttonElement.addEventListener('click', function() {
// Get the selected template file name
var templateFile = document.getElementById('template-select').value;
// Pass the selected template file name as an argument to the sendEmail function
sendEmail(templateFile);
});
}
window.onload = init;
function sendEmail(templateFile) {
// Read the contents of the selected file
var template = readFile(templateFile);
// Set values in the template
var html = HtmlService.createTemplate(template);
html.userFullName = userFullName;
html.userCompanyName = userCompanyName;
html.title = title;
html.company_location = company_location;
html.company_phone1 = company_phone1;
// Get the filled-in email template as a string
var emailTemplate = html.evaluate().getContent();
// Send the email
GmailApp.sendEmail(userEmail, subjectLine, '', {htmlBody: emailTemplate});
}
</script>
<script>
init();
</script>
${select}
${button}
`)
.setWidth(950)
.setHeight(750)
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
// Display the output page in a modal dialog box
SpreadsheetApp.getUi().showModalDialog(output, 'Email Preview');
//output.evaluate();
//window.onload = init;
};
function readFile(templateFile) {
// Get the contents of the selected file
var file = DriveApp.getFilesByName(templateFile);
var contents = file.next().getBlob().getDataAsString();
return contents;
}//window.onload = init;
Results.
Here is a link for testing.
https://docs.google.com/spreadsheets/d/1gXDbtjCYfZw8kOaOMorbJ54dXyl7bh6MFM1LopTrNww/edit?usp=sharing
Its always like this when you struggle for a week and give up, And you finally post something and then you find yourself a solution. So here is the correct way of doing it.
Let's first talk about the menu. I created a file template-select-menu.gs
<form>
<label for="template">Select a template:</label><br>
<select id="template" name="template">
<option value="Proposal Template.html">Proposal Template</option>
<option value="Markting Template">Marketing Template</option>
</select>
<br><br>
<input type="button" value="Preview" onclick="google.script.run.onTemplateSelected(document.forms[0].template.value)">
</form>
then I have my preview_email.gs
function showEmailPreview() {
// Get values from the active sheet and active row
var sheet = SpreadsheetApp.getActiveSheet();
var row = sheet.getActiveRange().getRowIndex();
var rate = sheet.getLastRow();
var userEmail = sheet.getRange(row, getColIndexByName("Primary Email")).getValue();
var userFullName = sheet.getRange(row, getColIndexByName("Contact Full Name")).getValue();
var userCompanyName = sheet.getRange(row, getColIndexByName("Company Name")).getValue();
var subjectLine = "Company Proposal - " + userCompanyName ;
var aliases = GmailApp.getAliases()
// Create the email template selection menu
var proposalTemplate = HtmlService.createTemplateFromFile('Proposal Template.html');
var marktingTemplate = HtmlService.createTemplateFromFile('Markting Template.html');
var selectMenu = HtmlService.createTemplateFromFile('template-select-menu.html');
var selectMenuHtml = selectMenu.evaluate().getContent();
// Create an HTML output page that displays the email template selection menu and a button to send the email
var output = HtmlService.createHtmlOutput(selectMenuHtml)
.setWidth(600)
.setHeight(450);
// Display the output page in a modal dialog box
SpreadsheetApp.getUi().showModalDialog(output, 'Email Preview');
}
/**
* This function is called when the user selects a template from the drop-down menu.
* It creates an email preview using the selected template and displays it in the modal dialog box.
*/
//var html = HtmlService.createTemplateFromFile(templateFileName);
function onTemplateSelected(templateFileName) {
// Get values from the active sheet and active row
var sheet = SpreadsheetApp.getActiveSheet();
var row = sheet.getActiveRange().getRowIndex();
var rate = sheet.getLastRow();
var userEmail = sheet.getRange(row, getColIndexByName("Primary Email")).getValue();
var userFullName = sheet.getRange(row, getColIndexByName("Contact Full Name")).getValue();
var userCompanyName = sheet.getRange(row, getColIndexByName("Company Name")).getValue();
var subjectLine = "Company Proposal - " + userCompanyName ;
var aliases = GmailApp.getAliases();
// Create the email template and set values in the template
if (templateFileName == 'Proposal Template.html') {
var proposalTemplate = HtmlService.createTemplateFromFile('Proposal Template.html');
proposalTemplate.userFullName = userFullName;
proposalTemplate.userCompanyName = userCompanyName;
var template = proposalTemplate.evaluate().getContent();
} else if (templateFileName == 'Markting Template') {
var marktingTemplate = HtmlService.createTemplateFromFile('Markting Template.html');
marktingTemplate.userFullName = userFullName;
marktingTemplate.userCompanyName = userCompanyName;
var template = marktingTemplate.evaluate().getContent();
} else {
var template = selectMenuHtml;
}
// Create an HTML output page that displays the email template and a button to send the email
var selectMenu = HtmlService.createTemplateFromFile("template-select-menu.html");
var selectMenuHtml = selectMenu.evaluate().getContent();
var output = HtmlService.createHtmlOutput(template)
.setWidth(600)
.setHeight(450)
.setSandboxMode(HtmlService.SandboxMode.IFRAME)
.setContent(selectMenuHtml + '<br><br>' + template);
// Update the modal dialog box with the new email template
SpreadsheetApp.getUi().showModalDialog(output, 'Email Preview');
}
Now create the the 2 files "Proposal Template.html" and "Markting Template.html". When you switch and click preview the content will change.
Please note that I still need to update the email buttons. but this is a great start for me.
Related
I am creating a web app using Google Apps Script. So this app basically is meant to send quotations to user by collecting various parameters. The deployment has 3 views. The first asks for Email and Plant Type. The second view asks for 4 parameters. The third view shows recommendation after some processing on server side along with other 2 inputs.
The problem is that I have to append a row after the submit button is clicked on the third view. So that a new row is created in my linked google sheets as a database with all the inputs from user. The script was running fine when there was 1 view. But as I made 3 views, it's now not appending a new row in google sheets.
The Object "Info" is where I am storing inputs from user.
Here's the script:
<script>
document.addEventListener('DOMContentLoaded', function() {
var elems = document.querySelectorAll('select');
var instances = M.FormSelect.init(elems);
});
var Info = {};
document.getElementById("btn1").addEventListener("click",dothis);
function dothis(){
Info.email = document.getElementById("email").value;
Info.ptype = document.getElementById("ptype").value;
}
document.getElementById("btn2").addEventListener("click",thenthis);
function thenthis(){
Info.quantity = document.getElementById("quantity").value;
Info.hotwt = document.getElementById("hotwt").value;
Info.coldwt = document.getElementById("coldwt").value;
Info.wetbt = document.getElementById("wetbt").value;
}
document.getElementById("submit").addEventListener("click",andthenthis);
function andthenthis(){
Info.recomcell = document.getElementById("recomcell").value;
Info.prefercells = document.getElementById("prefercells").value;
Info.coc = document.getElementById("coc").value;
google.script.run.UserClicked(Info);
document.getElementById("recomcell").value = "";
M.updateTextFields();
var mycoc = document.getElementById("coc");
mycoc.selectedIndex = 0;
M.FormSelect.init(mycoc);
var myprefercells = document.getElementById("prefercells");
myprefercells.selectedIndex = 0;
M.FormSelect.init(myprefercells);
}
</script>
Here's the other part of the code:
function UserClicked(Info){
var ss = SpreadsheetApp.openByUrl(url);
var ws = ss.getSheetByName("Database");
ws.appendRow([Info.email,Info.ptype,Info.quantity,Info.hotwt,Info.coldwt,Info.wetbt,Info.recomcell,Info.prefercells,Info.coc,new Date()]);
}
I have a form with an input type "text" which has an autofill function from a list that is fed from a spreadsheet in google drive (this works fine); by selecting the desired option from the list; I want another field in the form to be filled automatically with the cell next to the right, that is, if I select the data (character string) of cell I5 with the auto-complete option, the new text field should be filled automatically with the contents of cell J5 (this does not work). The event I use does not capture the entire string of cell I5, but only the typed characters, can anyone help me?
I have this code:
//page-js.html
document.addEventListener('DOMContentLoaded', function() {
document.getElementById("redIps").addEventListener("blur",getRegimenIps);
google.script.run.withSuccessHandler(populateRed).getRed();
});
//page-js.html
function getRegimenIps(){
var redIpsStr = document.getElementById("redIps").value;//****not capture the entire string***
google.script.run.withSuccessHandler(updateIpsReg).getIpsReg(redIpsStr);
}
//page-js.html
function updateIpsReg(regimen){
document.getElementById("redIpsReg").value = regimen;
M.updateTextFields();
}
//funcs.gs
function getRed(){ //****This works fine ****
var ss = SpreadsheetApp.openByUrl(url);
var ws = ss.getSheetByName("listas");
var data = ws.getRange(1,9).getDataRegion().getValues();
var options = {};
data.forEach(function(v){
options[v[0]]=null;
});
return options
}
//funcs.gs
function getIpsReg(redIpsStr){ //****This does not work****
var ss = SpreadsheetApp.openByUrl(url);
var ws = ss.getSheetByName("listas");
var data = ws.getRange(1,9,ws.getLastRow(),2).getValues();
var redIpsList = data.map(function(r){ return r[0]; });
var regList = data.map(function(r){ return r[1]; });
console.log(redIpsStr);
var position = redIpsList.indexOf(redIpsStr);
if (position > -1){
return regList[position].toFixed(2);
}else{
return 'Unavailable';
}
}//end getIpsReg(redIpsStr)
I'm using Firebase to store users info and I'm wanting to populate divs with each users info so it can be either accepted or deleted (but not deleted from Firebase).
So I wanted it to be structured something like this:
----------------------
Name
Email
Date
----------------------
Name
Email
Date
----------------------
and so on....
What I'm currently getting back is something like this:
What is the proper way to generate a div dependent upon how much data is in Firebase and format the content as specificed?
HTML:
<div>Some entry here
<h4 id="name"></h4>
<h4 id="date"></h4>
<h6 id="email"></h6>
<button id="0" class="remove">Remove</button>
</div>
<div>Another entry here
<button id="1" class="remove">Remove</button>
</div>
Javascript:
var ref = firebase.database().ref('requests');
ref.on('value', function(snapshot) {
snapshot.forEach(function(child) {
var datas = child.val();
var email = child.val().Email;
var name = child.val().Name;
var date = child.val().Scheduled_Date;
date = date.replace('.', '/');
$('#name').append(name);
$('#email').append(email);
$('#date').append(date);
});
});
For each child, you are appending the values to the same HTML elements (i.e. all the names are appended to the h4 element with id "name", all the emails to the one with id "email" and so on).
So it is normal they are displayed on a line (one row).
You have to create a new placeholder for each child (and it's set of values). You can do that with e.g. a table, like:
var tableRef = document.getElementById('myTable').getElementsByTagName('tbody')[0];
var ref = firebase.database().ref('requests');
ref.on('value', function(snapshot) {
snapshot.forEach(function(child) {
var datas = child.val();
var email = child.val().Email;
var name = child.val().Name;
var date = child.val().Scheduled_Date;
date = date.replace('.', '/');
// Insert a row in the table at the last row
var newRow = tableRef.insertRow(tableRef.rows.length);
// Insert a cell in the row at index 0
var newCell = newRow.insertCell(0);
// Append a text node to the cell with name value
var newText = document.createTextNode(name); // <-- name value from the child
newCell.appendChild(newText);
var newRow = tableRef.insertRow(tableRef.rows.length);
var newCell = newRow.insertCell(0);
var newText = document.createTextNode(email); // <-- email value from the child
newCell.appendChild(newText);
var newRow = tableRef.insertRow(tableRef.rows.length);
var newCell = newRow.insertCell(0);
var newText = document.createTextNode(date); // <-- date value from the child
newCell.appendChild(newText);
});
});
Inspired by How to insert row in HTML table body in Javascript?. See the fiddle in this SO post.
Or you can do it with divs, here is a possible code:.
HTML
<div id="parentDiv"></div>
JavaScript
var element;
var ref = firebase.database().ref('requests');
ref.on('value', function(snapshot) {
snapshot.forEach(function(child) {
var datas = child.val();
var email = child.val().Email;
var name = child.val().Name;
var date = child.val().Scheduled_Date;
date = date.replace('.', '/');
element = document.createElement("div");
element.appendChild(document.createTextNode(name));
document.getElementById('parentDiv').appendChild(element);
element = document.createElement("div");
element.appendChild(document.createTextNode(email));
document.getElementById('parentDiv').appendChild(element);
element = document.createElement("div");
element.appendChild(document.createTextNode(date));
document.getElementById('parentDiv').appendChild(element);
//You could add a specific css class to this div to generate the bottom border
});
});
To be complete, note that you could also use some MVVM javascript frameworks like vue.js, knockout.js as well as angular, react... in order to easily reflect in your HTML DOM the results of queries to your backend (and vice-versa).
I have One simple registration Form which is developed in C#.Net. This form also contain one Grid view which display data from database.In this,I want to disable Insert button when i select particular raw data. and i had develop this code in jquery. I used below code.
function DoStuff(lnk) {
debugger;
var grid = document.getElementById('GridView1');
var cell, row, rowIndex, cellIndex;
cell = lnk.parentNode;
row = cell.parentNode;
rowIndex = row.rowIndex;
cellIndex = cell.cellIndex;
var rowId = grid.rows[rowIndex].cells[0].textContent;
var rowname = grid.rows[rowIndex].cells[1].textContent;
var rowcontact = grid.rows[rowIndex].cells[2].innerHTML;
var rowaddress = grid.rows[rowIndex].cells[3].innerHTML;
var rowemail = grid.rows[rowIndex].cells[4].innerHTML;
var Id = document.getElementById('txt_Id');
var name = document.getElementById('txt_Name');
var contact = document.getElementById('txt_PhoneNumber');
var address = document.getElementById('txt_Address');
var email = document.getElementById('txt_EmailId');
Id.value = rowId;
name.value = rowname;
contact.value = rowcontact;
address.value = rowaddress;
email.value = rowemail;
document.getElementById('Button1').disabled = true;
};
But when i run that page it becomes disable and immediately enable automatically.....:(
Can anyone give me solution ???
You have to call this function after form is completely loaded.
Use below code to make it that happen if you are using jQuery.
$( document ).ready(function() {
DoStuff(lnk);
});
I made the following code to replace form fields in a page that I can't edit but only manipulate. However, the code does nothing. In chrome console when I print a variable it works fine. The code is below:
//GET val from drop DROP DOWN
var office_id = FieldIDs["OfficeName"];//Gets the input id
var offices;//gets the value from the drop down
$("#FIELD_"+office_id).change(function(){
offices = $(this).val();
}).change();
//The below gets the id's of all the input fields
var address_id = FieldIDs["Address"];
var address2_id = FieldIDs["Address2"];
var city_id = FieldIDs["City"];
var state_id = FieldIDs["State"];
var zip_id = FieldIDs["Zip"];
var phone_4id = FieldIDs["Number4"];//phone
var phone_id = FieldIDs["Number1"];//fax
var pdfm4 = FieldIDs["pdfm4"];
var pdfm = FieldIDs["pdfm"];
if(offices == "SoCal Accounting"){
$('#FIELD_'+address_id).val("7421 Orangewood Avenue");
$('#FIELD_'+address2_id).val("");
$('#FIELD_'+city_id).val("Garden Grove");
$('#FIELD_'+state_id).val("CA");
$('#FIELD_'+zip_id).val("92841");
$('#FIELD_'+phone_4id).val("+1 714.901.5800");//phone
$('#FIELD_'+phone_id).val("+1 714.901.5811");//fax
}