In-place replacement of HTML Elements - javascript

I have table that I generate with the following js:
var tbl = document.createElement('table');
var tbdy = document.createElement('tbody');
var thd = document.createElement('thead');
var Headings = ["Lun","File","CDROM","Removable","ReadOnly","NoFUA"];
var tr = document.createElement('tr');
for (var i = 0; i < Headings.length; i++) {
var td = document.createElement('td');
td.appendChild(document.createTextNode(Headings[i]))
tr.appendChild(td);
}
thd.appendChild(tr);
for (var lun in data) {
console.log(lun);
var tr = document.createElement('tr');
tr.appendChild(document.createElement('td').appendChild(document.createTextNode(lun)));
for (var info in data[lun]) {
var td = document.createElement('td');
td.appendChild(document.createTextNode(data[lun][info]))
tr.appendChild(td)
}
tbdy.appendChild(tr);
}
tbl.appendChild(thd);
tbl.appendChild(tbdy);
var table = document.getElementById('file-table');
and the following relevant HTML:
<table id="file-table" style="width:100%"></table>
the appendChild method you see in the last line of the js works however the intent of the creating the table in with the js is to do a complete replacement of all childNodes of 'file-table'.
I have tried iterating over the childNodes and using the removeChild method but this yields some interesting results - won't completely remove all nodes or sometimes an error message about the first parameter not being a Node.
Any ideas?

Could you select the target elements, and update them directly?
document.getElementById('td1').innerHTML = "Some text to enter"
If not, you could also replace the table body itself:
var new_tbody = document.createElement('tbody');
populate_with_new_rows(new_tbody);
old_tbody.parentNode.replaceChild(new_tbody, old_tbody)

Related

JS and DOM, trying to create table

I tried to create table but I can't create td in every tr, td is creating only in first td what is in table, how I can solve the problem?
// Creating div
var main = document.createElement("div")
main.innerHTML = ""
document.body.appendChild(main)
main.setAttribute("id", "main")
//Creating Icons
var puzzleico = document.createElement("div")
puzzleico.innerHTML = ""
document.getElementById("main").appendChild(puzzleico)
puzzleico.setAttribute("id", "puzzleico")
var puzzleico = document.getElementById("puzzleico").onclick = function() {createtable()};
//Creating tr and td
function createtable() {
//Creating Table
var table = document.createElement("table")
table.innerHTML = ""
document.body.appendChild(table)
table.setAttribute("id", "table")
for (var i = 0; i < 50; i++) {
var tr = document.createElement("tr")
tr.innerHTML = ""
document.getElementById("table").appendChild(tr)
tr.setAttribute("id", "tr")
var td = document.createElement("td")
td.innerHTML = ""
document.getElementById("tr").appendChild(td)
}
}
Element id's within a document need to be unique. The issue here is that your document.getElementById("tr") will always return the first element it finds with that id and so, all of your <td> elements will be appended to the first <tr>.
In order to fix it you can remove the tr.setAttribute("id", "tr") line and use the already existing tr variable to append the td child to.
function createtable() {
//Creating Table
var table = document.createElement("table")
table.innerHTML = ""
document.body.appendChild(table)
table.setAttribute("id", "table")
for (var i = 0; i < 50; i++) {
var tr = document.createElement("tr")
tr.innerHTML = ""
document.getElementById("table").appendChild(tr);
var td = document.createElement("td");
td.innerHTML = "test"
tr.appendChild(td)
}
}
createtable();
The above code will work, but using the already declared variables instead of finding them again can also be applied to the table case. Also, table.innerHTML = "" doesn't add any value because the innerHTML is already empty when you create a new element.
function createtable() {
//Creating Table
var table = document.createElement("table");
document.body.appendChild(table);
for (var i = 0; i < 50; i++) {
var tr = document.createElement("tr");
table.appendChild(tr);
var td = document.createElement("td");
td.innerHTML = "test";
tr.appendChild(td);
}
}
You can use this to create the table:
function createTable(){
//Creating And Appending Child
let table = document.createElement('table');
document.body.appendChild(table);
for(let i = 0; i < 50; i++){
let tr = document.createElement('tr');
let td = document.createElement('td');
td.innerHTML = i;
tr.appendChild(td);
table.appendChild(tr);
}
}
Here is the link to my codepen:
https://codepen.io/prabodhpanda/pen/gOPLqYe?editors=1010
id attribute of each element in DOM should be unique. You set same id for each tr element you create. document.getElementById element always returns the first element match by the id. This is the reason of the issue. Your last code snippet should be:
function createtable() {
//Creating Table
var table = document.createElement("table")
table.innerHTML = ""
document.body.appendChild(table)
table.setAttribute("id", "table")
for (var i = 0; i < 50; i++) {
var tr = document.createElement("tr")
tr.innerHTML = ""
document.getElementById("table").appendChild(tr)
tr.setAttribute("id", "tr" + i) // Check this
var td = document.createElement("td")
td.innerHTML = ""
document.getElementById("tr" + i).appendChild(td) // Check this
}
}
tr.appendChild(td) should also work if you don't need ID attribute.
I edited your answer and got what I want.
//Creating tr and td
function createtable() {
//Creating Table
var table = document.createElement("table")
table.innerHTML = ""
document.body.appendChild(table)
table.setAttribute("id", "table")
for (var i = 0; i < 50; i++) {
var tr = document.createElement("tr")
tr.innerHTML = ""
document.getElementById("table").appendChild(tr)
tr.setAttribute("id", "tr")
for (var v = 0; v < 50; v++) {
var td = document.createElement("td")
td.innerHTML = ""
tr.appendChild(td)
}
}
}

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

Create a bookmarklet that can retrieve all max length of text box and then print the id and max length in a table

I want to create a bookmarklet by using javascript, which can retrieve max length of all text box in the page, and then print a table below the page with all id and max length indicated.
Here is my code, however it did not print anything.
javascript: (function() {
var body =document.getElementsByTagName('body')[0];
var tbl = document.createElement('table');
var tbdy = document.createElement('tbody');
var D = document,
i, f, j, e;
for (i = 0; f = D.forms[i]; ++i)
for (j = 0; e = f[j]; ++j)
if (e.type == "text") S(e);
function S(e) {
var l= document.getElementById(e.id);
var x = document.getElementById(e.maxlength);
var tr=document.createElement('tr');
var td1=document.createElement('td');
var td2=document.createElement('td');
td1.appendChild(document.createTextNode(l));
td2.appendChild(document.createTextNode(x));
tr.appendChild(td1);
tr.appendChild(td2);
tbdy.appendChild(tr);
}
tbl.appendChild(tbdy);
body.appendChild(tbl);
})
This can actually be done much simpler than you have it.
Working jsfiddle: https://jsfiddle.net/cecu3daf/
You want to grab all of the inputs and run a loop over them. From this you can dynamically create a table and append it to the end of the document.body
var inputs = document.getElementsByTagName("input"); //get all inputs
var appTable = document.createElement("table"); //create a table
var header = appTable.createTHead(); //create the thead for appending rows
for (var i=0; i<inputs.length; i++) { //run a loop over the input elements
var row = header.insertRow(0); //insert a row to the table
var cell = row.insertCell(0); //insert a cell into the row
cell.innerHTML = inputs[i].maxLength; //input data into the cell
var cell = row.insertCell(0);
cell.innerHTML = inputs[i].id;
}
document.body.appendChild(appTable); //append the table to the document
To make it a bookmark, simply place the javascript: before hand. There is no need to encase it in a function. You can if you'd like to.

Creating dynamically large table using JavaScript

I'm trying to create dynamically a table using JavaScript.
Here is the code I'm using (or here http://liveweave.com/mqG5iT):
function Process(){
CreatTable(['First Name', 'Last Name', 'Email']);
}
function CreatTable(data) {
var checkbox;
var table;
var thead;
var tr;
var th;
var tbody;
tablearea = document.getElementById('ShowDataID');
table = document.createElement('table');
table.id = "ContactsTable";
thead = document.createElement('thead');
tr = document.createElement('tr');
tbody = document.createElement('tbody');
//create columns input checkbox column
checkbox = CreateHTMLElement("chkBoxAllEmails", "chkBoxAllEmails", "SelectAllEmails()", "checkbox", "false");
th = document.createElement('th');
th.appendChild(checkbox);
tr.appendChild(th);
thead.appendChild(tr);
//create columns FirstName,LastName,Emails
for (var i = 0; i < data.length; i++) {
var headerTxt = document.createTextNode(data[i]);
th = document.createElement('th');
th.appendChild(headerTxt);
tr.appendChild(th);
thead.appendChild(tr);
}
table.appendChild(thead);
//create rows and addind to table
for (var i = 0; i < 2000; i++) {
tr = document.createElement('tr');
checkbox = CreateHTMLElement("11", "11", "11", "checkbox", "11");
tr.appendChild(document.createElement('td'));
tr.appendChild(document.createElement('td'));
tr.appendChild(document.createElement('td'));
tr.appendChild(document.createElement('td'));
tr.cells[0].appendChild(checkbox); tr.cells[1].appendChild(document.createTextNode('John'+i.toString()));
tr.cells[2].appendChild(document.createTextNode('McDowell'));
tr.cells[3].appendChild(document.createTextNode('ddd#gmail.com'));
tbody.appendChild(tr);
table.appendChild(tbody);
}
document.getElementById("TablePagingArea").appendChild(table);
//return table;
}
function CreateHTMLElement(id, name, onclick, type, value) {
var HTMLElement = document.createElement('input');
HTMLElement.id = id;
HTMLElement.name = name;
HTMLElement.onclick = onclick;
HTMLElement.type = type;
HTMLElement.value = value;
return HTMLElement;
}
With a small set of data 1000-3000 rows it works relatively well but, some of the data set contains upwards of 5000 rows which causes Firefox to crash and close or become unresponsive.
My question is: is there a better way to accomplish what I am trying to do?
Most efficient way to create a bunch of elements is to create a string and create element from this string.
Most efficient way to create a string of element is to join from array
So you should refactor your code to
Create an array of elements like a[i] = "<tr><intput type='checkbox'></tr>";
Join an array to get one string var s = a.join();
Create DOM elements like var div = document.createElement('div'); div.innerHTML = s;

JavaScript/DOM - Give a newly created element an ID

How can I apply an element ID to a newly created element through JavaScript DOM?
The code I have written creates a table which is triggered from a button.
I need to apply a unique ID to this table so it can be styled differently to others which appear on my site.
Here is a sample of my code:
var tab = document.createElement("ViewShoppingCart");
document.getElementById("shopping_list").appendChild(tab);
var tbdy = document.createElement("tbody");
tab.id = "new_cart";
tab.appendChild(tbdy);
new_cart = true;
var total = 0;
for (var a = 0; a <= nameArray.length-1; a++) {
var tr = document.createElement("tr");
tbdy.appendChild(tr);
var td = document.createElement("td");
td.appendChild(document.createTextNode("x " + quantityArray[a]));
tr.appendChild(td);
var td2 = document.createElement("td");
td2.appendChild(document.createTextNode(nameArray[a]));
tr.appendChild(td2);
var td3 = document.createElement("td");
td3.appendChild(document.createTextNode(sumArray[a]));
tr.appendChild(td3);
}
Try
var tbdy = document.createElement("tbody");
tbdy.id = "newtbodyid";
tab.id = "new_cart";
tab.appendChild(tbdy);
new_cart = true;
For applying styles consider using class selectors, you may not need IDs at all.
Note that if you want to create valid HTML you can't have duplicated IDs that significantly lessens value for CSS styles, especially for table data.

Categories

Resources