Creating html table from multidimensional javascript array - javascript

I was trying to create an html table from a nested for loop array in Javascript. When I try to append the <tr> tags to the table they get put in an element called tbody. How can I get the tr tags to be appended in the to the table element rather than the tbody element?
<html>
<head>
<script src='jq.js'></script>
</head>
<body>
<table id='tb'></table>
</body>
<script>
$('#tb').ready(
function() {
console.log('table loaded');
var ar = Array(2);
for(var i=0;i<ar.length;i++){
ar[i]=Array(2);
}
ar[0][0]='1';
ar[1][0]='2';
ar[0][1]='3';
ar[1][1]='4';
console.log('multidimensional array created!');
for(var j=0;j<ar.length;j++){
console.log('<tr>');
$('#tb').append('<tr>');
for(var k=0;k<2;k++){
console.log('<td>'+ar[k][j]+'</td>');
$('#tb').append('<td>'+ar[k][j]+'</td>');
}
console.log('</tr>');
$('#tb').append('</tr>');
}
//expected:
//12
//34
//actual
//1 2 3 4
});
</script>
</html>
Here's a jsfiddle

You can't. HTML tables are composed of three sections:
thead contains the header rows
tbody contains the data rows. You can have multiple of these if you want to make different groups of rows (e.g. if rows = months, you could have a separate tbody for each year).
tfoot contains the footer rows
If you put rows directly within the table tag, they're assumed to be part of tbody, and the browser creates this element automatically for you. You either have to put all your rows in tbody elements, or put them all directly within table.
The problem with your code has nothing to do with the tbody element. The problem is that you're trying to append td elements directly to the table, rather than to the tr elements. You're treating $('#tb').append() as if it's concatenating HTML text to the document, not inserting entire HTML elements. It should be something like:
for(var j=0;j<ar.length;j++){
console.log('<tr>');
var row = $('<tr/>').appendTo('#tb');
for(var k=0;k<2;k++){
console.log('<td>'+ar[k][j]+'</td>');
row.append('<td>'+ar[k][j]+'</td>'); // Append TD to TR
}
}
Or you can use CtrlX's answer, where he composes the entire table as a string, then inserts it into the DOM in one step. This is more efficient than building up the table incrementally.

You shouldn't append content like this to your table, because the browser must redraw the whole DOM, so it's not very efficient.
You should build your table inside a string, then append the whole string to your table, like this :
$('#tb').ready(
function() {
console.log('table loaded');
var ar = Array(2);
for(var i=0;i<ar.length;i++){
ar[i]=Array(2);
}
ar[0][0]='1';
ar[1][0]='2';
ar[0][1]='3';
ar[1][1]='4';
console.log('multidimensional array created!');
//Prepare the outputed string
var theTable = "";
for(var j=0;j<ar.length;j++){
theTable += '<tr>';
for(var k=0;k<2;k++){
theTable += '<td>'+ar[k][j]+'</td>';
}
theTable += '</tr>';
}
//Finally appended the whole string to the table
$('#tb').append(theTable);
//expected:
//12
//34
//actual
//1 2 3 4
});
I've made a Jsfiddle for you : JSFiddle
Have fun !

<body>
<table id='tb1'>
<tbody id='tb'>
</tbody>
</table>
</body>
<script>
$('#tb').ready(
function() {
console.log('table loaded');
var ar = Array(2);
for(var i=0;i<ar.length;i++){
ar[i]=Array(2);
}
ar[0][0]='1';
ar[1][0]='2';
ar[0][1]='3';
ar[1][1]='4';
console.log('multidimensional array created!');
for(var j=0;j<ar.length;j++){
$('#tb').append('<tr>');
for(var k=0;k<2;k++){
$('#tb').append('<td>'+ar[k][j]+'</td>');
}
$('#tb').append('</tr>');
}
//expected:
//12
//34
//actual
//1 2 3 4
});
</script>
</html>
this is the working code, on this fiddle http://jsfiddle.net/fn4Wz/

Related

Issue with getting a keyup function to get sum of input field values using plain Javascript

I'm working on a personal project and I've run into an issue that I haven't been able to solve.
Here is a function that generates new table rows into a table (with id of "tableData") when a button is clicked:
function addNewRow(){
var tableEl = document.getElementById("tableData");
var newLine = '<tr class="newEntry">';
var classArray = ["classA", "classB", "classC", "classD"];
for (var i = 0; i < classArray.length; i++){
newLine += '<td><input class="' + classArray[i] + '"></td>';
}
newLine += '</tr>';
tableEl.insertAdjacentHTML("beforeend", newLine);
}
document.getElementById("addRow").addEventListener("click", addNewRow, false);
//the element with id="addRow" is a button
I've simplified the code for the above function for the sake of readability as it's not the focus of the problem. When the button is clicked, a new row is added successfully.
The problematic part involves another function that takes the sum of the respective classes of each row and displays them in a div.
The goal is to get the sum of the values of all input fields with matching class names. For example, let's say I use the addNewRow function to get six rows. Then I want to have the div showing the sum of the values of all input fields with the class name of "classA"; the number in that div should be the sum of those six values, which gets updated as I type in the values or change the existing values in any of the input fields with class name of "ClassA".
function sumValues(divId, inputClass){
var sumVal = document.getElementsByClassName(inputClass);
var addedUp = 0;
for (var j = 0; j < sumVal.length; j++){
addedUp += Number(sumVal[j].value);
}
document.getElementById(divId).innerHTML = addedUp;
}
Here are a couple (out of several) failed attempts:
document.input.addEventListener("keyup", sumValues("genericDivId", "classA"), false);
document.getElementsByClassName("classA").onkeyup = function(){sumValues("genericDivId", "classA");}
Unfortunately, after scouring the web for a solution and failing to find one, I just added an event listener to a button that, when clicked, would update the div to show the sum of values. Also had to modify the sumValues function to take values from an array rather than accepting arguments.
My question is: How can I modify the code so that the sum value updates as I type in new values or change existing values using pure Javascript (vanilla JS)?
You are very close, document.getElementsByClassName() returns an array of DOM objects, you need to set the onkeyup function for each and every element by looping through that array.
var classA = document.getElementsByClassName('classA'); // this is an array
classA.forEach(function(elem){ // loop through the array
elem.onkeyup = function(){ // elem is a single element
sumValues("genericDivId", "classA");
}
}
Hopefully this fixes your issue
Maybe the example below is not same with your situation, but you'll get the logic, easily. Anyway, do not hesitate to ask for more guide.
document.getElementById("row_adder").addEventListener("click", function() {
var t = document.getElementById("my_table");
var r = t.insertRow(-1); // adds rows to bottom - change it to 0 for top
var c = r.insertCell(0);
c.innerHTML = "<input class='not_important_with_that_way' type='number' value='0' onchange='calculate_sum()'></input>";
});
function calculate_sum() {
var sum = ([].slice.call(document.querySelectorAll("[type=number]"))).map(e=>parseFloat(e.value)).reduce((a, b) => a+b);
document.getElementById("sum").innerHTML = sum;
}
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div>
<p>
<strong>Sum</strong>:<span id="sum">0</span>
</p>
</div>
<button id="row_adder">
Click me
</button>
<table id="my_table">
</table>
</body>
</html>

Creating separate arrays from TH data in different tables

I'm having a bit of an issue with some JS/JQuery. I am using some script to create an array from the data within the <TH> tags, then doing some formatting of that data to create new content and styles for a responsive table.
<script>
$( document ).ready(function() {
// Setup an array to collect the data from TH elements
var tableArray = [];
$("table th").each(function(index){
var $this = $(this);
tableArray[index] = $this.text();
});
console.log(tableArray);
alert(tableArray);
// Create class name based on th values and store as variable
var tableString = tableArray.join();
tableString = tableString.replace(/,/g, '_')
tableString = tableString.replace(/ /g, '-')
var tableClass = ".responsive-table."+tableString;
console.log(tableClass);
// Push tableClass variable into the table HTML element
var applyTableClass = tableClass;
applyTableClass = applyTableClass.replace(/\./gi, " ") //converts the style declaration into something i can insert into table tag (minus the dots!)
console.log(applyTableClass);
$( "table" ).addClass( applyTableClass );
// Create a loop which will print out all the necessary css declarations (into a string variable) based on the amount of TH elements
var i = 0;
var styleTag = "";
while (tableArray[i]) {
styleTag += tableClass+" td:nth-of-type("+[i+1]+"):before { content: '"+tableArray[i]+"'; }";
i++;
}
// Push the styleTag variable into the HTML style tag
$('style#jquery-inserted-css').html(styleTag);
// Below is just a test script to check that values are being collected and printed properly (use for testing)
//$('#css_scope').html('<p>'+styleTag+'</p>');
});
</script>
This works great when there is a single table within the page, but not if there is additional tables. The reason is that the loop that creates the array keeps going and does not know to stop and return at the end of one table, then create a new array for the next table. I am imagining that I need to set up a loop that creates the arrays as well.
This is where I am quit stuck with my limited scripting skills. Can anyone please suggest a way to get my code to loop through multiple tables, to create multiple arrays which then create separate style declarations?
You can loop through each table instead of querying all tables at once:
$( document ).ready(function() {
$("table").each(function () {
var tableArray = [];
$(this).find("th").each(function (index) {
var $this = $(this);
tableArray[index] = $this.text();
});
console.log(tableArray);
alert(tableArray);
// Create class name based on th values and store as variable
var tableString = tableArray.join();
tableString = tableString.replace(/,/g, '_')
tableString = tableString.replace(/ /g, '-')
var tableClass = ".responsive-table." + tableString;
console.log(tableClass);
// Push tableClass variable into the table HTML element
var applyTableClass = tableClass;
applyTableClass = applyTableClass.replace(/\./gi, " ") //converts the style declaration into something i can insert into table tag (minus the dots!)
console.log(applyTableClass);
$(this).addClass(applyTableClass);
// Create a loop which will print out all the necessary css declarations (into a string variable) based on the amount of TH elements
var i = 0;
var styleTag = "";
while (tableArray[i]) {
styleTag += tableClass + " td:nth-of-type(" + [i + 1] + "):before { content: '" + tableArray[i] + "'; }";
i++;
}
// Push the styleTag variable into the HTML style tag
$('style#jquery-inserted-css').append(styleTag);
// Below is just a test script to check that values are being collected and printed properly (use for testing)
//$('#css_scope').html('<p>'+styleTag+'</p>');
});
});
Note that I change $("table th") to $(this).find("th"), $("table") to $(this) and $('style#jquery-inserted-css').html(styleTag); to $('style#jquery-inserted-css').append(styleTag);.
Hope this help.

Count number of rows for each printed table

I need your assistant in getting the total number of rows for each printed table in my html to be shown at the top of it.
I am having multiple tables in the html which their id is unique "detailsTable". Each table has different number of rows. I search for a script to print the total number of rows and I found the below script:
function count()
{
var rows = document.getElementById("detailsTable").getElementsByTagName("tr").length;
alert(rows);
}
and in the body tag, I placed:
<body onload="count()">
When I ran the page, it shows an alert for the first table which it has 22 records and the script ignores the below tables.
So, can you please help me to modify the above code and to display the alert for the other tables.
The id should be unique for every html element.
You can use class instead, and then:
function count()
{
var tables = document.getElementsByClassName("detailsTable");
var rows;
for (var i = 0; i < tables.length; i++) {
rows = tables[i].rows.length;
alert(rows);
}
}
If you want to count table rows with id = "detailsTable"
var rowCount = $('#detailsTable tr').length;
If you want to find it for every table, it would look something like:
$('.details').each(function(index) {
var rowCount = this.rows.length;
})

question regarding javascript;Html generation and search current webpage for tags

Hi I have 3 questions, if you have for example this simple website
<html> <head> </head> <body> <table>
<tr> <td>www.hello1.com</td>
</tr> <tr> <td>www.hello2.com</td>
</tr> </table> </html>
Question 1)
If I for instance decide to click on link number 2 (www.hello2.com), Is this stored in some kind of variable?
I know that this is storing the current URL but not the one that you click
window.location.href;
Question 2)
How do you search your document, say that I would like to search the this website and store all the links in a javascript array like this
var myArray = [];
searchThisWebSiteForURLS()//Do this function that I don't know to write that search this htmlsite for url's
var myArray = [ 'http://www.hello1.com', 'http://www.hello2.com'];//This is the reslt after that the function has been executed
Question 3)
I would like to write out these links. Say that I have another table like this
<html> <head> </head> <body> <table>
<tr> <td>X</td>
</tr> <tr> <td>Y</td>
</tr> </table> </html>
Where X = http://www.hello1.com
And Y = http://www.hello2.com
Of course it shall be as many rows as there are elements in the array like this
<html> <head> </head> <body> <table>
<tr> <td>X</td></tr>
<tr> <td>Y</td></tr>
<tr> <td>Z</td></tr>
<tr> <td>A</td></tr>
<tr> <td>B</td></tr>
</table> </html>
Where Z, A, B are the elements 3,4,5 in the array
var myArray = [ 'http://www.hello1.com', 'http://www.hello2.com','http://www.hello3.com','http://www.hello4.com','http://www.hello5.com'];
EDIT!--------------------------------------------------------------------------
Wow really thanks, all of you, really thanks! I just have one more question regarding the links, when comparing two links, say that the array looks like this
var pageLinks = ['http://www.example.at', 'http://www.example2.at', 'http://www.someothersite.at'];
And say that the user has pressed the example "http://www.example.at" link, then I want to create the table containing the similar links. So I do something like this
function checkForSimilarLink(theLinkToCompareWith){// in this case theLinkToCompareWith = "http://www.example.at"
var numLinks = pageLinks.length;
for(var i = 0; i < numLinks; i++) {
//Check if numLinks[i]== theLinkToCompareWith*
}
}
So how would you write this compare function? In this case we can consider
"http://www.example.at" and "http://www.example1.at" the "same" while "http://www.someothersite.at" obviosly aren't
Thanks again :)
I didn't understand question 1, but here's something for question 2 and 3:
Question 2:
var pageLinks = [];
var anchors = document.getElementsByTagName('a');
var numAnchors = anchors.length;
for(var i = 0; i < numAnchors; i++) {
pageLinks.push(anchors[i].href);
}
//now pageLinks holds all your URLs
Question 3:
// say pageLinks holds your desired URLs
var pageLinks = ['http://www.example.at', 'http://www.example2.at', 'http://www.example3.at'];
// create an empty table
var table = document.createElement('table');
// ... and it's tbody
var tbody = document.createElement('tbody');
// loop through your URLs
var numLinks = pageLinks.length;
for(var i = 0; i < numLinks; i++) {
// create new table row...
var tr = document.createElement('tr');
// a cell...
var td = document.createElement('td');
// and your anchor...
var a = document.createElement('a');
// set the anchor's href
a.setAttribute('href', pageLinks[i]);
// set the anchor's text, it's also the URL in this example
a.innerHTML = pageLinks[i];
// append the anchor to the table cell
td.appendChild(a);
// ... and that cell to the new row
tr.appendChild(td);
// ... and that row to the tbody, right? ;-)
tbody.appendChild(tr);
}
// after all rows were added to the tbody,
// append tbody to the table
table.appendChild(tbody);
// and finally append this table to any existing
// element in your document, e.g. the body:
document.body.appendChild(table);
// ...or add it to a div for example:
//document.getElementById('anyDiv').appendChild(table);
Go study JQuery!!!! XDD The best for web development.
for the first and second question in with jquery:
var anchors = $('a'); //returns all <a></a> elements from here you can get the url from all of theam
With jquery u can write any element that you want.
var table = $('<table></table>');
var tr = $('<tr></tr>').appendTo(table);
var td = $('<td></td>').setText('your link here')appendTo(tr);
. . .
table.appendTo(The parent element to add the table);
Question 1:
You can capture the onclick event for clicking on the link and during that store whatever information you want to a variable of your choosing (though, this would only be relevant if you included return false in the onclick event because the link would otherwise take the user to a new page and end your session).
Question 2 and 3 were answered quite well by Alex.

what's the easiest method to append a TR to a table by javascript?

If the table id is known – so the table can be obtained with docoument.getElementById(table_id) – how can I append a TR element to that table in the easiest way?
The TR is as follows:
<tr><td><span>something here..</span></td></tr>
The first uses DOM methods, and the second uses the non-standard but widely supprted innerHTML
var tr = document.createElement("tr");
var td = document.createElement("td");
var span = document.createElement("span");
var text = document.createTextNode("something here..");
span.appendChild(text);
td.appendChild(span);
tr.appendChild(td);
tbody.appendChild(tr);
OR
tbody.innerHTML += "<tr><td><span>something here..</span></td></tr>"
The most straightforward, standards compliant and library-independent method to insert a table row is using the insertRow method of the table object.
var tableRef = document.getElementById(tableID);
// Insert a row in the table at row index 0
var newRow = tableRef.insertRow(0);
P.S. Works in IE6 too, though it may have some quirks at times.
Using jQuery:
$('#table_id > tbody').append('<tr><td><span>something here..</span></td></tr>');
I know some may cringe at the mention of jQuery. Including a framework to do just this one thing is probably overkill. but I rarely find that I only need to do "just one thing" with javascript. The hand-coded solution is to create each of the elements required, then add them in the proper sequence (from inner to outer) to the other elements, then finally add the new row to the table.
If you're not opposed to using jQuery, you can use either of the following where "tblId" is the id of your table and "_html" is a string representation of your table row:
$(_html).insertAfter("#tblId tr:last");
or
$("#tblId tr:last").after(_html);
i use this function to append a bunch of rows into a table. its about 100% faster then jquery for large chunks of data. the only downside is that if your rows have script tags inside of them, the scripts wont be executed on load in IE
function appendRows(node, html){
var temp = document.createElement("div");
var tbody = node.parentNode;
var nextSib = node.nextSibling;
temp.innerHTML = "<table><tbody>"+html;
var rows = temp.firstChild.firstChild.childNodes;
while(rows.length){
tbody.insertBefore(rows[0], nextSib);
}
}
where node is the row to append after, and html is the rows to append
Really simple example:
<html>
<table id = 'test'>
<tr><td>Thanks tvanfosson!</td></tr>
</table>
</html>
<script type="text/javascript" charset="utf-8">
var table = document.getElementById('test');
table.innerHTML += '<tr><td><span>something here..</span></td></tr>';
</script>
I use this, works softly:
var changeInnerHTMLOfMyCuteTbodyById = function (id_tbody, inner_html)
{
//preparing
var my_tbody = document.getElementById (id_tbody);
var my_table = my_tbody.parentNode;
my_table.removeChild (my_tbody);
//creating dom tree
var html = '<table style=\'display:none;\'><tbody id='+ id_tbody+'>' +
inner_html + '</tbody></table>';
var tmp_div = document.createElement ('div');
tmp_div.innerHTML = html;
document.body.appendChild (tmp_div);
//moving the tbody
my_table.appendChild (document.getElementById (id_tbody));
}
You can do this:
changeInnerHTMLOfMyCuteTbodyById('id_tbody', document.getElementById ('id_tbody').innerHTML + '<tr> ... </tr>');

Categories