How to get innerHTML of td in dynamically populated table in JavaScript - javascript

I created a table and populated values from an array, so I have 5x5 table, where each td will be filled with a word. The word come from array memo and all the code below works fine.
var myTableDiv = document.getElementById("results")
var table = document.createElement('TABLE')
var tableBody = document.createElement('TBODY')
table.border = '1'
table.appendChild(tableBody);
//TABLE ROWS
for (i = 0; i < this.memo.length; i++) {
var tr = document.createElement('TR');
for (j = 0; j < this.memo[i].length; j++) {
var td = document.createElement('TD');
td.onclick = function () {
check();
}
td.appendChild(document.createTextNode(this.memo[i][j]));
tr.appendChild(td)
}
tableBody.appendChild(tr);
}
myTableDiv.appendChild(table);
I have one question : I would like to click on the cell and get the word, which belongs to the cell.
For this purpose I tried onclick as I created td element
td.onclick = function () {
check();
}
The function check should print the innerHTML of the cell, which was clicked
function check() {
var a = td.innerHTML;
console.log(a);
}
But it gives me always wrong text - the last one in the array, which was populated.
How could I solve it?..

You always get the last td in the array because the last value that was set to td was of the last cell. You need to add the a parameter, say event, to onclick's callback function, and then your clicked element will be referenced in event.target. Then you would be able to get it's innerHTML.

Here's why it's always giving you the first element: after the for (j = 0; ... loop is finished, the variable td will hold the value of the last element in the list. Then, when check is called, it accesses that same td variable pointing to the last element.
To solve this, you can add an argument to the function to accept a specific element and log that.
td.onclick = function () {
check(td);
};
// later...
function check(element) {
var html = element.innerHTML;
console.log(html);
}

I would pass the innerHTML in the click itself - please see working example below, with some mock data for memo.
var myTableDiv = document.getElementById("results")
var table = document.createElement('TABLE')
var tableBody = document.createElement('TBODY')
var memo = [
['joe', 'tom', 'pete'],
['sara','lily', 'julia'],
['cody','timmy', 'john']
]
table.border = '1'
table.appendChild(tableBody);
//TABLE ROWS
for (i = 0; i < this.memo.length; i++) {
var tr = document.createElement('TR');
for (j = 0; j < this.memo[i].length; j++) {
var td = document.createElement('TD');
td.onclick = function () {
check(this.innerHTML);
}
td.appendChild(document.createTextNode(this.memo[i][j]));
tr.appendChild(td)
}
tableBody.appendChild(tr);
}
myTableDiv.appendChild(table);
function check(a) {
console.log(a);
}
<div id="results">
</div>

you can try..
td.onclick = function () {
check();
}
to
td.onclick = function (evt) {
var html = evt.target.innerHTML;
console.log(html);
check(html); //to do something..
}

Related

Using Javascript to embed an onClick event to an HTML div

I'm trying to make an interactable and configurable grid using divs as their cells.
To first give a bit of context on this part of the code, I'm basically just repeating td's in HTML output then appending a specific amount of divs into the td's/rows (cellID is just a method for decorating the div names);
var table, row, div;
table = document.createElement('table');
for (var i=0; i < rows; i++)
{
row = document.createElement('td');
row.id = "row-" + i;
for (var j=0; j < cols; j++)
{
div = document.createElement('div');
div.id = cellID(i, j);
row.append(div);
}
table.append(row);
}
Let's say that:
-rows = 4 and -cols = 2 | The output result on the user's end would be this :
Now my current problem that I'm trying to figure out is how to make every repeated div be given the onClick() event so that an event occurs when you click on the boxes, here is what I tried to make this work :
div.addEventListener("click", null); //This part didn't work for me, though to be honest, I don't really know what to replace the null with
div.getElementById(div.id).onclick = function() { OnClick() }; (OnClick is a test method to see if it works, however this one just rejects an error, saying that "div.getElementById" is not a function, so I don't know what's up with that.)
These things I tried were all things that had been recommended throughout, but I don't know what else could make it work.
What do you think the problem may be there?
-
div.addEventListener() should work.
But you need to create valid DOM structure. Rows are tr, cells are td. You can put the div in the td, or just use the td directly.
let rows = 2,
cols = 4;
var table, row, div;
table = document.createElement('table');
for (var i = 0; i < rows; i++) {
row = document.createElement('tr');
row.id = "row-" + i;
for (var j = 0; j < cols; j++) {
let cell = document.createElement("td");
div = document.createElement('div');
div.id = cellID(i, j);
div.addEventListener("click", function() {
console.log('Clicked on', this.id);
});
div.innerText = div.id;
cell.append(div);
row.append(cell);
}
table.append(row);
}
document.body.appendChild(table);
function cellID(i, j) {
return `cell-${i}-${j}`;
}

How can I convert this innerhtml loop to a innertext one because XSS vulnerabilities?

I need to convert this loop to innertext with the dynamically added content how can I do that I looked on the internet but could'nt find anything?
function showMessages(messages) {
jsonMessages.innerHTML = "<tr><th>Naam</th><th>Bericht</th><th>Datum</th></tr>";
messages.sort(function (a, b) {
return a.created_at > b.created_at ? 1 : -1;
});
for (var i = 0; i < messages.length; i++) {
jsonMessages.innerHTML += `<tr><td>${messages[i].user_id}</td><td>${messages[i].content.replace(/</g,"<")}</td><td>${messages[i].created_at}</td></tr>`;
}
console.log(messages);
}
To change your code to prevent xss by using innerText instead of arbitrarily setting innerHTML to some unknown code you will need to create elements themselves first then set their content
For instance
//create a tr element
tr = document.createElement('tr');
//create new cell for above tr
td = tr.insertCell();
td.innerText = messages[i].user_id;
You would do this for the all elements that would have dynamic content. So in your case you could do the following
for (var i = 0; i < messages.length; i++) {
let tr = document.createElement('tr');
let userIdCell = tr.insertCell();
let contentCell = tr.insertCell();
let dateCell = tr.insertCell();
userIdCell.innerText = messages[i].user_id;
contentCell = messages[i].content;
dateCell = messages[i].created_at;
//finally add it to your table
jsonMessages.appendChild(tr);
}
There are other routes that do the same thing, like putting a blank string of your html structure into an element then select the elements and set them:
let tr = document.createElement('tr');
tr.innerHTML = `<tr><td></td><td></td><td></td></tr>`;
//first td child
tr.children[0] = messages[i].user_id;
//second td child
tr.children[1] = messages[i].content;
//third td child
tr.children[2] = messages[i].created_id;
It all just depends on your personal preference. The main point is to just create the elements first then set their innerText property instead of setting the whole html as one.
function showMessages(messages) {
jsonMessages.innerHTML = "<tr><th>Naam</th><th>Bericht</th><th>Datum</th></tr>";
messages.sort(function (a, b) {
return a.created_at > b.created_at ? 1 : -1;
});
for (var i = 0; i < messages.length; i++) {
var mainTr = document.createElement('tr');
var td1 = document.createElement('td').appendChild(document.createTextNode(messages[i].user_id));
var td2 = document.createElement('td').appendChild(document.createTextNode(messages[i].content.replace(/</g,"<")));;
var td3 = document.createElement('td').appendChild(document.createTextNode(messages[i].created_at));
mainTr.appendChild(td1);
mainTr.appendChild(td2);
mainTr.appendChild(td3);
jsonMessages.appendChild(mainTr);
}
console.log(messages);
}

how to set onclick attribute in a loop

I am building a table with text in the first column and buttons that do stuff in the second column. Here is the complete .js file:
var table = document.createElement("table");
var tableBody = document.createElement("tbody");
for(i = 0; i < array.length; i++) {
var row = table.insertRow(i);
var cell = row.insertCell(0);
cell.innerHTML = text[i];
var cell = row.insertCell(1);
var cellElement = document.createElement("input");
cellElement.setAttribute("id", ID[i]);
cellElement.setAttribute("type", "button");
cellElement.setAttribute("value", "button");
/////cellElement.onclick =
/////function(){ doThisThing(i,ID[i]); } );
cell.appendChild(cellElement);
row.appendChild(cell);
}
table.appendChild(tableBody);
document.body.appendChild(table);
Everything works except for the cellEllement.onclick = function(){}; The onlick() function does not set. I have tried variations on this:
cellElement.setAttribute("onclick",doThisThing(i,ID[i]));
How to I set the button onclick attribute when looping through to create a table?
You're using a reference to the i variable inside your function which will continue to change with the loop, and won't hold the value of i that it has when you go through that iteration of the loop. You need to hold on to the current value of i, probably by wrapping your callback in another function:
cellElement.onclick = (function(currI) {
return function() { doThisThing(currI, ID[currI]); };
})(i);
You could also use bind to make things simpler:
cellElement.onclick = doThisThing.bind(null, i, ID[i]);

Delete the row you click on (Javascript dynamic table)

I want to delete a row from a table, I am using Javascript.
I am dynamically creating table rows and in the last cell I have delete button so how to make it delete the row?
var newData4 = document.createElement('td');
var delButton = document.createElement('input');
delButton.setAttribute('type', 'button');
delButton.setAttribute('name', 'deleteButton');
delButton.setAttribute('value', 'Delete');
newData4.appendChild(delButton);
newRow.appendChild(newData4);
this is the function for creating my table rows
function addItem()
{
document.getElementById('add').onclick=function()
{
var myTable = document.getElementById('tbody');
var newRow = document.createElement('tr');
//var element1 = document.createElement("input");
//element1.type = "checkbox";
//newRow.appendChild(element1);
var newData1 = document.createElement('td');
newData1.innerHTML = document.getElementById('desc').value;
var newData2 = document.createElement('td');
newData2.innerHTML = document.getElementById('taskPriority').value;
var newData3 = document.createElement('td');
newData3.innerHTML = document.getElementById('taskDue').value;
myTable.appendChild(newRow);
newRow.appendChild(newData1);
newRow.appendChild(newData2);
newRow.appendChild(newData3);
var newData4 = document.createElement('td');
var delButton = document.createElement('input');
delButton.setAttribute('type', 'button');
delButton.setAttribute('name', 'deleteButton');
delButton.setAttribute('value', 'Delete');
newData4.appendChild(delButton);
newRow.appendChild(newData4);
}
}
function SomeDeleteRowFunction(btndel) {
if (typeof(btndel) == "object") {
$(btndel).closest("tr").remove();
} else {
return false;
}
}
try this code here is fiddle
alternatively try
//delete the table row
$(document).on('click', '#del', function(){
$(this).parents('tr').remove();
});
}); //del is the id of the delete block
one pure javascript approach
function deleteRowUI(btndel) {
var table=document.getElementById('filterTableBody');
if (typeof(btndel) == "object") {
p=btndel.parentNode.parentNode;
p.parentNode.removeChild(p);
var oTable = document.getElementById('filterTableBody');
//gets rows of table
var rowLength = oTable.rows.length;
for (var i = 1; i < rowLength; i++){
var oCells = oTable.rows.item(i).cells;
//gets cells of current row
var cellLength = oCells.length-1;
for(var j = 0; j < cellLength; j++){
oCells.item(j).innerHTML = "";
break;
}
break;
}
} else {
return false;
}
}
if you want to temporary hidden it you can do:
this.parentNode.style.display='none';
in mind that the exclusion button is in a td.
But if you want to really delete it from the html and the database:
you need to make the same as above and a extra call to a function of php/plsqlwathever to delete from de db, i recommend using ajax to call it.
http://www.w3schools.com/ajax/default.asp
uses jQuery remove method to do it.
By the id attribute :
$("#id here").remove();
By the class attribute :
$(".class name here").remove();
I hope I've helped a little...

Storing the index of a for loop in javascript

I'm developing an android app with phonegap. I'm making an HTML table with some that with a for loop from localStorage. I need, for each row, to store the index i of the for to use it for retrieving an item from localStorage that has the name like the index. I have some code but the variable that i defined for that effect gets overwritten by the loop (of course). Here's the code:
<script language="javascript">
if(len != 0) {
var table = document.getElementById('hor-minimalist-b'); // get the table element
var tableBody = table.childNodes[1]; // get the table body
var tableHead = table.childNodes[0]; // get the table head
var thead = document.createElement('th');
var row2 = document.createElement('tr'); // create a new row
var headText = document.createTextNode('Dados');
thead.scope = "col";
thead.appendChild(headText);
row2.appendChild(thead);
tableHead.appendChild(row2);
for (var i=0; i<len; i++) {
var row = document.createElement('tr'); // create a new row
var cell = document.createElement('td'); // create a new cell
var a = document.createElement('a');
var cellText = document.createTextNode(localStorage.getItem('key' + i));
var xyz = "key" + i;
a.href = "alterar.html";
a.onclick = function() { doLocalStorage(xyz) };
a.appendChild(cellText);
cell.appendChild(a); // append input to the new cell
row.appendChild(cell); // append the new cell to the new row
tableBody.appendChild(row); // append the row to table body
}}
</script>
</table>
Maybe i'm not explaining myself too well. If you need any more info please ask. Thanks in advance. Eva
try to put the key name in to a closure:
function wrapper(i) {
return function() {
doLocalStorage("key" + i)
}}
a.onclick = wrapper(i);
Not sure if I got your question right, but if you want to bind usage of a variable asynchronously when doing for loop then you should wrap it in a closure:
for(i = 1, c = arr.length; i < c; i++){
(function(i){
// i wont change inside this closure so bound events will retain i
$('#id'+i).click(function(){
alert(i); // Will alert the corresponding i
})
})(i);
}

Categories

Resources