I am having some difficulty using parentNode.removeChild()
. I have a list of 'items' in an un-ordered list, each have there own delete button. I am trying bind a click event to each individual button that will delete it's respective parent 'item'.
My code so far:
<ul class="list">
<h2>This is a list</h2>
<li class="item">
<h3>Some Item</h3>
<button class="delete">Delete</div>
</li>
<li class="item">
<h3>Some Item</h3>
<button class="delete">Delete</div>
</li>
<li class="item">
<h3>Some Item</h3>
<button class="delete">Delete</div>
</li>
</ul>
var childElements = document.getElementsByClassName('item');
var buttonElement = document.getElementsByClassName('delete');
function deleteItem(buttonsClass, childClass) {
for (var i=0;i<buttonsClass.length;i++) {
var child = childClass[i];
buttonsClass[i].addEventListener('click', function(child) {
childClass[i].parentNode.removeChild(childClass[i]);
}, false);
}
}
deleteItem(buttonElement, childElements);
I know there is an easier way to do this with jQuery but i really want to solve this with plain javascript. Thank you for any and all help.
This is a perfect case for event delegation. No need for jQuery at all:
(function(window, htmlElement) {
'use strict';
htmlElement.addEventListener("click", handleClick, false);
function handleClick(event) {
if (event.target.classList.contains("delete")) {
event.preventDefault();
removeItem(event.target);
}
}
function removeItem(button) {
var item = getItem(button),
confirmMessage;
if (item) {
confirmMessage = item.getAttribute("data-confirm");
if (!confirmMessage || window.confirm(confirmMessage)) {
item.parentNode.removeChild(item);
}
}
else {
throw new Error("No item found");
}
}
function getItem(button) {
var element = button.parentNode,
item = null;
while (element) {
if (element.nodeName === "LI" || element.nodeName === "TR") {
item = element;
break;
}
element = element.parentNode;
}
return item;
}
})(this, this.document.documentElement);
You have one click handler for the entire page, regardless of how many delete buttons you have. This should also work for list items or table rows, and by specifying a data-confirm
attribute on your buttons, it will pop up a confirm box before removing it.
<button type="button" class="delete"
data-confirm="Are you sure you want to delete this item?">
Delete
</button>
You can also easily change this so it uses another attribute to find the delete button:
<button type="button" class="delete"
data-delete
data-confirm="...">
Delete
</button>
Just change the condition of the if
statement in the handleClick function to:
if (event.target.hasAttribute("data-delete")) {
event.preventDefault();
removeItem(event.target);
}
This decouples your behavior from styling. You can use the delete
class name for styling, and the data-delete
attribute for JavaScript behavior. If you need to change the name of the CSS delete class for any reason, or use a different class, because you decide to use a third party CSS framework like Bootstrap, then you don't need to change a single line of JavaScript.
The last advantage here is that the click handler is attached to the document.documentElement
object, which is available the moment JavaScript begins executing and represents the <html>
element. No need for jQuery's document ready event handler. Just attach the click handler and import the script at any point on the page.
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