I have a table that consists of dates across the table headers and fruit down the left hand side. What i'm trying to do is get the date and the fruit eaten from a different object called 'eaten' and plot an X in the table row/column that coincides with the day it was consumed.
HTML
<table class="plan">
<thead>
<tr>
<th><strong>Food</strong></th>
<th>27/01/2017</th>
<th>28/01/2017</th>
<th>29/01/2017</th>
<th>30/01/2017</th>
<th>31/01/2017</th>
<th>01/02/2017</th>
<th>02/02/2017</th>
</tr>
</thead>
<tbody>
<tr><td>Apple</td></tr>
<tr><td>Banana</td></tr>
<tr><td>Carrot</td></tr>
<tr><td>Pear</td></tr>
</tbody>
</table>
The food titles are created via javascript from one object 'food', the dates are generated via momentJS and 'eaten' is the object data I want to plot from.
Javascript
var food = '{"food":[{"Name":"Apple"},{"Name":"Banana"},{"Name":"Carrot"},{"Name":"Pear"}]}';
$.each(JSON.parse(food), function(i, f) {
var tblRow = "";
tblRow += "<tr><td>" + f.Name + "</td></tr>";
$(tblRow).appendTo(".plan tbody");
});
for(i = 7; i > 0; i--) {
var day = moment().subtract('days', i).format('DD/MM/YYYY');
$('<th>' + day + '</th>').appendTo('.plan thead tr');
};
var eaten = '{"eaten":[{"fields":[{"value":"02/02/2017"},{"value":"Carrot"}]},{"fields":[{"value":"31/01/2017"},{"value":"Pear"}]},{"fields":[{"value":"30/01/2017"},{"value":"Banana"}]},{"fields":[{"value":"29/01/2017"},{"value":"Apple"}]},{"fields":[{"value":"27/01/2017"},{"value":"Apple"}]}]}'
What is the best way to go about plotting an X from the eaten object?
Should I get the cellIndex / rowIndex then compare the html text and plot an X?
JSFiddle
My suggestion (without changing your data schema and trying to not change much of your code logic):
parse your JSON once, for further reuse:
var eaten = JSON.parse(eatenJSON);
var food = JSON.parse(foodJSON);
populate a days array with your days.
var days = [];
for(i = 7; i > 0; i--) {
var day = moment().subtract('days', i).format('DD/MM/YYYY');
days.push(day);
}
set data-day and data-food in your td element;
for (var i=0; i<days.length; i++) {
tblRow += "<td data-day='" + days[i] + "' data-food='" + f.Name + "'></td>";
}
iterate over the eaten structure, find the elements with correspondent data-day anddata-food and, set their innerText with X, or whatever you want.
/* fill table */
eaten.eaten.forEach( function(userEaten) {
var fields = userEaten.fields;
var day = fields[0].value;
var food = fields[1].value;
document.querySelectorAll("td[data-day='" + day + "'][data-food='" + food + "']").forEach(function(td) {
td.innerText = "X";
});
});
Working fiddle: https://jsfiddle.net/mrlew/5gj4udf6/1/
EDIT: Updated the fiddle with your new JSON: https://jsfiddle.net/mrlew/5gj4udf6/2/
Just replaced this line
$.each(food, function(i, f) {
with:
food.food.forEach(function(f) {
Related
Having issues with what it might be a rather easy fix.
Context: My code is currently pulling data from Google Sheets, crafting some sort of table and sending it back to HTML where it repopulates an already existing table.
Issue: I am unable to make it so that it builds columns as well as rows. It pastes the data back all in one go (see image for context).
Files: GS & HTML. I believe the issue is on how I'm crafting the table. I know the current disposition of '' doesn't make sense, bu
HTML table with Gsheet values:
Original Gsheet table:
Google Script
function populateStratTb2(){
var tablerows = SpreadsheetApp.getActive().getSheetByName('supp_str').getRange(1, 5, 1000).getValue();
var tablevalues = SpreadsheetApp.getActive().getSheetByName('supp_str').getRange(4, 1, tablerows).getValues();
var tvlen = tablevalues.length
var active = SpreadsheetApp.getActive();
var sheet = active.getSheetByName("supp_str");
var myRange = sheet.getRange("d3:m" + tvlen);
var data = myRange.getValues();
var optionsHTML = "";
for ( var r = 0; r < 10; r+=1) {
for (var i = 0; i < data.length; i+=1) {
optionsHTML += '<tr><td>' + data[i][r] + '</td></tr>';
}};
return optionsHTML;
}
HTML Script
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>
$(function(){
google.script.run
.withSuccessHandler(displayData)
.populateStratTb2();
});
function displayData(hl){
document.getElementById('strattable').innerHTML=hl;
}
console.log('MyCode');
</script>
PS. I have spent a good couple hours scrolling though the forum picking bits and improving my original code. I am sure this question (or similar) has been answered already but I can't manage to find it.
In your script, how about the following modifications?
Modification 1:
If your for loop is used, how about the following modification?
function populateStratTb2() {
var sheet = SpreadsheetApp.getActive().getSheetByName('supp_str');
var tablerows = sheet.getRange(1, 5, 1000).getValue();
var tablevalues = sheet.getRange(4, 1, tablerows).getValues();
var tvlen = tablevalues.length
var myRange = sheet.getRange("d3:m" + tvlen);
var data = myRange.getValues();
var optionsHTML = "";
for (var r = 0; r < 10; r += 1) {
var row = "";
for (var i = 0; i < data.length; i += 1) {
row += '<td>' + data[i][r] + '</td>';
}
optionsHTML += '<tr>' + row + '</tr>';
}
optionsHTML = '<table border="1" style="border-collapse: collapse">' + optionsHTML + "</table>";
return optionsHTML;
}
I'm worried that your for loop might not be your expected result. So, I would like to proposed one more modified script as "Modification 2".
Modification 2:
If your data is converted to the HTML table, how about the following modification?
function populateStratTb2() {
var sheet = SpreadsheetApp.getActive().getSheetByName('supp_str');
var tablerows = sheet.getRange(1, 5, 1000).getValue();
var tablevalues = sheet.getRange(4, 1, tablerows).getValues();
var tvlen = tablevalues.length
var myRange = sheet.getRange("d3:m" + tvlen);
var data = myRange.getValues();
var optionsHTML = '<table border="1" style="border-collapse: collapse">' + data.reduce((s, r) => s += "<tr>" + r.map(c => `<td>${c}</td>`).join("") + "</tr>", "") + "</table>";
return optionsHTML;
}
Note:
If you don't want to add the border, please modify <table border="1" style="border-collapse: collapse"> to <table>.
From your reply, I added 2 sample scripts for the script for obtaining the same result from reduce and for loop as follows.
reduce
var optionsHTML = '<table border="1" style="border-collapse: collapse">' + data.reduce((s, r) => s += "<tr>" + r.map(c => `<td>${c}</td>`).join("") + "</tr>", "") + "</table>";
for loop
var optionsHTML = "";
for (var r = 0; r < data.length; r++) {
var row = "";
for (var c = 0; c < data[r].length; c++) {
row += '<td>' + data[r][c] + '</td>';
}
optionsHTML += '<tr>' + row + '</tr>';
}
optionsHTML = '<table border="1" style="border-collapse: collapse">' + optionsHTML + "</table>";
Reference:
reduce()
I am trying to email some details regularly and my script doesn't seem to work well. I just need the display value of A3:C7 to be sent in a click of a button but the email isn't showing exactly the way it was on my spreadsheet. I am new on Coding . Below is the code:
function sendReport (){
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var raw = sheet.getSheetByName('Raw Data');
var subType = raw.getRange('C3');
var jobType = subType.getValue();
var subID = raw.getRange('C4');
var jobID = subID.getValue();
var subBody = sheet.getSheetByName('Email Sheet');
var body1 = subBody.getRange('A3:C7');
var body = body1.getDisplayValues();
var subject = "RCA Report " + jobType + "-" + jobID
var message = "Hi TL, below is the " + subject
var closing = "For any clarifications, please do not hesitate to reach out to any of the QAs. Thanks! ";
var emailBody = message + body + closing;
MailApp.sendEmail("sample#sample.com",subject,emailBody)
};
The result looks like this:
Hi TL, below it the RCA report + jobType + "-" + jobIDCategory.Count.Judgment.16.0.27%.Did Not Load.....
So the data which looks like a table in my spreadsheet was somehow written continuously in a single line on my email.
Desired result:
Message...
Table A3:C7 (5 rows/3 columns including header)
Message...
To provide spreadsheet data in a table inside your e-mail, you can build an HTML <table> in your e-mail body, and populate data from the spreadsheet into the HTML table.
To do this, you need to iterate over the data in the selected spreadsheet range.
Currently you have this:
var body1 = subBody.getRange('A3:C7');
To iterate over this data, you can use 2 loops. The first will iterate over each row, and the second will iterate over each cell in the current row:
var dataRows = body1.getValues();
for (var i = 0; i < dataRows.length; i++) {
var dataRow = dataRows[i];
for (var j = 0; j < dataRow.length; j++) {
var cellContents = dataRow[j];
}
}
You can use these basic loops to build a string containing an HTML table:
var style = 'style="border: 1px solid black; border-collapse: collapse; padding: 5px;"';
var tableOutput = '<br><br><table ' + style + '>';
var dataRows = body1.getValues();
for (var i = 0; i < dataRows.length; i++) {
tableOutput = tableOutput + '<tr>';
var dataRow = dataRows[i];
for (var j = 0; j < dataRow.length; j++) {
var cellContents = dataRow[j];
tableOutput = tableOutput + '<td ' + style + '>' + cellContents + '</td>';
}
tableOutput = tableOutput + '</tr>';
}
tableOutput = tableOutput + '</table><br>';
Finally, because we are using HTML embedded in the body of the e-mail, we need to use the htmlBody parameter (documented here):
htmlBody: if set, devices capable of rendering HTML will use it instead of the required body argument
To do this, we need to change how we send the e-mail:
var emailBody = message + tableOutput + closing;
MailApp.sendEmail({
to: "sample#sample.com",
subject: subject,
htmlBody: emailBody
});
Here, we are explicitly using htmlBody as the body parameter, instead of the default plain string parameter.
Assuming the following input:
This will build the following e-mail body:
In my example I provided only the most basic styling to the table, to show black border lines around each cell, with some cell padding. You can obviously change that to whatever styling you wish to use.
I have multiple tables. when looping through each table.innerHtml print all tables one by one.but when convert into object it only gives one table object.
$( ".table" ).each(function( index ,e) {
let tableId = $(this).closest('table').attr('id')
var table = document.getElementById(tableId);
console.table(table.innerHTML+"tb");
let myObj = {
table: [],
add_rows: []
};
for (var i = 0; row = table.rows[i]; i++) {
let tr_obj = [];
for (var j = 0; col = row.cells[j]; j++) {
var drop_down = $("#drop\\[" + j + "\\]").val()
var text_value = $("#text\\[" + i + "\\]\\[" + j + "\\]").val();
tr_obj.push(create_object(drop_down, text_value));
}
myObj['table'].push(tr_obj);
}
console.log(JSON.stringify(myObj['table'])+"ttt")
var div="div"+tableId
var hidden="entry_field_"+tableId+""
document.getElementById(hidden).value = JSON.stringify(myObj).replace(/\\/g, "")
});
when we console table.InnerHtml it gives print both table.but MyObj gives same table object.
I've improved your fiddle and myObj is created correctly (in table property are rows from both tables). But if you want render this object in json format you have to redesign this object or render the same object in two tables. If you want render two objects with different tables prop you have to convert myObj in to separate objects. Look on my fiddle:
table.forEach((e,i)=>{
let tr_obj = [];
Array.from(e.rows).forEach((ele,ind)=>{
let cells = []
Array.from(ele.cells).forEach((element,index)=>{
let drop_down = $("#drop\\[" + i + "\\]\\[" + ind + "\\]\\[" + index + "\\]").val();
let text_value = $("#text\\[" + i + "\\]\\[" + ind + "\\]\\[" + index + "\\]").val();
cells.push(create_object(drop_down, text_value));
})
tr_obj.push(cells)
});
myObj['table'].push(tr_obj);
});
And fiddle: https://jsfiddle.net/wa3vbsc6/2/
I have this data in array:
Pune|M, Mumbai|O
and I want to show this data into html table, so for that I did this:
var arr;
arr = obj[0][2];
var j=0;
$.each(arr, function(){
var html = "<tr><td>" + arr[j] + "</td><td><span class='ui-icon ui-icon-close' onclick='remove_locations1()'></span></td></tr>";
j = j + 1;
$('#table_display_locations1').append(html);
});
obj[0][2] contain the
Pune|M, Mumbai|O
I manage to display the data like this:
Pune|M
Mumbai|O
but I want to show in first row as Pune and M in two different td's and in second row, Mumbai and O display in two different td's.
I tried split function, but it wont work for me.
can anyone please tell how I manage my string to display the result which I want?
Help?
var j=0;
$.each(arr, function(){
var split_array = arr[j].split('|');
var split_result = '';
for (var i = 0; i < split_array.length; i++) {
var split_result = split_result + '<td>'+split_array[i]+'</td>';
}
var html = "<tr>" + split_result + "<td><span class='ui-icon ui-icon-close' onclick='remove_locations1()'></span></td></tr>";
j = j + 1;
$('#table_display_locations1').append(html);
});
First use foreach in the main array, split each entries using |,
Try the below code.
var arr=["Pune|M","Mumbai|O"];
var text="";
arr.forEach(x => { text +="<tr>"; x.split('|').forEach(y => text+="<td>"+y+"<td />"); text +="</tr>";});
document.getElementsByTagName('table')[0].innerHTML=text;
console.log(text);
<table>
</table>
Please - need syntax for setting variables from jqGrid getRowData
property
Looping thru rows - just need to pull the ID and Phrase column values into variables
gridComplete: function () {
var allRowsInGrid = $('#list').jqGrid('getRowData');
for (i = 0; i < allRowsInGrid.length; i++) {
pid = allRowsInGrid[i].ID;
vPhrase = allRowsInGrid[i].Phrase;
vHref = "<a href='#' onclick='openForm(" + pid + ", " + vPhrase + ")'>View</a>";
}
},
Was able to get ID easy enough with getDataIDs :-)
Need help with getting specific column values for pid and vPhrase for i
Cheers
Try this:
var ids = jQuery("#list").jqGrid('getDataIDs');
for (var i = 0; i < ids.length; i++)
{
var rowId = ids[i];
var rowData = jQuery('#list').jqGrid ('getRowData', rowId);
console.log(rowData.Phrase);
console.log(rowId);
}
Please Note: If your goal is to add a link to cell which calls a javascript method you can achieve this by using formatter like given below, formatter should be added to colModel like you add other column properties like name,index,width,align etc, so you can avoid the iteration over row data
formatter: function(cellvalue, options, rowObject) {
return "<a href='#' onclick='openForm("
+ rowObject.ID + ", "
+ rowObject.Phrase
+ ")'>View</a>";
}
This is what I use when I want to get Data by RowID for specific Cell.
var selRow = jQuery("#list10").jqGrid('getGridParam','selarrrow'); //get selected rows
for(var i=0;i<selRow.length;i++) //iterate through array of selected rows
{
var ret = jQuery("#list10").jqGrid('getRowData',selRow[i]); //get the selected row
name = ret.NAME; //get the data from selected row by column name
add = ret.ADDRESS;
cno = ret.CONTACTNUMBER
alert(selRow[i] +' : ' + name +' : ' + add +' : ' + cno);
}