Reputation: 147
I've created a table using entirely JavaScript.
The table consists of 3 columns, where one of the columns contains only images in each of the rows. I'm trying to make it where when the user clicks one of the images in the columns, it toggles between two images.
I would have an idea of how to do this if it was just one image assigned to a variable, but since these images were placed by a for loop into a table, there doesn't seem to be any easy way to target them.
How do I do this? I've heard to use the onClick function, and I tried that first, without any success. Here's what my code looks like for that:
var books=[
{title:'Six Easy Pieces: Essentials of Physics By Its Most Brillant Teacher',
author:' Richard P. Feynman',
alreadyRead:false
},
{title:'Astrophysics for People In A Hurry',
author:'Neil deGrasse Tyson',
alreadyRead:true
},
{title:'Pet Semtary',
author:'Stephan King',
alreadyRead:true
},
{title:'The Poisonwood Bible',
author:'Barbara Kingsolver',
alreadyRead:true
},
{title:'The Name Of The Wind',
author:'Patrick Rothfuss',
alreadyRead:true
}
];
//creating table
var bookTable = document.createElement('table');
bookTable.style.width = '75%';
bookTable.setAttribute('border', '3px');
//creating head of table
var thead = document.createElement('thead');
var htr1 = document.createElement('tr');
var htd = document.createElement('td');
var htd2 = document.createElement('td');
var htd3 = document.createElement('td');
htd.appendChild(document.createTextNode('Title'));
htd2.appendChild(document.createTextNode('Author'));
htd3.appendChild(document.createTextNode('Read?'));
htr1.appendChild(htd)
htr1.appendChild(htd2)
htr1.appendChild(htd3)
thead.appendChild(htr1);
bookTable.appendChild(thead);
//creating body
var tbdy = document.createElement('tbody');
for (var i = 0; i < books.length; i++) {
var tr = document.createElement('tr');
var td = document.createElement('td');
var td2 = document.createElement('td');
var td3 = document.createElement('td');
td.appendChild(document.createTextNode(books[i].title ));
td2.appendChild(document.createTextNode(books[i].author ));
//adding images for read and not read
if(books[i].alreadyRead){
var image= document.createElement('img');
image.src="images/check.png";
image.style.width="50px";
image.style.height="50px";
image.addEventListener("click", function (event)
{
var selectedImage = event.target;
if (selectedImage.src == "images/check.png")
{
selectedImage.src = "images/xmark.jpg";
}
else if (selectedImage.src == "images/xmark.jpg")
{
selectedImage.src = "images/check.png";
}
});
td3.appendChild(image);
}
else{
var image= document.createElement('img');
image.src="images/xmark.jpg";
image.style.width="50px";
image.style.height="50px";
image.addEventListener("click", function (event)
{
var selectedImage = event.target;
if (selectedImage.src == "images/check.png")
{
selectedImage.src = "images/xmark.jpg";
}
else if (selectedImage.src == "images/xmark.jpg")
{
selectedImage.src = "images/check.png";
}
});
td3.appendChild(image);
}
tr.appendChild(td)
tr.appendChild(td2)
tr.appendChild(td3)
tbdy.appendChild(tr);
}
bookTable.appendChild(tbdy);
document.body.appendChild(bookTable)
//changing styles
document.head.innerHTML += `
<style>
thead {
background-color: grey;
font-weight: bold;
text-align: center;
}
</style>`;
Upvotes: 0
Views: 296
Reputation: 36426
The event listener is being entered just fine.
The problem is that the src you are getting back is a full URL not just the bit that you put in your src.
You need to test that the elements you put in the src are indeed within that complete image address.
A quick (if slightly dirty) way to do this is to use indexOf - e.g.
(selectedImage.src.indexOf('images/check.png') != -1)
So your code stays exactly as it is except for the tests to see what to change the image to are replaced by the above and equivalent for the other image:
<script>
var books=[
{title:'Six Easy Pieces: Essentials of Physics By Its Most Brillant Teacher',
author:' Richard P. Feynman',
alreadyRead:false
},
{title:'Astrophysics for People In A Hurry',
author:'Neil deGrasse Tyson',
alreadyRead:true
},
{title:'Pet Semtary',
author:'Stephan King',
alreadyRead:true
},
{title:'The Poisonwood Bible',
author:'Barbara Kingsolver',
alreadyRead:true
},
{title:'The Name Of The Wind',
author:'Patrick Rothfuss',
alreadyRead:true
}
];
//creating table
var bookTable = document.createElement('table');
bookTable.style.width = '75%';
bookTable.setAttribute('border', '3px');
//creating head of table
var thead = document.createElement('thead');
var htr1 = document.createElement('tr');
var htd = document.createElement('td');
var htd2 = document.createElement('td');
var htd3 = document.createElement('td');
htd.appendChild(document.createTextNode('Title'));
htd2.appendChild(document.createTextNode('Author'));
htd3.appendChild(document.createTextNode('Read?'));
htr1.appendChild(htd)
htr1.appendChild(htd2)
htr1.appendChild(htd3)
thead.appendChild(htr1);
bookTable.appendChild(thead);
//creating body
var tbdy = document.createElement('tbody');
for (var i = 0; i < books.length; i++) {
var tr = document.createElement('tr');
var td = document.createElement('td');
var td2 = document.createElement('td');
var td3 = document.createElement('td');
td.appendChild(document.createTextNode(books[i].title ));
td2.appendChild(document.createTextNode(books[i].author ));
//adding images for read and not read
if(books[i].alreadyRead){
var image= document.createElement('img');
image.src="images/check.png";
image.style.width="50px";
image.style.height="50px";
image.addEventListener("click", function (event)
{
var selectedImage = event.target;alert(selectedImage.src);
if (selectedImage.src.indexOf('images/check.png') != -1)
{alert();
selectedImage.src = "images/xmark.jpg";
}
else if (selectedImage.src.indexOf("images/xmark.jpg") != -1)
{
selectedImage.src = "images/check.png";
}
});
td3.appendChild(image);
}
else{
var image= document.createElement('img');
image.src="images/xmark.jpg";
image.style.width="50px";
image.style.height="50px";
image.addEventListener("click", function (event)
{
var selectedImage = event.target;
if (selectedImage.src == "images/check.png")
{
selectedImage.src = "images/xmark.jpg";
}
else if (selectedImage.src == "images/xmark.jpg")
{
selectedImage.src = "images/check.png";
}
});
td3.appendChild(image);
}
tr.appendChild(td)
tr.appendChild(td2)
tr.appendChild(td3)
tbdy.appendChild(tr);
}
bookTable.appendChild(tbdy);
document.body.appendChild(bookTable)
//changing styles
document.head.innerHTML += `
<style>
thead {
background-color: grey;
font-weight: bold;
text-align: center;
}
</style>`;
</script>
Upvotes: 1
Reputation: 63524
When you build your table add one listener to the table
element. This method uses event delegation - when you click on an element inside the table the event "bubbles up" the DOM and it caught by the listener on the parent element. A check to see if the target element is an image is all that's needed.
const table = document.querySelector('table');
// Build the table
for (let i = 0; i < 3; i++) {
const img = 'https://dummyimage.com/100x100/000/fff';
table.innerHTML += `<tr><td><img src="${img}" /></td></tr>`;
}
// Add a listener
table.addEventListener('click', handleClick, false);
function handleClick(e) {
// Extract the nodeName and src from the element
// that was clicked on
const { nodeName, src } = e.target;
// If the element is an image swap the images
if (nodeName === 'IMG') {
if (src.split('/')[4] === '000') {
e.target.src = 'https://dummyimage.com/100x100/aaa/000';
} else {
e.target.src = 'https://dummyimage.com/100x100/000/fff';
}
}
}
<table />
Upvotes: 0