Drawing a table with vanilla JS and loops - javascript

I am doing an exercise (from Beginning Javascript) to better understand DOM manipulation. Attempting to recreate the following table in a DRY method using only JS (the textbook solution is here):
<table>
<tr>
<td>Car</td>
<td>Top Speed</td>
<td>Price</td>
</tr>
<tr>
<td>Chevrolet</td>
<td>120mph</td>
<td>$10,000</td>
</tr>
<tr>
<td>Pontiac</td>
<td>140mph</td>
<td>$20,000</td>
</tr>
</table>
I tried this but unsure how you can loop variable creation without throwing an error:
var array = [['Car', 'Top Speed', 'Price'],['Chevrolet', '120mph', '$10,000'], ['Pontiac', '140pmh', '$20,000']] // Creating a data array which a loop will source from
var table = document.createElement('table');
document.body.appendChild(table); // Drew the main table node on the document
for (var i = 0; i<3; i++) {
var tr[i] = document.createElement('tr'); //Create 3 <tr> elements assigned to a unique variable BUT need a working alternative for 'tr[i]'
table.appendChild(tr[i]); // Append to <table> node
for (var j = 0; j<3; j++) {
var tdText = document.createTextNode(array[i][j]); // Extract data from array to a placeholder variable
tr[i].appendChild(tdText); // Take string from placeholder variable and append it to <tr> node
}
}

As already said the problem is the syntax error in declaring the tr[i] variable.
A more cleaner way will be is to use the table api methods like
var array = [
['Car', 'Top Speed', 'Price'],
['Chevrolet', '120mph', '$10,000'],
['Pontiac', '140pmh', '$20,000']
] // Creating a data array which a loop will source from
var table = document.createElement('table');
document.body.appendChild(table); // Drew the main table node on the document
array.forEach(function(row) {
var tr = table.insertRow(); //Create a new row
row.forEach(function(column) {
var td = tr.insertCell();
td.innerText = column; // Take string from placeholder variable and append it to <tr> node
});
});
HTMLTableElement
insertRow()
insertCell

Please use tr instead of tr[i]. It will work
var array = [['Car', 'Top Speed', 'Price'],['Chevrolet', '120mph', '$10,000'], ['Pontiac', '140pmh', '$20,000']] // Creating a data array which a loop will source from
var table = document.createElement('table');
document.body.appendChild(table); // Drew the main table node on the document
for (var i = 0; i<3; i++) {
var tr = document.createElement('tr'); //Create 3 <tr> elements assigned to a unique variable BUT need a working alternative for 'tr[i]'
table.appendChild(tr); // Append to <table> node
for (var j = 0; j<3; j++) {
var tdElement = document.createElement('td');
tdElement.innerHTML = array[i][j];
tr.appendChild(tdElement); // Take string from placeholder variable and append it to <tr> node
}
}

My version with the use of THead and TBody as well as th and td.
// input as an array
const array = [
['Car', 'Top Speed', 'Price'],
['Chevrolet', '120mph', '$10,000'],
['Pontiac', '140pmh', '$20,000']
]
const table = document.createElement('table');
// Generate Header
const head = table.createTHead();
const tr = head.insertRow();
array[0].forEach(function(item) {
const th = document.createElement('th')
th.appendChild(document.createTextNode(item));
tr.appendChild(th);
});
// Generate Body
const body = table.createTBody();
array.slice(1).forEach(function(row) {
const tr = body.insertRow();
row.forEach(function(item, index) {
if (index === 0) {
const th = document.createElement('th')
th.appendChild(document.createTextNode(item));
tr.appendChild(th);
} else {
const td = tr.insertCell(); // create td only
td.appendChild(document.createTextNode(item));
}
});
});
document.body.appendChild(table);
ref:
<thead>: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/thead
<tbody>: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tbody
<th>: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/th

Related

In-place replacement of HTML Elements

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)

Append IMG to Table

I am having trouble appending the entire preloaded image array to the table created. This code fills the last column. But I want to fill each cell with each one image per cell.
Where am I going wrong? What am I missing here?
function generate_table() {
//preload Image Array
var preload = ["../../images/Large/bcpot002_r1_c1.jpg", "../../images/Large/bcpot002_r2_c1.jpg", "../../images/Large/bcpot002_r3_c1.jpg","../../images/Large/bcpot002_r4_c1.jpg",
"../../images/Large/bcpot002_r1_c2.jpg", "../../images/Large/bcpot002_r2_c2.jpg", "../../images/Large/bcpot002_r3_c2.jpg","../../images/Large/bcpot002_r4_c2.jpg",
"../../images/Large/bcpot002_r1_c3.jpg", "../../images/Large/bcpot002_r2_c3.jpg", "../../images/Large/bcpot002_r3_c3.jpg","../../images/Large/bcpot002_r4_c3.jpg",
"../../images/Large/bcpot002_r1_c4.jpg", "../../images/Large/bcpot002_r2_c4.jpg", "../../images/Large/bcpot002_r3_c4.jpg","../../images/Large/bcpot002_r4_c4.jpg",
"../../images/Large/bcpot002_r1_c5.jpg", "../../images/Large/bcpot002_r2_c5.jpg", "../../images/Large/bcpot002_r3_c5.jpg","../../images/Large/bcpot002_r4_c5.jpg",];
//preload Images
var images = [];
for (i = 0; i < preload.length; i++) {
images[i] = new Image();
images[i].src = preload[i];
images[i].className="myImg";
}
// get the reference for display div
var imagediv = document.getElementById("test");
// creates a <table> element and a <tbody> element
var tbl = document.createElement("table");
var tblBody = document.createElement("tbody");
// creating all cells
for (var i = 0; i < 4; i++) {
// creates a table row
var row = document.createElement("tr");
row.setAttribute("class", "myTr");
for (var j = 0; j < 5; j++) {
// Create a <td> element and a text node, make the text
// node the contents of the <td>, and put the <td> at
// the end of the table row
var cell = document.createElement("td");
cell.appendChild(images[i]);
cell.setAttribute("class", "myTd");
row.appendChild(cell);
}
// add the row to the end of the table body
tblBody.appendChild(row);
}
// put the <tbody> in the <table>
tbl.appendChild(tblBody);
// appends <table> into <body>
imagediv.appendChild(tbl);
// sets the border attribute of tbl to 2;
tbl.setAttribute("cellpadding", "0");
tbl.setAttribute("cellspacing", "0");
tbl.setAttribute("class", "myTable");
}
Your images urls are indexed with rows of each cell first while you are accessing it through the row iterator which only returns the first 4 images due to your condition : for (var i = 0; i < 4; i++). So you need to use the second iterator as well to get the respective image :
cell.appendChild(images[(j*4) + i]);
https://jsfiddle.net/mjnxhwkL/

Put certain JSON data arrays into a table after using getJson command

How do I use the below code to pull certain details like country name and capital only into a table with drop down headers? Or can you suggest any plain English Youtube videos where I can learn how to do this or example courses where I can teach myself.
<script>
$(document).ready(function () {
//for example details in url below
var url = 'https://restcountries.eu/rest/v1/all';
$.getJSON(url, function (data) {
console.log(data)
// var arrItems = []; // THE ARRAY TO STORE JSON ITEMS.
// $.each(data, function (index, value) {
// arrItems.push(value); // PUSH THE VALUES INSIDE THE ARRAY.
// });
console.log(arrItems)
// EXTRACT VALUE FOR TABLE HEADER.
var col = [];
var arrItems = data.countries;
console.log(arrItems)
var firstCountry = arrItems[0]
console.log(firstCountry)
for (var i = 0; i < arrItems.length; i++) {
for (var key in arrItems[i]) {
if (col.indexOf(key) === -1) {
col.push(key);
}
}
}
// CREATE DYNAMIC TABLE.
var table = document.createElement("table");
// CREATE HTML TABLE HEADER ROW USING THE EXTRACTED HEADERS ABOVE.
var tr = table.insertRow(-1); // TABLE ROW.
for (var i = 0; i < col.length; i++) {
var th = document.createElement("th"); // TABLE HEADER.
th.innerHTML = col[i];
tr.appendChild(th);
}
// ADD JSON DATA TO THE TABLE AS ROWS.
for (var i = 0; i < arrItems.length; i++) {
tr = table.insertRow(-1);
for (var j = 0; j < col.length; j++) {
var tabCell = tr.insertCell(-1);
tabCell.innerHTML = arrItems[i][col[j]];
}
}
// FINALLY ADD THE NEWLY CREATED TABLE WITH JSON DATA TO A CONTAINER.
var divContainer = document.getElementById("showData");
divContainer.innerHTML = "";
divContainer.appendChild(table);
});
});
There's a lot of looping inside of looping, which can increase the time and space complexity - meaning, the more data, the slower this solution will become as well as in general this looks like it will be difficult to maintain.
I would first put as much of the html that you can in the static html and just append the dynamic html to the <tbody>.
You can use the Array.reduce static method to generate a string from your data. One thing you can do to make this easier to understand is stick with either mostly appending DOM nodes or using innerHTML. If you stick with innerHTML, you can create template strings for the cells and the rows.
This will make the code more declarative in nature and functional as well as composeable.
$(document).ready(function() {
//for example details in url below
var url = 'https://restcountries.eu/rest/v1/all';
$.getJSON(url, function(data) {
const html = buildHTML(data);
const tbody = document.querySelector('#showData tbody');
tbody.innerHTML = html;
});
});
const tableCellTemplate = (val) => {
return `<td>${val}</td>`;
};
const tableRowTemplate = (val) => {
return `<tr>${val}</tr>`;
};
function buildHTML(data) {
return data.reduce((prev, next) => {
const nameCell = tableCellTemplate(next.name);
const codeCell = tableCellTemplate(next.alpha2Code);
return prev + tableRowTemplate(nameCell + codeCell);
}, '');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="showData">
<table>
<thead>
<tr>
<th>Name</th>
<th>alpha2Code</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>

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;

Dynamically building table using Javascript

I need to add rows dynamically to a table on a button click event using JavaScript. In addition, the table cells need to contain textboxes.
How can I do this?
Here's a sample code taken from this source. Suggest you read more about DOM, specifically about DOM tables for this question.
function start() {
// get the reference for the body
var body = document.getElementsByTagName("body")[0];
// creates a <table> element and a <tbody> element
var tbl = document.createElement("table");
var tblBody = document.createElement("tbody");
// creating all cells
for (var j = 0; j < 2; j++) {
// creates a table row
var row = document.createElement("tr");
for (var i = 0; i < 2; i++) {
// Create a <td> element and a text node, make the text
// node the contents of the <td>, and put the <td> at
// the end of the table row
var cell = document.createElement("td");
var cellText = document.createTextNode("cell is row "+j+", column "+i);
cell.appendChild(cellText);
row.appendChild(cell);
}
// add the row to the end of the table body
tblBody.appendChild(row);
}
// put the <tbody> in the <table>
tbl.appendChild(tblBody);
// appends <table> into <body>
body.appendChild(tbl);
// sets the border attribute of tbl to 2;
tbl.setAttribute("border", "2");
}

Categories

Resources