I use Apps Script to pull data from Google Spreadsheets and then Display the data on an HTML page in a table format.
I am trying to hide the data that is pulled from the spreadsheet and displayed on the table but make the last four digits of the data to be visible.
I tried the JS code below and it works fine on HTML pages but the JS code doesn't work when I tried to apply it to Apps Script probably because the HTML page has its table value typed as text in the cells while Apps Script needs to pull its table value from the spreadsheet before applying the rule from the JS code to the data to hide it and only display the last four digits of the data.
Any help to understand how to apply the script below to Apps Script to hide data but show the last four digits will be appreciated.
JS and HTML Code Below;
var id_number = document.getElementById('data2');
id_number.innerHTML = new Array(id_number.innerHTML.length-3).join('x') +
id_number.innerHTML.substr(id_number.innerHTML.length-4, 4);
console.log(id_number.innerHTML);
var phone = document.getElementById('data3');
phone.innerHTML = new Array(phone.innerHTML.length-3).join('x') +
phone.innerHTML.substr(phone.innerHTML.length-4, 4);
console.log(phone.innerHTML);
<table>
<tr>
<td width = "120">ID NUMBER</td>
<td width = "15">:</td>
<td id="data2" class="hidetext">1234567890</td>
</tr>
<tr>
<td>PHONE</td>
<td>:</td>
<td id="data3" class="hidetext">0000000000</td>
</tr>
</table>
My Code.gs Code in Apps Script Below;
function doGet(e) {
return HtmlService.createTemplateFromFile("index").evaluate()
.setTitle("HTML DATA PAGE")
.addMetaTag('viewport', 'width=device-width, initial-scale=1')
.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
};
let ss = SpreadsheetApp.getActiveSpreadsheet();
function getData(keyword){
let sheet = ss.getSheetByName('Data');
let data = sheet.getRange(1,1,sheet.getLastRow(),sheet.getLastColumn()).getDisplayValues();
let index = data.map(d => d[2]).indexOf(keyword);
console.log(data);
console.log(data.map(d => d[2]));
console.log(index);
if(index > -1){
return data[index];
}else{
return undefined;
}
}
let url = ScriptApp.getService().getUrl();
My Apps Script Table Code in Index.html
<table>
<tr>
<td width = "120">ID NUMBER</td>
<td width = "15">:</td>
<td id="data2"></td>
</tr>
<tr>
<td>PHONE</td>
<td>:</td>
<td id="data3"></td>
</tr>
</table>
I am using the following JavaScript code to populate a table. How can I pass the bgcolor value as a parameter to TD?
let template = `
<tr>
<td bgcolor="#00FF00">${"pump"+child.val().PumpID}</td>
<td bgcolor="#00FF00">${child.val().StartTime}</td>
<td bgcolor="#00FF00">${child.val().Duration}</td>
<td bgcolor="#00FF00">${child.val().GalsPumped}</td>
<td bgcolor="#00FF00">${child.val().Cycle}</td>
<td bgcolor="#00FF00">${child.val().Status}</td>
</tr>`;
table.innerHTML += template;
})
});
Basically I want to do this:
var color_variable = #ff00;
.
.
<td bgcolor=color_variable>${child.val().Status}</td>
It looks like you want to modify bgColor dynamically by altering the color_variable. If you're not using a framework (like Vue.js, React, or Angular) and if this is the behavior you want you might want to do something like that:
let themeOptions = {
color_variable: 'green'
}
function rerender() {
let template = `
<tr>
<td bgcolor="${themeOptions.color_variable}">${"pump" + child.val().PumpID}</td>
<td bgcolor="${themeOptions.color_variable}">${child.val().StartTime}</td>
<td bgcolor="${themeOptions.color_variable}">${child.val().Duration}</td>
<td bgcolor="${themeOptions.color_variable}">${child.val().GalsPumped}</td>
<td bgcolor="${themeOptions.color_variable}">${child.val().Cycle}</td>
<td bgcolor="${themeOptions.color_variable}">${child.val().Status}</td>
</tr>`;
table.innerHTML += template;
}
function changeColor(color) {
themeOptions.color_variable = color;
rerender();
}
changeColor('blue')
Of course, this is not the best code sample. You might want to modify it to suit your needs, but you get the idea. You can always use objects to pass a value by reference and modify the value later. But don't forget that you have to rerender the DOM.
I'm new to javascript, I want to place a code in my html page like the following, but I get a NaN error or no error. He just doesn't make the sums. My html page is in Turkish but I hope you will understand. Thanks in advance for your suggestions and help
in two different tables
<td id="Hizmet_Bedeli1">35</td>
<td id="Hizmet_Bedeli2">35</td>
it needs to show a total in another table
<th scope="row" class="align-middle" id="Ham_Toplam"> </th>
Here is the javascript:
{
var hb1= document.getElementById("Hizmet_Bedeli1").textContent; // If I use .value also, it doesn't work if I use .textContent as well.
var hb2= document.getElementById("Hizmet_Bedeli2").textContent; // .value de kullansam .textContent de kullansam düzelmiyor
var hizmet_toplam= parseInt(hb1) + parseInt(hb2); //parseInt de kullansam Number de kullansam Nan hatasıalıyorum... // If I use parseInt with Number, I get Nan error ...
document.getElementById("Ham_Toplam").innerHTML = hizmet_toplam;
}
I want to add the textContent of #Hizmet_Bedeli1 and #Hizmet_Bedeli2 together.
You are most probably not wrapping your tr and th tags in a table tag, which will cause your browser to not render the elements.
{
var hb1 = document.getElementById("Hizmet_Bedeli1").textContent;
var hb2 = document.getElementById("Hizmet_Bedeli2").textContent;
var hizmet_toplam = parseInt(hb1) + parseInt(hb2);
document.getElementById("Ham_Toplam").innerHTML = hizmet_toplam;
}
<table>
<tr>
<td id="Hizmet_Bedeli1">35</td>
<td id="Hizmet_Bedeli2">35</td>
<tr/>
<th scope="row" class="align-middle" id="Ham_Toplam"> </th>
</table>
I have a table in html and I want to alter the text inside different cells using js. My table looks like this:
<tr><td colspan="7" style="text-align:center;">Calendar evenimente tds</td></tr>
<tr>
<th>Data1</th>
<th>Data2</th>
<th>Data3</th>
<th>Data4</th>
<th>Data5</th>
<th>Data6</th>
<th>Data7</th>
</tr>
<tr>
<td id="col1row1">null</td>
<td id="col2row1">null</td>
<td id="col3row1">null</td>
<td id="col4row1">null</td>
<td id="col5row1">null</td>
<td id="col6row1">null</td>
<td id="col7row1">null</td>
</tr>
</table>
and my js script looks like this:
var j=0;
for(j=0;j<=7;j++)
document.getElementById("col"+j+"row1").innerHTML=j;
but I get this error:
Uncaught TypeError: Cannot set property 'innerHTML' of null
My question is whats the propper way of modifying the text inside a HTML table cell and what am I doing wrong?
The first iteration of your loop fails because there is no col0. Rather than iterate over IDs like this, you can simply loop over the elements by tag:
Array.from(document.getElementsByTagName('td')).forEach((td, index) => {
td.innerHTML = index
})
If you want the count to start at 1, use td.innerHTML = index + 1 instead.
loop are calling an ID that does not exist.make for loop starts with 1 instead of zero as there is no col0row1 in your html
var j;
for(j=1;j<=7;j++){
document.getElementById("col"+j+"row1").innerHTML=j;
}
As at j = 0 there is no element with id "col0row1" hence the uncaught error.
var j = 1
for(j=1;j<=7;j++){
document.getElementById("col" + j + "row1").innerHTML = j;
}
I have an HTML Table of Task List Data that I am trying to get all the data values and store them to an object when a row is clicked on.
I have a demo of some HTML and the JavaScript below that is all functioning just as I need it.
The problem is that I know the jQuery part is really bad quality as it calls things like this...
$taskEl.parent().parent('td').next().next().next().text()
I feel these can be improved but I am not sure how so. Most of this was already done on an existing project that I am trying to clean up and this 1 section is really bugging me.
I would appreciate any help in alternative ways to get the data please?
Or if this is the most efficient way?
Also if I need to I have access to modify some of the HTML if need to add new ID's or data attributes.
JSFiddle demo...when you click a link in the Task Title, it will print the values that it selected to the DOM for demo puirposes...: DEMO
Demo JavaScript to get Task Data from the DOM Task List and create a JS Object with it:
//Open Task Modal when a Task record is clicked in Task List
$('body').on('click', '.taskName', function() {
// Set and Cache Task ID from clicked on Task Item
var taskId = $(this).parent().parent().parent().dataAttr('task-id');
var $taskEl = $(this);
// Populate Task Data Object from DOM values
taskDataObject = {
//projectId: projectTaskModal.cache.projectId,
taskId: taskId,
taskName: $taskEl.text(),
taskDescription: $taskEl.next('.description').text(),
taskStatus: $taskEl.parent().parent('td').next().text(),
taskPriority: $taskEl.parent().parent('td').next().next().text(),
taskTags: $taskEl.parent().parent('td').next().next().next().text(),
taskCreatedDate: $taskEl.parent().parent('td').next().next().next().next().text(),
taskModifiedDate: $taskEl.parent().parent('td').next().next().next().next().next().text(),
taskDueDate: $taskEl.parent().parent('td').next().next().next().next().next().next().text(),
};
});
Demo Task List HTML
<span id="projectIdPlaceholder" data-project-id="1234"></span>
<table>
<!-- test task list record 1 -->
<tr id="task-row-1414135033730" data-task-id="1414135033730">
<td width="1%" class="task-checkbox">
<div class="status_update status-checkbox-Not-Started" data-id="1414135033730" data-status="Not Started" id="1414135033730"></div>
</td>
<td width="59%" class="task-name">
<div><span id="1414135033730-taskName" class="taskName strikethrough">Add a Plugin System similar to WordPress Action and Filter Hooks
<span class="open-description-icon open-description-icon-close" title"toggle="" description="" view"="">+</span>
</span>
<div id="1414135033730-taskDescription" class="description" style="display: block;">Project module will Fire Events before and After key events and Plugins in a custom/modulename/plugins/ folder will load and be able to Listen for these Event Hooks and then run it;s own code before and after these actions are executed!</div>
</div>
</td>
<td width="10%">
<div id="1414135033730-status" class="Not Started status"> Not Started</div>
</td>
<td width="10%">
<div id="1414135033730-taskPriority" class="priority">Low</div>
</td>
<td width="10%">
<div class="type">Other</div>
</td>
<td width="10%">
<div id="1414135033730-createdDate" class="createdDate">2014-10-24 07:18:41</div>
</td>
<td width="10%">
<div id="1414135033730-modifiedDate" class="modifiedDate">2014-10-24 07:18:41</div>
</td>
<td width="10%">
<div id="1414135033730-dueDate" class="dueDate">None</div>
</td>
</tr>
<!-- test task list record 2 -->
<tr id="task-row-1414135033731" data-task-id="1414135033731">
<td width="1%" class="task-checkbox">
<div class="status_update status-checkbox-Completed" data-id="1414135033731" data-status="Completed" id="1414135033731"></div>
</td>
<td width="59%" class="task-name">
<div>
<span id="1414135033731-taskName" class="taskName">Testing Task Record Number 2
<span class="open-description-icon open-description-icon-close" title"toggle="" description="" view"="">+</span>
</span>
<div id="1414135033731-taskDescription" class="description" style="display: block;">My project task description for demo testing task record number 2!</div>
</div>
</td>
<td width="10%">
<div id="1414135033731-status" class="Completed status">Completed</div>
</td>
<td width="10%">
<div id="1414135033731-taskPriority" class="priority">High</div>
</td>
<td width="10%">
<div class="type">Magento</div>
</td>
<td width="10%">
<div id="1414135033731-createdDate" class="createdDate">2014-10-27 03:10:14</div>
</td>
<td width="10%">
<div id="1414135033731-modifiedDate" class="modifiedDate">2014-10-27 03:22:24</div>
</td>
<td width="10%">
<div id="1414135033731-dueDate" class="dueDate">06/21/2015</div>
</td>
</tr>
</table>
Since you have Task ID available and the divs all have ID's, I would target the element ID's directly. In jQuery, the more specific you can be, the better.
$('body').on('click', '.taskName', function() {
// Get the task (row) that will be used for running all the selections
var taskid = $(this).closest("tr").dataAttr('task-id');
var taskSel = "#" + taskid + "-";
// Populate Task Data Object from DOM values
taskDataObject = {
taskId: taskid;,
taskName: $(taskSel + "taskName").text(),
taskDescription: $(taskSel + "taskDescription").text(),
taskStatus: $(taskSel + "taskStatus").text(),
taskPriority: $(taskSel + "taskPriority").text(),
taskTags: $(taskSel + "taskTags").text(),
taskCreatedDate: $(taskSel + "taskCreatedDate").text(),
taskModifiedDate: $(taskSel + "taskModifiedDate").text(),
taskDueDate: $(taskSel + "taskDueDate").text(),
};
});
Your different values are in div and span with a descriptive class name, you could just select them using find() and their className within the row that was clicked.
Something like this:
//Open Task Modal when a Task record is clicked in Task List
$('body').on('click', '.taskName', function() {
// Get the task (row) that will be used for running all the selections
$task = $(this).closest("tr");
// Populate Task Data Object from DOM values
taskDataObject = {
//projectId: projectTaskModal.cache.projectId,
taskId: $task.data('task-id'),
taskName: $task.find(".taskName").text(),
taskDescription: $task.find(".description").text(),
taskStatus: $task.find(".status").text(),
taskPriority: $task.find(".priority").text(),
taskTags: $task.find(".type").text(),
taskCreatedDate: $task.find(".createdDate").text(),
taskModifiedDate: $task.find(".modifiedDate").text(),
taskDueDate: $task.find(".dueDate").text()
};
});
Edit: To be consistent, I replaced $(this).text() with $task.find(".taskName").text(), and $(this).next(".description").text() with $task.find(".description").text(). And removed taskId and taskEl as they were redundant.
Edit2: Replaced $(this).parent().parent().parent() with $(this).closest("tr"). That way if the HTML structure changes in the future (and the number of parents change), still the task row will be selected and the code should work without issues.
Instead of manually selecting each element, I suggest you to use data-* attributes to store values and use JavaScript to dynamically build the object, for example:
HTML:
<table id="table">
<tr>
<td data-name="taskName" data-value="Test">
<div class="foo">Test</div>
</td>
<td data-name="taskDate" data-value="1439275213">
<div class="foo">2014-10-24 07:18:41</div>
</td>
</tr>
</table>
JavaScript:
var $nodes = $('#table').find('td[data-name]'); // find TDs with 'data-attr'
var attributes = {};
$nodes.each(function() { // generate object with all data-name/data-value pairs
var $node = $(this);
attributes[$node.attr('data-name')] = $node.attr('data-value');
});
console.log(attributes); // prints { taskName: "Test", taskDate: "1439275213" }
Demo: http://jsfiddle.net/andunai/uu65ntks/
P. S. This method will also allow you to display values different from their value, for example, to display human-readable date, but to serialize it as unix timestamp.
There are various options here, depends on what you need,
This example is not the fastest but is closed to best performance,
great usage of this is reloading DOM element from $ selectors, meaning that parallel events processing the DOM will render same thing,
instead of $this = $(this), reelect your dom element, again not the best practice in term of performance (search in dom), still provides the best results over dynamic modified html.
Your call:
$('body').on('click', '.taskName', function() {
var taskId = $(this).attr('id').replace('-taskName', '');
taskDataObject = {
//projectId: projectTaskModal.cache.projectId,
taskId: taskId,
taskName: $(this).text(),
taskDescription:$('[id="' + taskId + '-taskDescription"').text(),
taskStatus:$('[id="' + taskId + '-status"').text(),
taskPriority: $('[id="' + taskId + '-taskPriority"').text(),
taskTags: "undefined please defeine corect atribute on div",
taskCreatedDate: $('[id="' + taskId + '-createdDate"').text(),
taskModifiedDate: $('[id="' + taskId + '-modifiedDate"').text(),
taskDueDate: $('[id="' + taskId + '-dueDate"').text(),
};
deepTrim(taskDataObject);
printObjectToDom(taskDataObject);
});
you can write custom selector over your main parent html, similar with my example
var T_REX = $(this).parent().parent()... whatever;
var T_REX_CUBS = TREX.children();
var taskname = T_REX_CUBS[0].find("div.taskName").text();
or the simplest ones
var T_REX = $(this).closest('tr');
var taskid = T_REX.attr('data-task-id');
var taskname = T_REX.find("div.taskName").text();
Now the fastest option is to save the main parent object, over that apply jquery custom selectors, but this is not the recommend if your data from table is changing real time.