简体   繁体   中英

javascript and dom manipulation

My goal is to delete and/or move the parent element of the button on the page when it is clicked. The DOM doesn't seem to respond to my click event. I think it has something to do with scope and global variables but I'm still a newbie. Here's what my code looks like.

 var startButton = document.querySelectorAll('button[data-action="start"]'); var deleteButton = document.querySelectorAll('button[data-action="delete"]'); var element = document.getElementsByTagName('section'); var firstChildElement = element.firstChild; startButton.addEventListener("click", toStart); deleteButton.addEventListener("click", deleter); /*function declarations*/ function toStart() { element.insertBefore(this.parentNode, firstChildElement); } function deleter() { element.removeChild(this.parentNode); } 
 <section> <article> <h2>Item One 😇</h2> <p>Lorem ipsum dolor sit amet</p> <button data-action="start">Move to start</button> <button data-action="delete">Delete</button> </article> <article> <h2>Item Two 👿</h2> <p>Lorem ipsum dolor sit amet</p> <button data-action="start">Move to start</button> <button data-action="delete">Delete</button> </article> <article> <h2>Item Three 👻</h2> <p>Lorem ipsum dolor sit amet</p> <button data-action="start">Move to start</button> <button data-action="delete">Delete</button> </article> </section> 

That's because you are using querySelectorAll() , which returns a node list (a set of nodes) and you can't add an event listener (call .addEventListener() ) on a set. You can only do it on an individual node. The same is true for .getElementsByTagName() . It also returns a node list and you can't ask for the .firstChild of a node list. You can only call it on a node.

You can use .querySelector() instead to get just the first node that matches the selector.

Now, if you want to set up events on all the buttons, then you'd need to loop over the node list and call .addEventListener() for each one.

But, since you want the same listeners on all the buttons, it's more efficient and less code to use event delegation , whereby we allow events to "bubble" up to ancestor elements and intercept the event just once at that higher level element. Then, we can examine which element actually triggered the event at a lower level and act accordingly.

 // We're going to let all click events within the section be handled at the section level // instead of setting up the same handlers on multiple elements. let sec = document.querySelector("section"); sec.addEventListener("click", handleClick); // When the event bubbles up to the section, this function will be called // and it will automatically receive a reference to the event that triggered it function handleClick(event){ // The .target property of the event object refers to the lower-level ojbect // that actually initiated the event (either a start or delete button in our case). // We're going to need the nearest <article> ancestor of the button that was clicked // The closest() method finds the nearest ancestor element that matches the selector let art = event.target.closest("article"); // We can check what the source of the event was and act accordingly // Since you've used data-* attributes, use the dataset API to test them if(event.target.dataset.action === "start"){ toStart(art); } else if(event.target.dataset.action === "delete") { deleter(art); } } /*function declarations*/ function toStart(element){ element.parentNode.insertBefore(element, element.parentNode.firstChild); } function deleter(element){ element.parentNode.removeChild(element); } 
 <section> <article> <h2>Item One 😇</h2> <p>Lorem ipsum dolor sit amet</p> <button data-action="start">Move to start</button> <button data-action="delete">Delete</button> </article> <article> <h2>Item Two 👿</h2> <p>Lorem ipsum dolor sit amet</p> <button data-action="start">Move to start</button> <button data-action="delete">Delete</button> </article> <article> <h2>Item Three 👻</h2> <p>Lorem ipsum dolor sit amet</p> <button data-action="start">Move to start</button> <button data-action="delete">Delete</button> </article> </section> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM