I have an element that looks like this:
There is an onclick event on the section area and one on the cross.
<div onclick="sectionClicked()">
.....
<div onclick="deleteSection()">
<img src=".../delete-section.png" />
</div>
</div>
CSS to position the cross
.section_delete {
display: block;
position: absolute;
top: -10px;
right: -5px;
}
However, when I click on the cross, both deleteSection and sectionClicked functions are fired.
How do I prevent the sectionClicked function from being fired when then cross is clicked?
What is very strange is that if I click on the very outside of the cross, so that I am certainly not clicking on the section area, the same thing is happening.
CodePudding user response:
I think you better wrap both in another div. Make the fist div's position relative. As the cross is inside the div, so its an element under it. So it will fire all over its element. I have attached the code below. Hope this might help you. Here assume red colored div as the cross icon.
function sectionClicked(){
console.log("Hi I'm yellow div");
}
function deleteSection(){
console.log("Hi I'm red div");
}
.section_delete{
position: absolute;
top: 0;
right: 0;
z-index: 10;
}
<div style="position: relative">
<div style="height: 150px; background-color: yellow" onclick="sectionClicked()">
<p style="text-align:center"> Click Me </p>
</div>
<div style="background-color: red" onclick="deleteSection()">
<p> Click Me </p>
</div>
</div>
CodePudding user response:
- The visual position of the cross icon does not matter, what matters is the icon's ancestry in the DOM and that's the way events propagate, bubble
- never use
Event.stopPropagation()
(even if seemingly a quick fix) unless you really, really know what you're doing (and this is not such case). An app and all its components both yours or third-party should always be notified and able to intercept events occurring during their lifetime - in their environment. - stop using inline HTML
on*
handlers. JavaScript is supposed to be in one place only and that's its respective tag or file
Instead
delegate events on the parent element (or even better on a static common parent if you have any), and use Event.target
in combination with .closest()
to determine the clicked element:
document.querySelectorAll(".section").forEach((elSection) => {
elSection.addEventListener("click", (evt) => {
// Delete button was clicked:
if (evt.target.closest(".section_delete")) {
console.log("Delete button clicked");
elSection.remove();
}
// Section was clicked:
else {
console.log("Section clicked");
elSection.classList.toggle("is-done");
}
// Section or any other child element was clicked:
// ...
});
});
.section {
position: relative;
background: #eee;
padding: 1rem;
margin: 1rem;
}
.section_delete {
display: block;
position: absolute;
top: -10px;
right: -5px;
}
.is-done {
background: hsl(100, 80%, 80%);
}
<div >
Lorem ipsum
<button type="button" >×</button>
</div>
<div >
Dolor sit amet
<button type="button" >×</button>
</div>
<div >
Adipiscing consectetur elit
<button type="button" >×</button>
</div>
For a better understanding read: events for dynamic child elements
Additionally
- Don't use
DIV
when in need for<button>
. Markup semantics matter.
CodePudding user response:
if you specify the event in the onclick:
<div onclick="deleteSection(event)">
<img src=".../delete-section.png" />
</div>
Then you can stop the event propagating:
deleteSection = ev =>{
ev.stopPropagation();
...
}