I'm new to javascript and HTML, and I am looking to dynamicaly create a table with a loop in javascript inside of a HTML file.
I have the code to create a table, but I am struggling to get it to increase by one cell each row.
I feel as though I need to add 1 my cell variable each time the for loop runs, I assume its something like cells++ but when ever I do this the html file wont load anything, any ideas on where to place it within my for loops? or am I totaly on the wrong path?
<script>
var table = "", rows = 1, cells = 1;
for (var r = 0; r < rows; r++) {
table += "<tr>";
for (var c = 1; c <= cells; c++) {
table += "<td>" + c + "</td>"
}
table += "</tr>"
}
document.write("<table border =1>" + table + "</table>")
</script>
This is what I want it to look like:
In order to get "stairs" look-like table, the amounts of rows and cells should be equal. Example below is how to do it properly. In order to change amount of rows, change value of variable from 7 to what you want ;)
var table = "";
rows = 7;
for (var r = 0; r <= rows; r++) {
table += "<tr>";
for (var c = 1; c <= r; c++) {
table += "<td>" + c + "</td>";
}
table += "</tr>";
}
document.write("<table border =1>" + table + "</table>");
I'm a total novice at Javascript, but I was able to modify some scripts I found online to get a row emailed to the address in column B of that row. There are three places where I'm totally stuck:
How do I trigger the script to run when column B is updated?
In line two of my code, I've hard coded the row number as variable dataRow. How do I get the updated row from my spreadsheet?
The HTML is rendering in some instances, but not others. The td width in line 22 is not functioning, not is any of the html formatting in lines 46 and 47. I've tried a couple of techniques but nothing is working.
Thank you!
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var dataRow = 232; //updated row in spreadhseet
var sh = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var data = sh.getRange("E:T").getValues();
var TABLEFORMAT = 'cellspacing="2" cellpadding="2" dir="ltr" border="1" style="table-layout:fixed;font-size:10pt;font-family:arial,sans,sans-serif;border-collapse:collapse;border:1px solid #ccc;font-weight:normal;color:black;background-color:white;text-align:center;text-decoration:none;font-style:normal;"'
var htmltable = ['<table ' + TABLEFORMAT +'>'];
row = 0;
htmltable += '<tr>';
for (col = 0 ;col<data[row].length; col++){
if (data[row][col] === "" || 0) {htmltable += '<td>' + 'None' + '</td>';}
else
if (row === 0) {
htmltable += '<th>' + data[row][col] + '</th>';
}
else
if (col===10){htmltable += '<td>' + data[row][col] + '</td>';}
else
{htmltable += '<td width=400px" style="width:400px; background-color:yellow;">' + data[row][col] + '</td>';}
}
htmltable += '</tr>';
row = dataRow - 1;
htmltable += '<tr>';
for (col = 0 ;col<16; col++){
if (data[row][col] === "" || 0) {htmltable += '<td>' + 'None' + '</td>';}
else {htmltable += '<td>' + data[row][col] + '</td>';}
}
htmltable += '</tr>';
htmltable += '</table>';
var dataRange = sheet.getRange(dataRow, 1, 1, 19)
var data = dataRange.getValues();
for (i in data) {
var row = data[i];
var emailAddress = row[1];
var ccAddress = row[2];
var signature = '<span style="font-family:"Arial",sans-serif">Best</span></br>Adam Schwartz </span> </br><span style="font-size:10.0pt;font-family:"Arial",sans-serif;color:#48B8DD"> <stong> MANAGER OF ESCALATIONS - RESIDENTIAL</stong></span></br><span style="font-family:"Arial",sans-serif">SMS ASSIST</span><span style="font-size:9.0pt;font-family:"Arial",sans-serif;color:#6C6C6C"> 875 N. Michigan Ave. | Suite 2800 | Chicago, IL 60611 </span>';
var message = "Hello " + row[4] + "," + '</br></br>' +"One of your escalation model tasks was randomly selected for QA last week. Your scores are below, along with my notes." + '</br></br>' + htmltable + '</br></br>' + signature; // Assemble the body text
var subject = "Preventive Escalation Model QA " + row[19];
MailApp.sendEmail(emailAddress, subject, message, {htmlBody:message,cc:ccAddress});
}
}
First, you need an onEdit trigger in order to fire the function every time column B the spreadsheet is edited. Also, because you want to send emails, a simple trigger won't be enough (see restrictions of simple triggers here), you need to install a trigger. You can do this manually or programmatically. Here I provide the code to install the edit trigger programmatically. You would have to run this function once:
function createEditTrigger() {
var ss = SpreadsheetApp.getActive();
ScriptApp.newTrigger('sendEmails')
.forSpreadsheet(ss)
.onEdit()
.create();
}
This will make sendEmails run every time the spreadsheet is edited. You would have to put a condition that checks if the edited range is in column B. And you could do that if you use an Event object, which will be received by sendEmails as a parameter and that contains information about the context that fired the trigger.
Let's say that, as is usual, the event object is called e. You can access the range that was edited by doing e.range. And you can know the column that was edited if you do e.range.getColumn(). Also, you can know which row was updated if you do e.range.getRow() (which was your second problem).
With all this said, you would have to modify the function sendEmails the following way. You would have to change this:
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var dataRow = 232; //updated row in spreadhseet
var sh = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
// Rest of the code
}
To this:
function sendEmails(e) {
var range;
if (!e) range = SpreadsheetApp.getActiveRange();
else range = e.range; // Edited range
var sh = range.getSheet(); // Edited sheet
var dataRow = range.getRow(); // Edited row index
var column = range.getColumn(); // Edited column index
var yourSheetName = "Sheet1"; // Please change accordingly
// Check that edited sheet is the one you want to track change from
// and that edited column is B (index 2):
if (sh.getName() == yourSheetName && column == 2) {
// Rest of the code
}
}
It is very important that you write e as an argument for the function, otherwise the code won't know what e is. Also please bear in mind that this will only work if the spreadsheet is edited manually by a user, not programmatically by a script).
Also, in this sample, the sheet you want to track changes from is called Sheet1, please change it in the code if that's not the case.
Finally, regarding the HTML, I think you are missing some quotes in several places, and that's why it's not working properly. In this line, for example:
'<td width=400px" style="width:400px; background-color:yellow;">'
The 400px is missing the first ", it whould be width="400px".
I see a similar thing happening in this line:
'<span style="font-family:"Arial",sans-serif">Best</span> // ...
Here, you should be using escape characters (\"), otherwise, the script thinks you want to close a quote block when you want to open a new one. You should do something like this:
'<span style="font-family:\"Arial\",sans-serif">Best</span> // ...
I hope this is of any help.
I can help with 1 and 2. 3 is an email formatting question and that's normally a pain.
There's an onEdit(e) function which passes an object to the function. e.g. when I edit cell A7 to contain just the letter a, the object (e) contains this:
{
"range": {
"columnStart": 1,
"rowStart": 7,
"rowEnd": 7,
"columnEnd": 1
},
"value": "a"
}
Within the onEdit function, you could check (range.columnStart <= 2 && range.columnEnd >= 2) for changes to column B
You may be able to use the row value from the object above. Otherwise, you can find the last row in the sheet using var lastRow = sh.getLastRow()
Say I have a dynamic table, something like this (just an example):
var table = '<table>';
for (var i=0; i<6; i++) {
table += '<tr>';
table += '<th>';
table += 'HEADER ' + i + '</th></tr>'
table += '<tr><td>one</td>';
table += '<td>two</td>';
table += '<td>three</td>';
table += '<td>four</td>';
table += '<td>five</td>';
table += '<td>six</td>';
table += '<td>seven</td>';
table += '<td>eight</td>';
table += '</tr>';
}
table += '</table>';
What I'd like to do is to take each header and its table data under the header and save each as a separate table. For example, the first table would be:
HEADER 0
1 2 3 4 5 6 7 8
The second table would be:
HEADER 1
1 2 3 4 5 6 7 8
etc...
NOTE: There's no guarantee that there's only one row under each header. Some may have multiple rows.
To get the first table I could do:
var indexval = $(table).find('tr:contains("1")').index();
var firstTable = $(table).find('tr:lt('+indexval+')');
$('#testarea').html(firstTable);
I'm aware I'm calling these "tables" and that may not be correct. But how to start at the "next" header and go the the one after that and save 'that' table? In the end I'd have a number of little tables I could print to the screen by calling their variable names.
Demo:
var table = '<table>';
for (var i = 0; i < 6; i++) {
table += '<tr>';
table += '<th>';
table += '<td>HEADER ' + i + '</td></th></tr>'
table += '<tr><td>one</td>';
table += '<td>two</td>';
table += '<td>three</td>';
table += '<td>four</td>';
table += '<td>five</td>';
table += '<td>six</td>';
table += '<td>seven</td>';
table += '<td>eight</td>';
table += '</tr>';
}
table += '</table>';
//$('#testarea').html(table);
var indexval = $(table).find('tr:contains("1")').index();
var firstTable = $(table).find('tr:lt(' + indexval + ')');
$('#testarea').html(firstTable);
td, th {
min-width: 50px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='testarea'></div>
EDIT: I ended up solving my own problem by just using a couple of arrays to store each section of the table (each header and its immediate relevant rows under it). The first for loop gets the index value of the header, and the second for loop selects out the table rows (header and associated cells under it). The "firstRow" variable selects just the first header and its rows, the 'lastRow' variable does the same with the last header and row(s). Apologies for not initially putting the question in clear terms. The question was just asking how to segment out a large table into pieces with each header and its relevant rows underneath and save them as separate variables. My thinking was this would clean up my pagination method I've currently got on my site. When a 'page up' or 'page down' is clicked, it just loads the appropriate variable in the div on the page.
var firstRow = "";
var test = [];
var indexVal = [];
for (var i=2; i<7; i++) {
indexVal[i] = $(table).find('tr:contains('+('MC' + ' ' + i)+')').index();
}
firstRow = $(table).find('tr:lt('+indexVal[2]+')');
lastRow = $(table).find('tr:gt('+((indexVal[6]) - 1)+')');
for (var j=1; j<7; j++) {
test[j] = $(table).find('tr:lt('+indexVal[j + 1]+'):gt('+((indexVal[j]) - 1)+')');
}
The only issue I had was not being able to integrate the first and last rows into the for loops. I had to make them separate hand coded variables. But it works.
JSFIDDLE
I want print a table dynamically, but my program displayed in a messy way.
I hope each row conludes two elements. I want to display the table like this. In 1s it gets a name and display it. And in next 1s it gets another name and display it. By repeating in this way, display all data.Here is my main code.
var count = 0;
function AddTd(id, showname)
{
console.log(id);
if(id == 0) // if this is in the first column
{
var str = '<tr><td width="10px">'+showname+'</td>';
$("#datashow").append(str);
count = 1; // next element should in second column
return;
}
if(id == 1) // if this is in the second column
{
var str = '<td width="10px">'+showname+'</td></tr>';
$("#datashow").append(str);
count = 0; // next element should in first column
return;
}
}
setInterval('change()',50); // In function change, print the table dynamically
This should create table with as many elements as there will be in array and do 2 columns per row.
http://jsfiddle.net/XfKME/3/
var names = ["name1", "name2", "name3", "name4"];
var tbody = "<table>";
$.each(names, function (i, item) {
if (i % 2 == 0)
tbody += "<tr>";
tbody += "<td>";
tbody += item;
tbody += "</td>"
if (i % 2 == 1)
tbody += "</tr><br />";
});
tbody += "</table>";
I am wondering how to create a function with a for loop which creates new cells / rows for the other for loop to call upon. The function should return newRow which should be a specified amount of cells. The idea is the html code displays 3 images per row, but if there is just 2 images then it only needs 2 cells. That is the first if / else statement.
Here is the code so far..
var cells = document.getElementsByTagName('td');
var cell = '<td>' + cells[0].innerHTML + '</td>';
//console.log(cell);
document.getElementById('searchBtn').onclick = search;
//specified as 3 per row
var NUMPERROW = 3;
//gets number from form text input
var num = document.getElementById("searchtxt").value;
function search(){
//var num = 4;
console.log(num);
//loop once per row
var htmlStr = '';
for (var i = 0; i < num; i = i + NUMPERROW){
//htmlStr += '<tr>' + cell + cell + cell + '</tr>;
if (num - i >= NUMPERROW) {
//displays a new row of 3
htmlStr += newRow(NUMPERROW);
}else { //less then 3 to display
htmlStr += newRow(num - i);
}
}
document.getElementById('thumbnails').innerHTML = htmlStr;
}
/*
*Returns the html for a new row.
* numToAdd: the number of cells to add for this row.
*
*/
//this function i do not know how to write
function newRow(cellsToAdd){
/////?????????? should be a for loop return new Row for the for loop above
}
}
Here is a simple function if you don't want to pass the values you can leave content out.
function newRow(numberOfCells, content)
{
var result = '<tr>';
for(var i = 0; i < numberOfCells; i++)
result += '<td>' + content[i] + '</td>';
result += '</tr>';
return result;
}