Leia
Leia

Reputation: 357

Event Delegation: Affecting more elements than it should

I'm learning event delegation, and I encounter a problem.

At first, when I did the first draft, if I clicked in the < span > it would only delete the text and not the button, so I modified it. Later, when clicking the container div it deleted the whole thing, so I changed it again.

Right now it's functional, but it seems to me that it could be written more generically (without needing to add the class names, just the id of the container) and in a more efficient way, I feel there is a lot more code than it should be.

And one more thing: It should work with dynamically added elements.

Any help would be very appreciated!

function getTarget(e) {
    return e.target;
}

function remove(e) {
    var target = getTarget(e);
    target.parentNode.removeChild(target);
}

function remove1(e) {
    var target = getTarget(e);
    var parent = target.parentNode;
    parent.parentNode.removeChild(parent);
}

document.getElementById("contenedor").addEventListener("click", function (e) {
	if (e.target && e.target.nodeName === "DIV" && e.target.classList.contains("bot")) {
		remove(e);
	}
    if (e.target && e.target.nodeName === "SPAN") {
		remove1(e);
	}
    document.getElementById("parrafo").textContent  = "Hice click en";
});
<!DOCTYPE html>
<html>
<head>
</head>
<body>
    <div id="contenedor">
    <div class="bot" id="boton" style="width:200px; height:50px; background-color: red"><span>asdasd</span></div>
    <br>
    <div class="bot" id="boton1" style="width:200px; height:50px; background-color: red"><span>asdasd</span></div>
    <br>
    <div class="bot" id="boton2" style="width:200px; height:50px; background-color: red"><span>asdasd</span></div>
    <br>
    <div class="bot" id="boton3" style="width:200px; height:50px; background-color: red"><span>asdasd</span></div>
    <br>
    <div class="bot" id="boton4" style="width:200px; height:50px; background-color: red"><span>asdasd</span></div>
    <br>
    <div class="bot" id="boton5" style="width:200px; height:50px; background-color: red"><span>asdasd</span></div>
    </div>
    <br>
<script src="script.js"></script>
</body>
</html>

Upvotes: 1

Views: 54

Answers (1)

Me.Name
Me.Name

Reputation: 12534

In a JS event, e.target is the element the action (click) is performed on and this the element the code is attached to. That can be used to check if the parentNode is the div the click was attached to (well, the same could be done by checking if the parent is the div by its id, but since it's an event delegation excercise, this is more fun :) )

document.getElementById("contenedor").addEventListener("click", function (e) {
    var target = e.target;
    if(target!==this){ //if the div itself is clicked do nothing
        while(target.parentNode !== this) //loop up until it's a direct parent, this also works with multiple nested elements
            target = target.parentNode;
        target.parentNode.removeChild(target);
    }
    document.getElementById("parrafo").textContent  = "Hice click en";

});

fiddle

As a side note, instead of adding a <BR> under each div, you can also alter the margin through css with something like

.bot{
    margin-bottom:20px;
}

This has the advantage that removed elements hold the same space (unless of course, that is not the intention ;) )

Example: fiddle

Upvotes: 1

Related Questions