I'want to add an eventListener to the table cells so each time a table cell is clicked to execute a function .
var getDaysInMonth = function (year, month) {
return new Date(year, month, 0).getDate();
}
var calendar = {
month: function () {
var d = new Date();
return d.getMonth() + this.nextMonth;
},
year: function () {
var y = new Date();
return y.getFullYear();
},
nextMonth: 1,
cellColor: 'white',
}
var loopTable = function () {
var daysInMonth = getDaysInMonth(calendar.year(), calendar.month());
var table = document.getElementById('myTable');
var rows = table.rows;
var l = 1;
var month = calendar.month();
var year = calendar.year();
var firstDay = new Date(year + "-" + month).getDay();
var currentDay = new Date().getDay();
var dayOfMonth = new Date().getDate();
for (let i = 1; i < rows.length; i++) {
if (rows[i] == rows[1]) {
var k = 1;
for (let j = firstDay; j < rows[i].cells.length; j++) {
if (k === dayOfMonth && calendar.nextMonth === 1) {
rows[i].cells[j].style.backgroundColor = calendar.cellColor;
}
if (k <= daysInMonth) {
rows[i].cells[j].innerHTML = k;
k++
}
}
} else {
for (let j = 0; j < rows[i].cells.length; j++) {
if (k === dayOfMonth && calendar.nextMonth === 1) {
rows[i].cells[j].style.backgroundColor = calendar.cellColor;
}
if (k <= daysInMonth) {
rows[i].cells[j].innerHTML = k;
k++
}
}
}
}
}
loopTable();
clickCell();
function monthTitle() {
var monthsArray = ['Jan.', 'Feb.', 'Mar.', 'Apr.', 'May', 'Jun.', 'Jul.', 'Aug.', 'Sept.', 'Oct.', 'Nov.', 'Dec.'];
monthNum = calendar.month();
var monthName = monthsArray[calendar.month() - 1] + '' + calendar.year();
var title = document.getElementById('calendarTitle');
var nextArrow = document.getElementById('nxt');
var leftArrow = document.getElementById('prev');
if (monthName === ('Dec.' + '' + calendar.year())){
xmas();
}
if (monthNum >= 12) {
nextArrow.className += ' inactiveLink';
} else if (monthNum <= 1) {
leftArrow.className += ' inactiveLink';
} else {
nextArrow.classList.remove('inactiveLink');
leftArrow.classList.remove('inactiveLink');
}
title.innerHTML = '';
var titleNode = document.createTextNode(monthName);
title.appendChild(titleNode);
}
monthTitle();
function nextMonth() {
clearTable();
calendar.nextMonth += 1;
monthTitle();
loopTable();
}
function previousMonth() {
clearTable();
calendar.nextMonth -= 1;
monthTitle();
loopTable();
}
function clearTable() {
var table = document.getElementById('myTable');
var rows = table.rows;
for (var i = 1; i < rows.length; i++) {
cells = rows[i].cells;
for (var j = 0; j < cells.length; j++) {
if (cells[j].innerHTML = '') {
cells[j].style.display = 'none';
}
cells[j].innerHTML = '';
cells[j].style.backgroundColor = '#D9534F';
cells[j].style.emptyCells = 'hide';
}
}
}
var next = document.getElementById('nxt');
var previous = document.getElementById('prev');
var table = document.getElementById('myTable');
var cell = table.rows;
next.addEventListener('click', nextMonth);
previous.addEventListener('click', previousMonth);
function clickCell() {
var row = document.getElementById('myTable').rows;
for (var i = 0; i < row.length; i++) {
for (var j = 0; j < row[i].cells.length; j++ ) {
row[i].cells[j].addEventListener('click', function(){
console.log('click');
})
}
}
}
clickCell();
body {
background-color: rgb(0, 121, 191);
}
table {
width: 50%;
background-color: #D9534F;
border: 1px solid white;
padding: 10px;
padding-bottom: 20px;
font-size: 25px;
border-radius: 25px;
position: relative;
margin: auto;
}
td {
border: 1px solid white;
text-align: center;
font-weight: 600;
font-size: 20px;
padding: 20px;
}
th {
height: 50px;
}
.calArrows {
text-decoration: none;
color: white;
font-size: 35px;
}
#nxt {
font-size: 30px;
position: absolute;
top: 0;
right: 25%
}
#prev {
font-size: 30px;
position: absolute;
top: 0;
left: 25%;
}
#calendarTitle {
font-family: 'Indie Flower', cursive;
font-weight: 600;
font-size: 25px;
color: white;
}
.inactiveLink {
cursor: not-allowed;
pointer-events: none;
}
#myTable {
empty-cells: hide;
}
.xmasDec {
width: 90%;
height: 70%;
position: absolute;
top: -10%;
left: 5%;
}
#calWraper {
position: relative;
}
#myCan {
position: absolute;
top: 0;
left: 10%;
width: 90%;
height: 70%;
opacity: 0, 5;
}
<body>
<canvas class="myCan" width="100" height="100"></canvas>
<div id="calWraper">
<table id="myTable">
<caption id="calendarTitle">Test</caption>
<tr>
<th>Sun</th>
<th>Mon</th>
<th>Tue</th>
<th>Wed</th>
<th>Thur</th>
<th>Fri</th>
<th>Sat</th>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
</tr>
</table>
<canvas id="myCan" width="200" height="200" style="background-color: transparent"></canvas>
<a href="#" id="prev" class="calArrows"><i class="fa fa-arrow-left" ></i></a>
<a href="#" id="nxt" class="calArrows"><i class="fa fa-arrow-right" ></i></a>
</div>
</html>
I tried by creating a function that it will loop through rows and cells and add the eventListener to each . But it seems that its not working , its working on random instances which is really strange behavior . Here is the function i create:
function clickCell() {
var row = document.getElementById('myTable').rows;
for (var i = 0; i < row.length; i++) {
for (var j = 0; j < row[i].cells.length; j++ ) {
console.log(row[i].cells[j].innerHTML);
row[i].cells[j].addEventListener('click', function(){
console.log('click');
})
}
}
}
It seems your canvas is overlapping your table. Because of that td
elements in your table are never clicked.
You will need to add CSS property pointer-events:none
to your canvas.
#myCan {
...
pointer-events: none;
}
This way it won't block table from being clicked anymore.
You can also add event listeners to your cells way simpler:
document.querySelectorAll('#myTable td')
.forEach(e => e.addEventListener("click", function() {
// Here, `this` refers to the element the event was hooked on
console.log("clicked")
}));
That creates a separate function for each cell; instead, you could share one function without losing any functionality:
function clickHandler() {
// Here, `this` refers to the element the event was hooked on
console.log("clicked")
}
document.querySelectorAll('#myTable td')
.forEach(e => e.addEventListener("click", clickHandler));
Some browsers still don't have forEach
on the HTMLCollection returned by querySelectorAll
, but it's easily polyfilled:
if (!HTMLCollection.prototype.forEach) {
Object.defineProperty(HTMLCollection.prototype, "forEach", {
value: Array.prototype.forEach
});
}
If you have to support truly obsolete browsers that don't have Array.prototype.forEach
, see the polyfill on MDN.
This is a case for event delegation: Hook the click event on the table (or table body), not individual cells, and then determine which cell was clicked by looking at event.target
and its ancestors.
Simplified example:
document.querySelector("#my-table tbody").addEventListener("click", function(event) {
var td = event.target;
while (td !== this && !td.matches("td")) {
td = td.parentNode;
}
if (td === this) {
console.log("No table cell found");
} else {
console.log(td.innerHTML);
}
});
Live Copy:
document.querySelector("#my-table tbody").addEventListener("click", function(event) {
var td = event.target;
while (td !== this && !td.matches("td")) {
td = td.parentNode;
}
if (td === this) {
console.log("No table cell found");
} else {
console.log(td.innerHTML);
}
});
table, td, th {
border: 1px solid #ddd;
}
table {
border-collapse: collapse;
}
td, th {
padding: 4px;
}
<table id="my-table">
<thead>
<tr>
<th>First</th>
<th>Last</th>
</tr>
</thead>
<tbody>
<tr>
<td>Joe</td>
<td>Bloggs</td>
</tr>
<tr>
<td>Muhammad</td>
<td>Abdul</td>
</tr>
<tr>
<td>Maria</td>
<td>Gonzales</td>
</tr>
</tbody>
</table>
Note that instead of the loop you could use the new (experimental) closest
method on elements:
var td = event.target.closest("td");
...but A) It's still experimental, and B) It won't stop when it reaches the tbody
, so in theory if you had nested tables, would find the wrong cell.
If you need to support browsers that don't have Element.prototype.matches
, in this specific case you could use td.tagName !== "TD"
instead of !td.matches("td")
(note the capitalization).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With