Undefined variables in html templates for MailApp - javascript

I am trying to send an HTML email using MailApp.
This is the table where I will pull the data from:
After reading the documentations and posts on SO, I am still unable to pin point why the email sent out is showing undefined in the variables part.
Would appreciate if someone can point me to the right direction.
These are my codes:
sendHtmlEmail.gs
function sendEmails() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var lastRow = ss.getLastRow();
var quotaLeft = MailApp.getRemainingDailyQuota();
if((lastRow-1) > quotaLeft){
Browser.msgBox("You have " + quotaLeft + " email quota left and you're trying to send " + (lastRow-1) + " emails. Emails were not sent.")
} else {
for (var row = 2; row <= lastRow; row++){
var currentEmail = ss.getRange(row, 4).getValue();
var currentContact = ss.getRange(row, 3).getValue();
var currentNewSize = ss.getRange(row,8).getValue();
var currentSub = ss.getRange(row, 9).getValue();
var returnData = [currentContact, currentNewSize, currentSub];
var html = HtmlService.createTemplateFromFile('htmlTemplate');
html.data = returnData;
var template = html.evaluate().getContent();
var subjectLine = "Important notice";
MailApp.sendEmail({to: currentEmail, subject: subjectLine, htmlBody: template});
} //close for loop
Browser.msgBox("You have successfully sent " + (lastRow-1) + " emails.")
} //close else statement
}
htmlTemplate.html
<!DOCTYPE html><html><head><base target="_top"></head><body style="text-align: center;font-family: Arial;">
<div id="center" style="width:300px;border: 2px dotted grey;background:#ececec;margin:25px;margin-left:auto;
margin-right:auto;padding:15px;"><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/4/4f/Simple_Alert.svg/600px-Simple_Alert.svg.png"
width="180" style="margin:10px 0px"><br /><div style=" border: 2px dotted grey;background:white;margin-right:auto; margin-left:auto;
padding:10px;"><h2>Alert</h2><h3>Important Notice <br /><br />
+ <?= data.currentContact ?> + '<br />' + <?= data.currentNewSize ?> + '<br />' + <?= data.currentSub ?> + '<br /></h3></div></body></html>'
I know that it is something to do with the htmlTemplate data.currentNewSize etc, but after tweaking my codes they are still showing undefined as shown in the image.

You are using an array in the method while the template is expecting an object.
Replace
var returnData = [currentContact, currentNewSize, currentSub];
with
var returnData = {currentContact: currentContact, currentNewSize: currentNewSize, currentSub: currentSub}

The issue lies in the html code. As I have declared the array in sendHtmlEmail.gs, I did not call it correctly in my htmlTemplate.html.
In this line:
var returnData = [currentContact, currentNewSize, currentSub];
currentContact is in position 0, currentNewSize is in position 1 and so forth.
In the htmlTemplate.html, I need to replace this line:
+ <?= data.currentContact ?> + '<br />' + <?= data.currentNewSize ?> + '<br />' + <?= data.currentSub ?> + '<br /></h3></div></body></html>'
with this:
+ <?= returnData[0];?> + '<br />' + <?= returnData[1];?> + '<br />' + <?= returnData[2];?> + '<br /></h3></div></body></html>'

Related

How do I insert an object data array into a database with AJAX

I want to insert data from an array into a database table in the submit() function where the sql syntax is at. I want to insert the data then redirect to another page after successful. I don't know how to do this with ajax.
I tried to make ajax syntax but I don't know if i'm passing the data correctly for obj.name and obj.books corresponding to their own values in the array.
example:
[{"name":"book1","books":["thisBook1.1","thisBook1.2"]},{"name":"book2","books":["thisBook2.1","thisBook2.2","thisBook2.3"]}]
function submit(){
var arr = [];
for(i = 1; i <= authors; i++){
var obj = {};
obj.name = $("#author" + i).val();
obj.books = [];
$(".auth" + i).each(function(){
var data = $(this).val();
obj.books.push(data);
});
//sql = ("INSERT INTO table (author, book) VALUES ('obj.name', 'obj.books')");
//mysqli_query(sql);
arr.push(obj);
}
$("#result").html(JSON.stringify(arr));
}
/////////////////////////////////
//I tried this:
$.ajax({
type: "POST",
data: {arr: arr},
url: "next.php",
success: function(){
}
});
/////////////////////////////////
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<style type="text/css">
<!-- #main {
max-width: 800px;
margin: 0 auto;
}
-->
</style>
</head>
<body>
<div id="main">
<h1>Add or Remove text boxes with jQuery</h1>
<div class="my-form">
<form action"next.php" method="post">
<button onclick="addAuthor()">Add Author</button>
<br>
<br>
<div id="addAuth"></div>
<br>
<br>
<button onclick="submit()">Submit</button>
</form>
</div>
<div id="result"></div>
</div>
<script type="text/javascript">
var authors = 0;
function addAuthor() {
authors++;
var str = '<br/>' + '<div id="auth' + authors + '">' + '<input type="text" name="author" id="author' + authors + '" placeholder="Author Name:"/>' + '<br/>' + '<button onclick="addMore(\'auth' + authors + '\')" >Add Book</button>' + '</div>';
$("#addAuth").append(str);
}
var count = 0;
function addMore(id) {
count++;
var str = '<div id="bookDiv' + count + '">' + '<input class="' + id + '" type="text" name="book' + id + '" placeholder="Book Name"/>' + '<span onclick="removeDiv(\'bookDiv' + count + '\')" style="font-size: 20px; background-color: red; cursor:pointer; margin-left:1%;">Remove</span>' + '</div>';
$("#" + id).append(str);
}
function removeDiv(id) {
//var val = confirm("Are you sure ..?");
//if(val){
$("#" + id).slideUp(function() {
$("#" + id).remove();
});
//}
}
function submit() {
var arr = [];
for (i = 1; i <= authors; i++) {
var obj = {};
obj.name = $("#author" + i).val();
obj.books = [];
$(".auth" + i).each(function() {
var data = $(this).val();
obj.books.push(data);
});
// sql = ("INSERT INTO table (author, book) VALUES ('obj.name', 'obj.books')");
// mysqli_query(sql);
arr.push(obj);
}
$("#result").html(JSON.stringify(arr));
}
</script>
</body>
</html>
Send your array to server ,stringify array before sending it to server so in server you can decode json and recover your array, and then insert received data to database
JS
function submit(){
var arr = [];
for(i = 1; i <= authors; i++){
var obj = {};
obj.name = $("#author" + i).val();
obj.books = [];
$(".auth" + i).each(function(){
var data = $(this).val();
obj.books.push(data);
});
//sql = ("INSERT INTO table (author, book) VALUES ('obj.name', 'obj.books')");
//mysqli_query(sql);
arr.push(obj);
}
sendToServer(arr)
$("#result").html(JSON.stringify(arr));
}
function sendToServer(data) {
$.ajax({
type: "POST",
data: {arr: JSON.stringify(data)},
url: "next.php",
success: function(){
}
});
}
PHP (next.php)
$data = json_decode(stripslashes($_POST['arr']));
foreach($data as $item){
echo $d;
// insert to db
}
Please Keep the following in mind
Javascript/JQuery is client side and hence cannot access the database which is on the server.
You can Send data via AJAX to next.php and then use this data to insert into your database.
To improve debugging, use the following code to ensure the correct data is being delivered in next.php
var_dump($_POST);
Your SQL statements must be executed in next.php using the data passed by $_POST (since your "type" of AJAX request is post).

Getting an image source from JSON data

I'm attempting to call a PHP file and have it return a result (a single record's 'pageLocation') from a database table ('page'). I then want to get that result into a variable, so I can use it while creating an image in html.
Currently, the image is being created but the source is not feeding into it, leaving a default empty image at the correct size.
Javascript:
// Loads a list of comics created by the user from the database.
function loadComic()
{
var xmlhttp = new XMLHttpRequest();
var getID = '<?php echo $_SESSION["userID"]; ?>';
var url = "loadCom.php?userID="+getID;
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState == 4 && xmlhttp.status == 200)
{
loadComicJSON(xmlhttp.responseText);
}
}
xmlhttp.open("GET", url, true);
xmlhttp.send();
}
// JSON parsing for 'loadComic'.
function loadComicJSON(response)
{
var arr = JSON.parse(response);
var i;
var out = "";
document.getElementById("loadList").innerHTML="";
if (arr.length == 0)
{
//Non-relevant code affecting layout if no comics are found.
}
else
{
out+="<br>";
for(i = 0; i < arr.length; i++)
{
// Gets image source from database.
imgSrc = "";
tempID = arr[i].comicID;
$.post("getCover.php", {'comicID':tempID}, function(result)
{
imgSrc += ("" + result);
}
);
// Creates image item and associated radio button.
out += "<hr><br><img name = '" + ('com' + arr[i].comicID) + "' id='" + ('com' + arr[i].comicID) + "' onclick='resizeThumb(this)' height='100px;' src='" + imgSrc + "'><input name='comicList' type='radio' id='" + arr[i].comicID + "' value='" + arr[i].comicID + "'>" + arr[i].comicName + " </option><br><br>";
}
}
}
</script>
PHP (getCover.php):
<?php
if (isset($_POST["comicID"]))
{
include_once('includes/conn.inc.php');
$checkID = $_POST["comicID"];
$query = ("SELECT FIRST (pageLocation) FROM page WHERE comicID = '$checkID' ORDER BY pageNum");
$result = mysqli_query($conn, $query);
$conn->close();
echo ($result);
}
else
{
$checkID = null;
echo "Error. No comic found.";
}
?>
Thanks for any help provided.
You need to get he data from the result, like:
$row = $result->fetch_assoc()
Also, yes, Jim G is right, you need to escape that POST variable.

$.getJSON always failing

Apologies if this has been answered before but I couldn't find what I was looking for. So, I use $.getJSON to send some variables to a php file. The file returns success as true but for some reason always triggers the .fail function.
The weird thing is, it all works fine on my laptop, just not on the computer at university. Connection to the database is fine, like I said everything works and it returns all the correct data but doesn't trigger the success function.
JQuery:
function request_user_review() {
$.getJSON("user_review_list.php", success_user_review).fail(fail_user_review);
}
function success_user_review(response) {
if (response.success) {
var user_review_list = "";
$("#user_reviews .review_cafe").remove();
$("#user_reviews .review").remove();
$("#user_reviews .rating").remove();
$("#user_reviews .review_choice").remove();
for (var i = 0; i < response.rows.length; i++) {
var review_cafe = '<tr id="row_' + response.rows[i].id + '"><td class="review_cafe">'
+ response.rows[i].cafe + '</td>';
var review = '<td class="review">'
+ response.rows[i].review + '</br>Review left: ' + response.rows[i].date + '</td>';
var rating = '<td class="rating">'
+ response.rows[i].rating + '/5</td>';
var review_choice = '<input type="hidden" class="cafe_id" value="' + response.rows[i].cafe_id + '" /><td class="review_choice"><button onclick="request_edit(this.id)" id="edit_' + response.rows[i].id + '" class="btn_edit">Edit</button><button onclick="request_delete_review(this.id)" id="delete_' + response.rows[i].id + '" class="btn_delete">Delete</button></td></tr>';
user_review_list += review_cafe + review + rating + review_choice;
}
$("#user_reviews").html(user_review_list).trigger("create").trigger("refresh");
} else {
$("#review_message").html("Review failed to be loaded!").trigger("create").trigger("refresh");
}
}
function fail_user_review() {
$("#review_message").html("Connection down?").trigger("create").trigger("refresh");
}
PHP:
<?php //user_review_list.php
require_once "sql.php"; //connection to database and query is handled here
require_once "logged_in.php";
error_reporting(E_ALL ^ E_NOTICE);
ini_set('display_errors','On');
$session_id = $_SESSION['userid'][0];
$result = array();
$result['success'] = false;
$query = "SELECT * FROM reviews WHERE user = $session_id;";
if ($result_set = Sql::query($query)) {
$result['success'] = true;
$result['message'] = "Your Reviews" ;
$rows = mysqli_num_rows($result_set);
$result['rows'] = array();
for ($i = 0; $i<$rows; $i++) {
$tmpRow = mysqli_fetch_assoc($result_set);
$php_date = strtotime($tmpRow['date']);
$formatted_php_date = date('M d, Y', $php_date );
$tmpRow['date'] = $formatted_php_date;
$result['rows'][$i] = $tmpRow;
}
} else {
$result['message'] = "Failed to read Reviews" ;
}
print(json_encode($result));
Thanks
James
The messages you get mean you're trying to parse something that's already JSON. My earlier statement about parsing JSON is not going to be of much help here because you're not just getting back a string that needs to be converted to JSON -- which you really shouldn't be with $.getJSON().
You're getting back a JSON with an invalid encoding somewhere along the line, so trying to parse it won't help you. Validate your JSON first and foremost (the error could be due to your differing server settings between machines) using jsonlint, and continue from there.

.html() help dont know how to handle it

...
success: function (reqCode) {
if (reqCode['error_code'] == 1) {
//Generiere Tabelle
$(".done").html(
'<p class="bold center"><?php echo "Besucher ".$month_name[' + reqCode['month'] + ']." ".' + reqCode['year'] + '; ?></p>'
'<canvas id="cvs" width="680" height="250">[No canvas support]</canvas>'
'<script>'
'chart = new RGraph.Line("cvs", ' + reqCode['data_string'] + ');'
'chart.Set("chart.tooltips", ' + reqCode['labels_string'] + ');'
'chart.Set("chart.tooltips.effect", "expand");'
'chart.Set("chart.background.grid.autofit", true);'
'chart.Set("chart.gutter.left", 35);'
'chart.Set("chart.gutter.right", 5);'
'chart.Set("chart.hmargin", 10);' +
'chart.Set("chart.tickmarks", "circle");'
'chart.Set("chart.labels", ' + $reqCode['labels_tooltip'] + ');'
'chart.Draw();'
'</script>'
);
$('.done').fadeOut('slow');
$('.done').fadeIn('slow');
}
}
I don't know why every new line needs its own '..'. Anyway it's not working. Looked into the API reference but found nothing useful :(
Edit: For my second question:
This is what JSON response:
$response['error_code'] = '1';
$response['data_string'] = "[" . join(", ", $data) . "]";
$response['labels_string'] = "['" . join("', '", $labels) . "']";
$response['labels_tooltip'] = "['" . join("', '", $data) . "']";
$response['month'] = $month_name[$month];
$response['year'] = $year;
echo json_encode($response);
There does seem to be something wrong with that <script> tag, but really? You don't need to insert that <script> tag. You're already running JavaScript; just do this:
success: function (reqCode) {
if (reqCode['error_code'] == 1) {
var month_name = <?php echo json_encode($month_name); ?>;
//Generiere Tabelle
$(".done").html(
'<p class="bold center">Besucher ' + month_name[reqCode['month']] + ' ' + reqCode['year'] + '</p>'+
'<canvas id="cvs" width="680" height="250">[No canvas support]</canvas>'
);
var chart = new RGraph.Line("cvs", reqCode['data_string']);
chart.Set("chart.tooltips", reqCode['labels_string']);
chart.Set("chart.tooltips.effect", "expand");
chart.Set("chart.background.grid.autofit", true);
chart.Set("chart.gutter.left", 35);
chart.Set("chart.gutter.right", 5);
chart.Set("chart.hmargin", 10);
chart.Set("chart.tickmarks", "circle");
chart.Set("chart.labels", reqCode['labels_tooltip']);
chart.Draw();
$('.done').fadeOut('slow');
$('.done').fadeIn('slow');
}
}
I've fixed some syntax errors in there, though I can't guarantee that there are none left. Just watch the JavaScript console for errors.
You should have a container element with class done on it, like:
<div class="done" />
In addition, you can short:
$('.done').html('..all the html..').fadeOut('slow').fadeIn('slow');
Moreover, as Vivin Paliath said, you should concat all the strings in the html using +
'<a>'+
'asdsad'+
'</a>'
Good Luck!
You need + signs
success: function (reqCode) {
if (reqCode['error_code'] == 1) {
//Generiere Tabelle
$(".done").html('<p class="bold center"></p>'+
'<canvas id="cvs" width="680" height="250">[No canvas support]'+
'<script>'+
'chart = new RGraph.Line("cvs", ' + reqCode['data_string'] + ');'+
'chart.Set("chart.tooltips", ' + reqCode['labels_string'] + ');'+
'chart.Set("chart.tooltips.effect", "expand");'+
'chart.Set("chart.background.grid.autofit", true);'+
'chart.Set("chart.gutter.left", 35);'+
'chart.Set("chart.gutter.right", 5);' +
'chart.Set("chart.hmargin", 10);' +
'chart.Set("chart.tickmarks", "circle");'+
'chart.Set("chart.labels", ' + $reqCode['labels_tooltip'] + ');'+
'chart.Draw();'+
''
);
$('.done').fadeOut('slow');
$('.done').fadeIn('slow');
}
}
You need to pass a single string to the html() function. Something like:
$(".done").html("<p>hello</p><p>goodbye</p>").
If you need to combine multiple strings you will need to use string concatenation, like:
var combinedString = '<p>hello</p>' + '<p>goodbye</p>'

Splitting an array

I have two javascript functions, the first one is working, teh second is working but not echoing the correct value in the hidden inputs.
Ive manage to get the last hidden input value correct but I'm not sure how
var customTicketsArr = Array();
function EditEventAddTicket(){
alertWrongTime = false;
var TicketName = jQuery("#ticketname").val();
var TicketPrice = jQuery("#ticketprice").val();
var ticketquantity = jQuery("#ticketquantity").val();
var storeString = "TicketName" + TicketName + "TicketPrice" + TicketPrice + "Quantity" + ticketquantity + '';
customTicketsArr.push(storeString);
EditEventUpdateTickets(true);
}
function EditEventUpdateTickets(fade){
jQuery("#custom_tickets_string").val(customTicketsArr);
var output = "";
var style = "";
for (i = customTicketsArr.length-1; i >= 0; i--){
ticketname = customTicketsArr[i].split("TicketName");
ticketprice = customTicketsArr[i].split("TicketPrice");
ticketquantity = customTicketsArr[i].split("Quantity");
if(fade){
if (customTicketsArr.length - 1 == i){
style = "display: none; ";
var fadeInDiv = i;
} else {
style = "";
}
}
if (i % 2 == 1) { style += "background-color: #660000; "}
html = "<div id='customticket" + i + "' class='customeventbase' style='" + style + "'>";
html += '<input type="hidden" name="customTicketid[' + i + '][Name]" id="customticketName' + i + '" value="'+ ticketname + '" />';
html += '<input type="hidden" name="customTicketid[' + i + '][Price]" id="customticketPrice' + i + '" value="' +ticketprice[1] +'" />';
html += '<input type="hidden" name="customTicketid[' + i + '][Quantity]" id="customticketQuantity' + i + '" value="'+ ticketquantity[1] +'" />';
html += '<button class="customeventdel" type="button" onClick="EditEventRemoveDate(' + i + ')"></button>';
html += '<div class="clear"></div>';
html += '</div>\n';
output += html;
}
output += "<input type='hidden' id='custom_ticket_info' name='custom_ticket_info' value='" + customTicketsArr + "' />";
jQuery("#custom_ticket_container").html(output);
if(fade){
setTimeout("EditEventfadeInDiv(" + fadeInDiv +")", 10);
}
}
this outputs:
<div style="background-color: #660000; " class="customeventbase" id="customticket1">
<input type="hidden" value=",testTicketPrice50Quantity44" id="customticketName1" name="customTicketid[1][Name]">
<input type="hidden" value="undefined" id="customticketPrice1" name="customTicketid[1][Price]">
<input type="hidden" value="44" id="customticketQuantity1" name="customTicketid[1][Quantity]">
<button onclick="EditEventRemoveDate(1)" type="button" class="customeventdel"></button>
<div class="clear"></div></div>
the values for the first two hidden fields are incorrect
They're not incorrect values - split() is doing exactly what it is supposed to - returning an array of substrings after removing the separator.
With your string structure, splitting on TicketName will give you two strings - the substring before the separator and the substring after - TicketName itself is not included.
Thus, for the string "TicketNametestTicketPrice50Quantity44", you will get "" and "testTicketPrice50Quantity44" when you split on "TicketName" . Splitting the same string on TicketPrice will give you "TicketNametest" and "50Quantity44".
I'd suggest putting objects into your array instead -
var storeObject = {
"TicketName" : TicketName,
"TicketPrice" : TicketPrice,
"Quantity" : ticketquantity
};
customTicketsArr.push(storeObject);
You can then get back the data as:
for (i = customTicketsArr.length-1; i >= 0; i--){
var currentObject = customTicketsArr[i];
var ticketname = currentObject.TicketName;
var ticketprice = currentObject.TicketPrice;
var ticketquantity = currentObject.Quantity;
//do other stuff here
}
why do you save it as a string? I would recommend storing it in an object:
function EditEventAddTicket(){
alertWrongTime = false;
var TicketName = jQuery("#ticketname").val();
var TicketPrice = jQuery("#ticketprice").val();
var ticketquantity = jQuery("#ticketquantity").val();
var ticket = {"TicketName": TicketName, "TicketPrice": TicketPrice, "Quantity": ticketquantity};
customTicketsArr.push(ticket);
EditEventUpdateTickets(true);
}
and then you can simply load the data:
for (i = customTicketsArr.length-1; i >= 0; i--){
ticketname = customTicketsArr[i].TicketName;
ticketprice = customTicketsArr[i].TicketPrice;
ticketquantity = customTicketsArr[i].Quantity;
// ...
}
Why not just make a two dimensional array?
var customTicketsArr = Array();
function EditEventAddTicket() {
customTicketsArr.push({
'name' : jQuery("#ticketname").val(),
'price' : jQuery("#ticketprice").val(),
'qty' : jQuery("#ticketquantity").val()
});
}

Categories

Resources