http://jsfiddle.net/KKH9a/16/
Tried using console using table1.rows[0].cells[1].innerHTML => "Numbers"
Tried even this code table1.rows[0].cells[1].innerHTML!=null => true
But if I try this code below:
HTML:
<table id="table1">
<tr>
<td>Value</td>
<td></td>
</tr>
<tr>
<td>Value</td>
<td>Value</td>
</tr>
<table>
Javascript:
for (var i = 0; i < table1.rows.length; i++) {
for (var j = 0; j < table1.rows[i].cells[j].innerHTML; j++) {
if (table1.rows[i].cells[j].innerHTML != null) {
var count = 0;
count = count + 1;
alert(count);
}
}
}
table1 isn't defined. You need to use document.getElementById to get a reference to your table element.
On line 2 you're specifying j < table1.rows[i].cells[j].innerHTML. This doesn't make any sense and should be changed to j < table1.rows[i].cells.length.
You need to move your count variable completely outside your loop, otherwise it will always be equal to 1.
Change your code to this:
var table1 = document.getElementById('table1');
var count=0;
for(var i=0;i<table1.rows.length;i++)
{
for(var j=0;j<table1.rows[i].cells.length;j++)
{
if(table1.rows[i].cells[j].innerHTML!=null)
{
count++;
alert(count);
}
}
}
Working JSFiddle demo.
Work on understanding how Javascript interacts with the HTML DOM.
At present your code refers to "table1", but this has nothing to do with the HTML element with the id "table1".
Introductory Javascript tutorials will explain how to get DOM elements into variables. To make things easier, you could use JQuery or something similar.
Once you're past that, you can start looking at the errors in your for loop logic (which other answers have already addressed).
First, you shouldn't use innerHTML to check if there is something in a node. Just count the number of childs instead :
if (table1.rows[i].cells[j].childNodes.length > 0) {
Secondly, if you declare count inside the loops, it will be resetted at each iteration.
Thirldy, I don't understand what you're trying to do with j < table1.rows[i].cells[j].innerHTML. And innerHTML is a String, not a number. You should use parseInt on it.
Calculate count of cells using JQuery after document is ready
$(document).ready(function() {
var count = 0;
$('#table1 td').each(function() {
if($(this).html() != "") {
count++;
}
});
alert(count);
});
Updated Demo: http://jsfiddle.net/KKH9a/27/
Related
Let's say I have a grid that looks like this (the numbers inside the cell is just for labeling, it could just be empty cells):
Written in HTML as follows:
<table>
<tr>
<td>0 </td>
<td>1 </td>
</tr>
<tr>
<td>2 </td>
<td>3 </td>
</tr>
</table>
There are two things that I would like to do:
Add some JavaScript code that log the number of the cell to the console when each cell is clicked. Here is how I did it:
const cells = document.querySelectorAll('td');
for (var i = 0; i < cells.length; i++) {
cells[i].addEventListener('click', function () {
console.log(i);
});
}
But the console always returns the value 4 wherever I click the table. My questions are:
By adding cells[i].addEventListener in each iteration of the for loop, does it add an event listener for each cell?
Why does the console always return 4 even if I clicked the cells[0], cells[\1], cells[2] or cells[3]?
What should I do to make the console return the desired position in the array cells, i.e. return 0 if I clicked cells[0], return 1 if I clicked cells[\1], return 2 if I clicked cells[2], return 3 if I clicked cells[3]?
Next,
The second thing that I would like to do is to change the colour of each cell depending on the colour that I chose from the colour picker as set by the HTML: <input type="color" id="colorPicker">
Here is how I did it:
const cells = document.querySelectorAll('td');
for (var i = 0; i < cells.length; i++) {
cells[i].addEventListener('click', function () {
const color = document.querySelector('#colorPicker').value;
cells[i].style.backgroundColor = color;
});
}
But the colour of the cell did not change.
I don't plan to use jQuery, I would just like to use basic JavaScript that add an event listener to each cell. I have tried to figure some ways out for hours but still clueless in the end. Could somebody please give some help? I really appreciate it, thanks!
Since i is incrementing then after the for loop is complete i == cells.length.
in place of...
for (var i = 0; i < cells.length; i++) {
cells[i].addEventListener('click', function () {
console.log(i);
});
}
use...
for (var i = 0; i < cells.length; i++) {
cells[i].addEventListener('click', function (e) {
console.log(e.target);
});
}
And the same for your latter example...
is because you use "i" variable on your callback. And "i" have value : 4 at the end of your loop, so when you click callback, your app use this last value.
Just change your code by :
const cells = document.querySelectorAll('td');
for (var i = 0; i < cells.length; i++) {
console.log(cells[i].innerText);
cells[i].addEventListener('click', (event) => {
console.log(event.target.innerText); // Take the text node from the element who fire the click event.
// If you don't want to use innerText, you can do like this.
console.log(
//We transform querySelectorAll to traversable array. Then we find index of current event target.
Array.from(document.querySelectorAll('td')).findIndex(e => e === event.target)
);
});
}
And for you second case base on colorPicker :
const cells = document.querySelectorAll('td');
for (var i = 0; i < cells.length; i++) {
cells[i].addEventListener('click', function (event) {
const color = document.querySelector('#colorPicker').value;
event.target.style.backgroundColor = color;
});
}
live sample
I'm trying to add a "clearing" function to my table that calculates totals. So that when person first time presses button that does the calculation, then changes amounts of products and then presses again, the previous answer would be cleared and new added.
I have tried like this:
function clear () {
var table = document.getElementById("pricetable");
var rows = table.getElementsByTagName("tr");
for (var i = 0; i < rows.length; i++) {
rows[i].className = "";
var cells = rows[i].getElementsByTagName("td");
for (var j = 1; j < cells.length - 1; j++) {
cells[j].className = "";
}
}
}
Then I'm calling the function in the beginning of my previous function that calculates the amounts and prices:
function calculate () {
clear ();
...
}
But nothing happens. I was thinking that it might have something to do with the fact that I have created the last row and also the last column (which both include the totals) dynamically. The id of the row is lastRow, and the column doesn't have id.
And I don't want to use jquery or add classes, ids etc to the html file. So does anyone know what's wrong with my code?
className just clears styling.
You're looking for innerHTML:
...
for (var j = 1; j < cells.length - 1; j++) {
cells[j].innerHTML = "";
}
...
className refers to the CSS class name(s) applied to an element. Here's what your current code does:
Before
<td class='foo'>999</td>
After
<td class=''>999</td>
innerHTML pretty much does what it says:
Before
<td class='foo'>999</td>
After
<td class='foo'></td>
Also, I just noticed your for loop starts at 1. Hopefully this was intentional ;)
I can see that you are setting the className to nothing rather than setting the innerHTML to nothing...
Try replacing this:
cells[j].className = "";
With this:
cells[j].innerHTML = "";
I am attempting to replace an image in a table on a click. I am not using JQuery; I am only Javascript to achieve this task. I think I have narrowed down the problem to the comment in the JavaScript code below. All other searches have ended me up with how to change image sources when they are part of the body etc. not part of a cell. I ran through other possible ways as well but for some reason I can't get it to work. Thanks so much!
HTML (Just cut out so you could see what each of the variables is referring to)
<td class="block"><img class="PieceImg" src="Directory/BlankSpace.png"></td>
JavaScript
var cells = document.getElementsByClassName("PieceImg");
for(var j = 0; j<cells.length;j++)
{
var cell = cells[j];
cell.addEventListener("click", function()
{
cell.src="Directory/RedPiece.png"; // This is the problem
alert('Test');
})
}
Assuming that you are running your JavaScript once the DOM is loaded, you should just have to replace cell.src with this.src.
var cells = document.getElementsByClassName("PieceImg");
for(var j = 0; j<cells.length;j++)
{
var cell = cells[j];
cell.addEventListener("click", function()
{
// Replace cell. with this.
this.src="Directory/RedPiece.png";
alert('Test');
})
}
The reason is simple: every time you loop, you create a variable called "cell" (var cell = cells[j];). This non-global variable is overwritten every time the loop is run. If you are running this code inside of a function, your cell variable will not even exist when it comes time to change the src. It will be undefined. Note that making this variable global would result in cell being the last element by class name PieceImg, so that wouldn't work any better.
However, if you use this instead, you will be referencing the "clicked" (remember addEventListener("click")) element when you click it, in this case your image. Thus you are able to change the src. Do a console.log of "this" inside your eventListener to see more things you can access. This gives a similar effect as adding the "click" handler inline:
<img src="fox.png" onclick="alert(this.src);" alt="Fox" />
Let me know if that makes sense to you.
Here's a fully function fiddle: https://jsfiddle.net/7se0vyf5/
Problem is the for loop and the reference of the variable. It does not keep the state when you assign the event handler.
var cells = document.getElementsByClassName("PieceImg");
for (var j = 0; j < cells.length; j++) {
var cell = cells[j];
(function(cell){
cell.addEventListener("click", function() {
console.log(cell);
cell.src = "Directory/RedPiece.png"; // This is the problem
alert('Test');
});
}(cell));
}
<table>
<tr>
<td class="block">
<img class="PieceImg" src="Directory/BlankSpace.png">
</td>
<td class="block">
<img class="PieceImg" src="Directory/BlankSpace.png">
</td>
<td class="block">
<img class="PieceImg" src="Directory/BlankSpace.png">
</td>
</tr>
</table>
So let's say I have a table, and I want to manipulate a specific <td> in it:
HTML:
<table>
<tr><td>1</td> <td>2</td></tr>
<tr><td>3</td> <td>4</td></tr>
<tr><td id="hi">5</td> <td>6</td></tr>
</table>
Javascript:
document.getElementsByTagName("table")[0].rows[2].cells[0];
This will help me REACH a specific cell in a table.
My question is this:
Say I have a specific <td> inside a table:
var td = document.getElementById("hi")
I want to KNOW its location in the table, so I can be able to reach it using table.rows[x].cells[y]
How can I check this location?
I'd suggest, as you imply you know which specific cell you want to find, though currently untested:
var td = document.getElementById("hi"),
col = td.cellIndex,
row = td.parentNode.rowIndex;
The cellIndex property of a td element gives the index of the cell in the row.
The rowIndex property of a tr element gives the index of the row in the table.
So,
var td = document.getElementById("hi");
var x = td.cellIndex;
var y = td.parentNode.rowIndex;
You will need something like this:
function getRowCellPosition(table, cell) {
for (var i = 0; i < table.rows.length; i++) {
for (var j = 0; j < table.rows[i].cells.length; j++) {
if (table.rows[i].cells[j] === cell) {
return {
row: i,
cell: j
};
}
}
}
return null;
}
or more simple:
function getRowCellPosition(cell) {
return {
row: cell.parentNode.rowIndex,
cell: cell.cellIndex
}
}
Simply create a for loop that goes through each row and column and compare the TD in that index against the one you want.
Try this:
for row:
Array.slice(el.parentNode.parentNode.children).indexOf(el.parentNode)
for col:
Array.slice(el.parentNode.children).indexOf(el)
The slice magick is because el.parentNode.children is not an array.
edit: I wasn't aware of td.cellIndex and tr.rowIndex. Definitely use them.
I want to create a JavaScript function that parses my HTML page, get the Table by it's ID, and after that, add a class attribute to each <tr> as if the line is the 1st, I'll add :
class="line1" to the <tr>
but if the line is the second, I'll add class="line2" to the <tr>
How to do please
If I understand you corrrectly, you want to alternate the class names to get some kind of zebra style right?
var table = document.getElementById('yourTableId');
var rows = table.rows;
for(var i = 0, l = rows.length;i < l; i++) {
rows[i].className = 'class' + ((i%2) + 1);
}
See the HTML DOM Table Object.
its very easy in jquery ... as below :-
$(document).ready(function() {
//for table row
$("tr:even").addClass("AlternateBG1");
$("tr:odd").addClass("AlternateBG2");
})
BUT IN JQUERY...
var table = document.getElementById("yourTableId");
for(var i in table.rows){
table.rows[i].className = 'line'+(i+1).toString();
}
It is easy without jQuery:
oTBody=document.getElementById("tBodyId");
//for (key in oTbody.childNodes) {
for (var nPos=0, nLength = oTbody.childNodes.length; nPos<nLegth; nPos++)}
oRow = oTbody.childNodes[nPos];
if (oRow && oRow.tagName && oRow.tagName.toLowerCase() == "tr") {
oRow.className = (bNormalRow? sClass1:sClass2);
bNormalRow = !bNormalRow;
}
}
With jQuery is really simple, do something like:
var i = 1;
$("#myTable tr").each(function() {
$(this).addClass("line"+i);
i++;
});
Where #myTable is your table id, and $(this) inside each function will be the current element on the cycle.