// needs to be tr not a classname of .tr
const tableRow = document.querySelectorAll('.tr');
const firstNewCell = document.createElement('td');
tableRow.forEach((element) => {
// needs to be "afterbegin", so that it is just inside the beginning of the table row element
// you are also using the same firstNewCell element each time so rather than it being
// duplicated it will be moved from one table row to the next.
// you need to create a table cell element inside this function
element.insertAdjacentElement("beforebegin", firstNewCell)
});
// this should be inside the forEach callback function
firstNewCell.style.display = "table-cell";
firstNewCell.style.width = "500px";
firstNewCell.style.backgroundColor = "yellow";
firstNewCell.innerHTML = "A";
Another issue is that you’re adding the same cell element to each row, thus removing it from each previous row (an element can only have a single parent), and ending up with the new cell only being added to the last row. You’d have to create a new cell inside the forEach() callback for this to work.
BTW you might also have a look at the insertCell() method, which makes things a bit less verbose:
const tableRows = document.querySelectorAll('tr')
tableRows.forEach(row => {
const newCell = row.insertCell(0)
// Set style and text content here
})
I would like to thank all commenters for their remarks.
Finally I came up with the following working tested code which you can test in any owned Drupal website at:
example.com/admin/structure/types
Code
const allTableRowsExceptTableHeading = document.querySelectorAll('tr.odd, tr.even');
allTableRowsExceptTableHeading.forEach((element) => {
const newCell = document.createElement('td');
// This variable must be here inside the function because...
// For each table row we work on, we create and add a table cell...
element.insertAdjacentElement('afterbegin', newCell);
newCell.innerHTML = '<span class="numberCell">A</span>';
newCell.style.display = 'table-cell';
newCell.style.width = 'maxContent';
newCell.style.textAlign = 'center';
newCell.style.backgroundColor = 'yellow';
// These HTML-CSS directives must be here inside the function because...
// For each table row we work on, we create and add these new HTML-CSS directives...
});
let baseNumber = 1;
document.querySelectorAll('.numberCell').forEach((element)=>{
element.innerHTML = `<span>${baseNumber++}</span>`;
});
I needed 'tr.odd, tr.even' to select all tr elements which are not the first tr which is a table heading because regular negation as with 'tr:not(:first-child)' didn’t work for some reason possibly related to Drupal’s HTML-CSS behavior.
As can be figured from the code, the last part makes the new column and all its cells to include one-base-indexed incremented numbers, as a way to directly output a count of all existing rows.
But,
There might be a better way to do it.
Well that’s probably because the header row is correctly wrapped in a thead with only that single child row. Maybe try tbody > tr as a selector instead, so you don’t have to rely on class names related to styling.
You might do this directly inside the forEach() callback, which receives the current index as the second parameter: