Event Listeners w/my bookstore

Event Listeners w/my bookstore
0

#1

Wondering if anyone can help with the “delete” - using an eventListener - I used a keyCode method for adding Books but would like to use a “click” eventlistener for deleting.
I can’t figure out how to target the parent.
Any tips or direction anyone give me would be appreciated.

https://codepen.io/kahwasaurus/pen/qpQRYr


#2

Well, since every time you create a book there is no persistence (i.e. no db) , you would want to create some type of identifier for the book as you create it, then you can use that same identifier to delete it. Right now, all the books created are generically the same, so you can not delete a specific book. There are several ways to approach this, but let’s see what you come up with first…


#3

I could be totally wrong here, so let me know if I’m going in the right direction. I was thinking of running a for loop to get each book (or span). When I click on the span, that span’s parent element would delete.

for (i=0;i<span.length;i++) {  //for each span in the span node
    //addEventListener when user clicks on the trash can 
    book.classList.remove("book"); }  //remove the book class
    //find parent element of span i.e. book
    //then delete that corresponding spans parent element

How is that as far as a process? Writing the code is next


#4

sounds good, maybe even less verbose than what I was thinking, of course you’d still have to add some type of an identifier (class or id) to your trash can (span) so you can attach an event listener (like a click) to it right ?, anyway go for it and see how it works out…


#5

OK I got a lot further. We now have a trash can that can be removed if the book already exists. If we’re adding it as a new title, however, it’s not clickable. Thoughts on what the difference is? I suspect it has to do with row 28 and adding that tag to the innerHTML within the book.


#6

Ok got it done with jquery so if you can convert to plain javascript will work as well … if i get a chance ill try and do it … Im just used to working with jquery.
(‘click’, ‘i’, function … the i here represents your tag for the icons and is important
and also add jquery to codepen … when its converted to plain javascript you can remove jquery

    $('#shelf').on('click', 'i', function(){
       var rem = $(this).closest('p');
    $(rem).remove();
            return false;
       });

#7

ok heres a javascript version it adds a event handler to the div id shelf and if a ‘<i>’ tag is clicked it removes your book …

  shelf.addEventListener("click", function(e) {
    var target = e.target;
        if(target.tagName == 'I'){
        return target.parentNode.remove();
        }
  });

#8

A new book is not clickable, because you only run the following code one time:

var trashCans = document.querySelectorAll("i");

Array.from(trashCans).forEach(function(trashcan) {
  trashcan.addEventListener("click", function(e) {
    const i = e.target.parentElement;
    i.parentNode.removeChild(i);
  });
});

When the page loads, you have your “first book” in the html section and so trashCans only has the “first book”. Hence, the only book with an addEventListener on it is “first book”.

There are two ways to solve this issue.

  1. Whenever a new book is added, you could use addEventListener to attach an event handler to it. The problem with this method is, if you added 100 books, there would be 100 event listeners which is a lot of overhead for the app.

  2. The better method is to use event delegation, so that you only have one event listener which “listens” to the entire collection of books (the div with id=“shelf”). Then, whenever a book is clicked, you check the event target to see if it is a trash can icon. If it is, then remove it. I have blurred out how this would be implemented below, in case you want to attempt to implement it on your own.

shelf.addEventListener("click", event => {
  if (event.target.classList.contains('fa-trash-o'))
    event.target.parentElement.remove();
});   

UPDATE: It appears @JohnL3 beat me to a solution, but hopefully you understand why your original solution was not working.


#9

Thanks for the jQuery solution too. Saving this for when I’m there. I’d like to be able to create the library with both vanilla JS and jQuery.


#10

So part of this is that I’m not fully grasping the event.target capability. I’ll stare at it for a bit until it clicks.

OK so summarizing mostly for myself:

add a click event listener to the shelf, and function
get the event target (i.e. where the user clicked) and set it to "target"
if the target name is ‘i’, (trash can)
return target’s parent (parent of i aka “book”) and remove it.


#11

Ah ok so this (your #2) is would take care of deleting ALL books, whether they exist or are added later. Add the eventListener to the shelf, find the target of where the click occurred, and if the click was on the trash can, then remove the target’s (trash) parent (book)

The solution is always so much easier than the learning process but I’m pretty excited that it’s starting to click!


#12

So wait this means that I won’t have to declare every single variable at the top of the JS file. It’ll find everything using the event target.


#13

No if you didnt declare shelf at the top of the file i then would have to do it before i could use shelf.

e.target is a object (e is a object e.target is html console.log it to see ) … so i assign its contents to var target … i can then check for things like tagName by doing if (target.tagName = ‘I’ or eg if it was span you clicked i would do if(target.tagName == ‘SPAN’) or do things like randelldawson did … i dont know much about the e.target but just enough to sort me out when i need to do something like this … else i just google event.target and see what comes up.
Also if you didnt want to delete all the books … eg maybe the first couple should not be able to be deleted you probably could give any that are added to the dom a class eg del and then target only those with a class of del … but you wouldnt use tagName … you probably would need to look up another parameter to use … had a quick look and think if(target.className === ‘name of class’) would work.


#14

shelf.addEventListener(“click” … this adds an event listener of type click on the div with id of shelf … the e in the function is just short for event … so e is a object of information on the event … if you console.log(e.target) you get ‘’<i class=‘fa fa-trash-o fa-2x’>’'
if you console.log(e) you get a big object back … try it out and go to dev tools and open the object and see whats in it …
so when you click on the trash icon you are actually triggering the eventlistener on the div id of shelf … because the trash icon is inside the div … thats why you … if(target.tagName == ‘I’){ use this line to check if you clicked on the icon in the div if so you can delete it … if you had clicked on the paragraph within the div it wouldnt match and book wouldnt be deleted.
hope this helps im not great at explaining things lol


#15

Very helpful! Thank you. I’m testing out parts of my code in small parts but definitely understanding the big picture. Just need to practice.