join an array of elements to append it to a node - javascript

How can I do something like:
var html = [];
var tr = document.createElement('tr');
var tr_two = document.createElement('tr');
var tr_three = document.createElement('tr');
html.push(tr);
html.push(tr_two);
html.push(tr_three);
html.join(''); //This doesnt work
document.getElementById('tbody').appendChild(html);
So I need to join my array in a way that is doable, so I hit the DOM once.

Try:
var tbody = document.getElementById('tbody');
html.forEach(funtion(node) {
tbody.appendChild(node);
});

You are trying to join DOM elements instead strings.
You can use outerHTML to achive what you want.
var html = [];
var tr = document.createElement('tr');
var tr_two = document.createElement('tr');
var tr_three = document.createElement('tr');
html.push(tr.outerHTML);
html.push(tr_two.outerHTML);
html.push(tr_three.outerHTML);
html.join(''); //Now it will work
And to append to DOM use
document.getElementById('tbody').innerHTML += html.join('');

The appendChild() function can only be used with nodes, not strings. To do that with your current code, change it to the following:
var html = [];
var tr = document.createElement('tr').appendChild(document.createTextNode("tr 1"));
var tr_two = document.createElement('tr').appendChild(document.createTextNode("tr 2"));
var tr_three = document.createElement('tr').appendChild(document.createTextNode("tr 3"));
html.push(tr);
html.push(tr_two);
html.push(tr_three);
var tbody = document.getElementById("tbody");
html.forEach(function(elem) {
tbody.appendChild(elem);
})
I've added text nodes to each of the trs created so you can see the difference between each one.
The forEach loop just iterates over each element in array you created, and appends each one at time to the element you specified.
Here's a JSFiddle.

Related

creating dynamic grid in javascript

I'm trying to create a dynamic grid in javascript.
Once I'm able to create the two-dimensional grid I'm going to input variables into my functions so they can accept any numerical inputs. For now, I'm just trying to get the grid the render both vertically and horizontally.
My second function is only allowing me to add cells to the same column instead of appending them horizontally. How can get the new columns to shift horizontally?
Here is my code:
function makeCell() {
const canvas = document.getElementById('pixelCanvas')
const newTable = document.createElement('table')
const tr = document.createElement('tr')
const td = document.createElement('td')
canvas.appendChild(newTable);
newTable.appendChild(tr);
tr.appendChild(td);
}
function makeLine() {
let em = ''
for (let i = 0; i < 2; i++) {
em += makeCell()
}
return em
}
function makeGrid() {
let en = ''
for (let i = 1; i <= 4; i++) {
en += makeLine()
}
return en + '\n'
}
makeGrid();
If you mentally run through the code you'll see where you went wrong in your logic.
MakeGrid fires, you go into the first for loop, makeLine fires, you go into the second inner for loop, makeCell fires, here you select the control with id='pixelCanvas', create a new table, create a new tr and create a new td. Then you append the table to the canvas, the tr to the table and lastly the td to the tr.
That's great for the first cell, but now you want the second... Here's the problem, makeCell completed and we go through round two of the for loop in makeLine. It's the same logic, however, so it creates a new table, but because the id is the same it doesn't overwrite anything. Then, it creates a new tr and a new td and appends those. That's why you end up with just one column, each iteration you're created a new row.
Solution:
So how do you fix that? Well, you've probably realized by now you need to create a new row and then iterate through all the cells you want to add to that row BEFORE you append that row to your table.
Modifying your code, this might look like so:
function makeCell(tr) {
// Create new td.
const td = document.createElement('td');
// Append td to tr.
tr.appendChild(td);
// return tr object with appended td.
return tr;
}
function makeLine(newTable) {
// Create new tr.
var tr = document.createElement('tr');
// Loop through number of cells.
for (let i = 0; i < 2; i++) {
// Overwrite tr object with each new cell added.
tr = makeCell(tr);
}
// Append new tr to table.
newTable.appendChild(tr);
// Return the table with the new tr.
return newTable;
}
function makeGrid() {
// Select canvas element.
const canvas = document.getElementById('pixelCanvas');
// Create new table.
var newTable = document.createElement('table');
// Loop through the rows, note use var so that I can pass the
// newTable object in to our function and overwrite it each loop.
for (let i = 1; i <= 4; i++) {
// Overwrite with each appended tr.
newTable = makeLine(newTable)
}
// Append completed object to canvas.
canvas.appendChild(newTable);
}
makeGrid();
Note the use of var instead of let, so the object can be overwritten with the new object on each iteration.
Hope that helps!

Jquery check if data exist as a substring on an html table

Check if data exist on an html table even if it is a substring.
var substring = 'find me'; //substring or data that you wanted to check
var dataExist = [];
$('table#tableID tr').each(function () {
var arrayOfThisRow = [];
var tableData = $(this).find('td');
if (tableData.length > 0) {
if($(this).text().indexOf(substring) == -1)
dataExist.push(true);
}
});
console.log(dataExist.includes(true))
If you're just trying to figure out if a table has a string anywhere in it, you could simply use indexOf() on myTable.innerText.
var myTable = document.getElementById('myTable');
var exists = myTable.innerHTML.indexOf('find me');
If you want to make sure the exists variable is always a boolean, you can use the below line.
var exists = !! ~ document.getElementById('tableID').innerHTML.indexOf('find me');

Swapping html table elements (the complete object) in javascript

EDIT: I just noticed that I'm trying to swap integers because I'm getting the rowIndex. That's not what I want to do. I want to swap objects. However, I don't really know how.
I want to move table elements up and down in a queue by swapping with the element above and the element below respectively. However, my code doesn't work. The following is the JS function for the downButton.
var downButton = document.getElementsByClassName('downButton')[0];
downButton.onclick = function moveDown(currentRow) {
var index = currentRow.parentNode.parentNode.rowIndex;
var nextRow = currentRow.nextElementSibling.parentNode.parentNode.rowIndex;
var temp = index;
index = nextRow;
nextRow = temp;
}
This is the html for the down button:
<button class = "downButton">down</button>
Here's a JSFiddle link for the table: https://jsfiddle.net/Led4b3nw/
Swap innerHTML instead of indexes:
var index = currentRow.parentNode.parentNode;
var nextRow = currentRow.nextElementSibling.parentNode.parentNode;
var temp = index.innerHTML;
index.innerHTML = nextRow.innerHTML;
nextRow.innerHTML = temp;

Javascript deleteRow causing indexSizeError, need closure

I have this code:
var table = document.getElementById("editTable");
var row = table.insertRow(-1);
var i = row.rowIndex;
var remove = document.createElement("input");
remove.type = "button";
remove.value = "Remove";
remove.onclick = (function() {
var I = i;
return function() {
table.deleteRow(I);
}
})();
var td1 = row.insertCell(-1);
td1.appendChild(remove);
I have read several articles here and I don't understand what I am doing wrong. When I try to delete the last row that I create , I get this error:
IndexSizeError: Index or size is negative or greater than the allowed amount
table.deleteRow(I);
I am pretty sure this is a closure issue. I understand scope but not syntax for anonymous functions in javascript;
I think you're over thinking the whole function/anonymous function/closure stuff here. It's looking a little too complicated. Try this code:
var table = document.getElementById("editTable");
var row = table.insertRow(-1);
var remove = document.createElement("input");
//Append input first so you can get it's parent
var td1 = row.insertCell(-1)
.appendChild(remove);
remove.type = "button";
remove.value = "Remove";
remove.onclick = function () {
var parent = this.parentNode.parentNode; //get the row node
table.deleteRow(parent.rowIndex - 1); //Delete the row index behind it.
};
jsFiddle
Corey, I see you have a working solution but you may be interested in something closer to your original idea.
The problem with your original code appears to be that i becomes an unreliable measure of current row index after other rows have been removed. Trapping i in a closure is not a solution - you just trap a value that is guaranteed to be correct only at the time it is trapped.
However trapping row itself, then obtaining row.rowIndex when it's needed will be reliable, because row.rowIndex gives the current index, not the index at the time the row was appended to the table.
remove.onclick = (function(row) {
return function() {
table.deleteRow(row.rowIndex);
};
})(row);
here is the code working:
var remove = document.createElement("input");
remove.type = "button";
remove.value = "Remove";
remove.onclick = function () {
var parent = this.parentNode.parentNode; //get the row node
table.deleteRow(parent.rowIndex); //Delete the row index behind it.
};
var td1 = row.insertCell(-1)
.appendChild(remove);

Javascript - get all table -> tr values

<table>
<tr><td>foo</td></tr>
<tr><td>bar</td></tr>
<tr><td>abc#yahoo.com</td></tr>
</table>
Can anybody tell me how to write a Javascript line to only grab the email address in the table below, I've been searching a lot, but all I come across is tutorials which use "id" in either table on in td .. I want to do it without having an id .. please help
var rows = document.getElementsByTagName("table")[0].rows;
var last = rows[rows.length - 1];
var cell = last.cells[0];
var value = cell.innerHTML
Try it yourself here: http://jsfiddle.net/ReyNx/.
Obviously you'll have to change document.getElementsByTagName("table")[0] to appropriately match your table
If you're using jQuery it's easier:
var value = $('table tr:last td').text();
For more info, see the MDN DOM reference, which shows you which properties are available on which elements to traverse the DOM.
No jQuery, innerHtml or other evil / heavy functions, just plain old JavaScript:
// Get the first table in the document.
var table = document.getElementsByTagName('table')[0];
// Get the third row of this table (0-index 3rd = 2)
var emailRow = table.rows[2];
// Get this element's content.
var emailContent = emailRow.firstChild.textContent;
You could write it in 1 line:
var emailContent = document.getElementsByTagName('table')[0].rows[2].firstChild.textContent;
If you want to find all email addresses in a table:
var emails = [];
var table = document.getElementsByTagName('table')[0];
var rows = table.rows;
for (var i = 0; i < rows.length; i++) {
var rowText = rows[i].firstChild.textContent;
if (~rowText.indexOf('#')) { // If the content of the row contains a '#' character (This could be replaced with a regex check)
// Also, I personally prefer to use '~' over '> -1' for indexOf(), but both would work.
emails.push(rowText);
}
}
console.log(emails);
Working example
If like me you want to get the text from all the first column items in all the tables on the page then use this.
jQuery('table tr td').each( function( cmp ) {
console.log( jQuery(this).text() );
} );
I wanted to extract all emails, but I had more than 1,000 rows and 17 columns/cells.
I used vanilla js, made some adjustments to get my desired output
var table = document.getElementsByTagName("table")[0]; //first table
var rows = table.rows;
//loop through rows
for (var i = 0; i < rows.length; i+=1) {
var emailTr = rows[i];
var emailTd = emailTr.cells[2]; //target third column/cell
var email = emailTd.innerHTML; //get the value
console.log(email + ', ');
var node = document.createElement("span"); // create span element
node.innerHTML = email + ', '; // desired output
document.body.appendChild(node); // display to document body
}
Assuming you're using vanilla Javascript (no libraries such as jQuery), and that this is the only table on the page, you can use the following code to select the third tr in the table, then find out what the td element contains
var table = document.getElementsByTagName("table")[0];
var emailTr = table.rows[2];
var emailTd = emailTr.cells[0];
var email = emailTd.innerHTML;
jQuery would make this easier
var email = $("table").children("tr:eq(2)").children("td").html();
A simple way is to give it a common class. Try:
<table>
<tr><td class="email">foo</td></tr>
<tr><td class="email">bar</td></tr>
<tr><td class="email">abc#yahoo.com</td></tr>
</table>
<script>
function getEmail(){
var email = new Array();
var arr = document.getElementsByClassName('email');
for(var i=0; i< arr.length; i++){
email.push(arr[i].innerHTML);
}
alert(email.join(','));
}
</script>
Demo
This is a solution in case you are using or plan to use jQuery library.
Given the email is always in the third row and first column (like in your example) then you can do as follows:
email = $('table tr:nth-child(3) td:first-child').html();
See working demo
Get all the <tr> elements. Loop through each one and compare the innerHTML against a regex that matches email addresses.
var emailAddresses = [];
var cells = document.getElementsByTagName("td");
for (var i = 0; i < cells.length; i++) {
if (cells[i].innerHTML.match(/yourEmailRegex/g)) {
emailAddresses[emailAddresses.length] = cells[i].innerHTML;
}
}
Find the appropriate regular expression here http://www.regular-expressions.info/email.html
in my case i want fifth column value of last row
var rows = document.getElementsByTagName("tbody")[0].rows;
var last = rows[rows.length - 1];
var cell = last.cells[4];
console.log(cell.textContent);

Categories