Copy row from any table - javascript

I have an HTML page with 3 tables on it. I want to be able to copy specific cells in a table row to the clipboard. The row could come from any of the 3 tables.
Using the code below, I highlight and copy the row for a table with an ID of "final". How do I make this work for any of the 3 tables? I tried by getElementsByTagName and labeling them the same name but did not work - understandably so. Is there a way to designate the selected table? I am trying to avoid copying the whole row and might eventually add the formatted msg to a new page rather than copy to the clipboard.
function copy_highlight_row() {
var table = document.getElementById('final');
var cells = table.getElementsByTagName('td');
for (var i = 0; i < cells.length; i++) {
// Take each cell
var cell = cells[i];
// do something on onclick event for cell
cell.onclick = function () {
// Get the row id where the cell exists
var rowId = this.parentNode.rowIndex;
var rowsNotSelected = table.getElementsByTagName('tr');
for (var row = 0; row < rowsNotSelected.length; row++) {
rowsNotSelected[row].style.backgroundColor = "";
rowsNotSelected[row].classList.remove('selected');
}
var rowSelected = table.getElementsByTagName('tr')[rowId];
rowSelected.style.backgroundColor = "yellow";
rowSelected.className += " selected";
var cellId = this.cellIndex + 1
msg = 'Title: ' + rowSelected.cells[0].innerHTML;
msg += '\r\nDescription: ' + rowSelected.cells[1].innerHTML;
msg += '\n\nLink: ' + rowSelected.cells[2].innerHTML;
msg += '\nPublication Date: ' + rowSelected.cells[3].innerHTML;
//msg += '\nThe cell value is: ' + this.innerHTML copies cell selected
navigator.clipboard.writeText(msg);
}
}
};

Based on a couple of the suggestions I came up with the following:
function highlight_row() {
var cells = document.querySelectorAll('td')
for (var i = 0; i < cells.length; i++) {
// Take each cell
var cell = cells[i];
// do something on onclick event for cell
cell.onclick = function () {
// Get the row id where the cell exists
var rowId = this.parentNode.rowIndex;
var t_ID = this.closest('table').id
var table=document.getElementById(t_ID);
var rowsNotSelected = table.getElementsByTagName('tr');
for (var row = 0; row < rowsNotSelected.length; row++) {
rowsNotSelected[row].style.backgroundColor = "";
rowsNotSelected[row].classList.remove('selected');
}
var rowSelected = table.getElementsByTagName('tr')[rowId];
rowSelected.style.backgroundColor = "yellow";
rowSelected.className += " selected";
var cellId = this.cellIndex + 1
msg = 'Title: ' + rowSelected.cells[0].innerHTML;
msg += '\r\nDescription: ' + rowSelected.cells[1].innerHTML;
msg += '\n\nLink: ' + rowSelected.cells[2].innerHTML;
msg += '\nPublication Date: ' + rowSelected.cells[3].innerHTML;
navigator.clipboard.writeText(msg);
}
}
}
At the end of the html I call the function. The HTML contains 3 tables and this enabled me to click on any table, highlight the row, and copy the correct range of cells.

Related

Populating HTML table with Google Sheet data (rows & columns)

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()

Code to delete rows for a table not working Javascript / HTML

I have a problem with the following code. I am trying remove rows from a table if that row does not contain the meat in the td. To clarify, when the function is called, it takes in 2. (Which is where the word meat can be found in the table)
Some of the rows do not contain the word meat, x = rows[i].getElementsByTagName("td")[a]; The word meat can be found in [a] of the row. I think the problem is with x.innerHTML, as I don't think it returns a value to compare to b.
Any help or leads are appreciated. Right now when the button is clicked to call the function, nothing happens.
function clearTable(a) {
var table, rows, switching, i, x, c, shouldSwitch;
table = document.getElementById("Invtable");
switching = true;
var b = "meat";
while (switching){
switching = false;
rows = table.getElementsByTagName("tr");
for (i = 0; i < (rows.length); i++) {
shouldSwitch = false;
x = rows[i].getElementsByTagName("td")[a];
if(x.innerHTML.toLowerCase() != b){
shouldSwitch= true;
break;
}
}
if (shouldSwitch) {
table.deleteRow(i);
switching = true;
}
}
}
var table = "<tr>";
for (var i = 0; i < array.length; i++) {
table += "<tr>";
for (var j = 0; j < array[i].length; j++) {
if (j == 6) {
table += "<td> <img src='CSV_Photos/" + array[i][j] + "' style ='width:250px;height:250px'>" + "<br>" //every 6th column is a picture
+ "<center> " + '<button id="btn" onClick="clickMe(\''+ array[i][1] + ',' + array[i][5] + '\')"> Buy / Add To Cart </button> </td>' + "</center>"; //button onclick takes (name+price)
} else {
table += "<td>" + array[i][j] + "</td>";
}
}
table += "</tr>";
}
Edit: Starting from the var table, that's how the table was made in javascript in a function.
The table code in html looks like this :
<tr><td>1000</td><td>Chicken</td><td>Meat</td><td>Perfect</td><td>Yes</td><td>$2.99</td><td>image</td> </tr>
The problem is you are passing the incorrect column number as the argument. You only have two td per row and the index starts at 0. So you have to pass 1 as your argument: clearTable(1).
I created a simple table so you can see your function works with the correct argument.
EDIT
I recreated my table to have 6 columns and I created a button that runs the function onClick.
var table = '<table id="Invtable"><tr><td>Food</td><td>chicken</td><td>Veggies</td><td>Ceral</td><td>Soda</td><td>Water</td></tr><tr><td>Food</td><td>water</td><td>Soda</td><td>Meat</td><td>Water</td><td>Ceral</td></tr><tr><td>Third-Food</td><td>Meat</td><td>Chicken</td><td>Ceral</td><td>Water</td><td>Soda</td></tr></table>';
var btn = '<button onClick="clearTable(1)">Meat</button>';
document.body.innerHTML = table + btn;
//clearTable(1);
function clearTable(a) {
var table, rows, switching, i, x, c, shouldSwitch;
table = document.getElementById("Invtable");
switching = true;
var b = "meat";
while (switching){
switching = false;
rows = table.getElementsByTagName("tr");
console.log(rows);
for (i = 0; i < (rows.length); i++) {
shouldSwitch = false;
x = rows[i].getElementsByTagName("td")[a];
if(x.innerHTML.toLowerCase() != b){
shouldSwitch= true;
break;
}
}
if (shouldSwitch) {
table.deleteRow(i);
switching = true;
}
}
}

javascript get element in table untill a class happen

I have a huge table which most of the entries are "display:none". When the user click on an entity the rows should appear until the same class happen.
The table looks something like this:
<tbody>
<tr id="1" class="department"></tr>
<tr style="display:none;" id="43" class="sub"></tr>
<tr style="display:none;" id="55" class="sub"></tr>
<tr style="display:none;" id="85" class="sub"></tr>
<tr id="6" class="department"></tr>
<tr style="display:none;" id="150" class="sub"></tr>
</tbody>
So by clicking on id = 1 row the table should expand to show id= 43,55,85 (until reach to class="department" again)
I know it's a bit confusing so feel free to ask me questions if you need more explanation.
In plain javascript, you can do something like this:
function hasClass(elem, cls) {
var str = " " + elem.className + " ";
var testCls = " " + cls + " ";
return(str.indexOf(testCls) != -1) ;
}
var table = document.getElementById("myTable");
var rows = table.getElementsByTagName("tr");
for (var i = 0; i < rows.length; i++) {
(function(index) {
rows[index].addEventListener("click", function(e) {
for (var i = index + 1; i < rows.length; i++) {
var row = rows[i];
if (hasClass(row, "department")) {
break;
}
row.style.display = "";
}
});
})(i);
}
Working demo: http://jsfiddle.net/jfriend00/Dh3p3/
The code uses a closure to capture the row index for each row, such that when it is clicked on, you can use that index into the previously captured array of rows. It then walks down that array showing rows until it finds an item that has the "department" class.
FYI, this puts event listeners on all the rows so if you manually show one of the hidden rows, it can be clicked on and have the same behavior. If you only want click handlers on the class="department" rows, the code can easily be modified to do that too.
Here's a version that works with a hierarchy of classes. It expands only items at the next level on a click:
function hasClass(elem, cls) {
var str = " " + elem.className + " ";
var testCls = " " + cls + " ";
return(str.indexOf(testCls) != -1) ;
}
var table = document.getElementById("myTable");
var rows = table.getElementsByTagName("tr");
for (var i = 0; i < rows.length; i++) {
(function(index) {
rows[index].addEventListener("click", function(e) {
// nothing to do if clicking on the last item
if (index + 1 >= rows.length) {
return;
}
// get class name to stop on
var clsToStopOn = this.className;
// get class name to show
var clsToShow = rows[index + 1].className;
for (var i = index + 1; i < rows.length; i++) {
var row = rows[i];
if (hasClass(row, clsToStopOn)) {
break;
}
if (hasClass(row, clsToShow)) {
row.style.display = "";
}
}
});
})(i);
}
Working multi-level demo: http://jsfiddle.net/jfriend00/9HgPt/

How to get row and column values, of a table, on click by a event listener

I have two dynamic tables, one with the results of a sum and on other with the sum value, example: 4 and 2+2.
I have the following code in javascript where I click on the table with sum value, and then click on the respective sum value, and when I click on the right sum value, I want to know the value of the index on the column and row of the cell that was clicked.
I have eventListeners to create the clickable cells, and then compare with the cells of the other table.
Here is the code for the clickable cell of the first table:
var handler = function(e){if (choiceFlagElement != null) {
choiceFlagElement.style.background = 'green';
}
choiceFlagElement = e.target;
choiceFlagNumber = parseInt(e.target.innerHTML);
e.target.style.background = 'green';
}
and then I have this part for compare to the above cell:
var handler2 = function(e){
if (choiceFlagElement == null) {
return;
}
if (choiceFlagNumber == eval(e.target.innerHTML)) {
e.target.style.background = 'green';
e.target.style.visibility= 'hidden';
choiceFlagElement.style.visibility = 'hidden';
pontuacao();
inicio=Date.now();
count++;
choiceFlagNumber.target.innerHTML="-1";
}
}
Here is where I create the two table:
function criartabela(tamanho){
var tbl = "<table id=tabela>";
var tbl2 = "";
var resultados = new Array();
var f=0;
for (var ri = 0; ri < tamanho ; ri++) {
tbl += "<tr>";
for (var ci = 0; ci < tamanho; ci++) {
contas();
tbl += "<td class='cel"+tamanho+"' id=x visibility=visible >" + a + "+" + b + "</td>";
var total = a+b;
resultados[f]=total;
f=f+1;
}
}
resultados.sort(function(a,b){return a - b});
for(y=0; y<resultados.length; y++){
tbl2 += "<div class='resul"+tamanho+"' id=total >"+ resultados[y] + "</div>";
}
tbl += "</tr>";
tbl += "</table>";
document.getElementById("tabelap").innerHTML = tbl;
document.getElementById("resposta").innerHTML = tbl2;
}

dynamically creating a table and adding cells to the table through a function with Javascript

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;
}

Categories