Here is my HTML file
<div class="a">
<div class="b">
</div>
</div>
<script>
document.querySelector('.a').onclick = ()=>{
document.querySelector('.a').style.backgroundColor ='black'
}
document.querySelector('.b').onclick = ()=>{
document.querySelector('.b').style.backgroundColor ='violet'
}
</script>
When I click on the div with class 'b' ,the event handler on the div with class 'a' is also called. I want only the div with 'b' class event handler to be called. Can someone help on this?
This is Event Bubbling, which means that each event is triggered not only on the target element but also on its ancestor elements.
To prevent this behavior, you can use Event.stopPropagation() to stop the event from propagating to the ancestor elements of the target element.
document.querySelector('.a').onclick = () => {
document.querySelector('.a').style.backgroundColor = 'black'
}
document.querySelector('.b').onclick = (event) => {
event.stopPropagation();
document.querySelector('.b').style.backgroundColor = 'violet'
}
div { width: 100px; height: 100px; }
.a { padding: 40px; background: red; }
.b { background: blue; }
<div class="a">
a
<div class="b">b</div>
</div>
There's a concept called Event Bubbling in JS. By default any event that's happening on a particular element will be propagated to the parent and to it's parent and so on till the event reaches the document.
In order to stop this behaviour Event.stopPropagation will come to the rescue and will stop propagating the event to the parent.
So in this case calling e.stopPropagation in the onclick handler of the div with class b i.e., the inner div will stop the event to be propagated to the parent div.
document.querySelector('.a').onclick = (e) => {
document.querySelector('.a').style.backgroundColor = 'black'
}
document.querySelector('.b').onclick = (e) => {
e.stopPropagation();
document.querySelector('.b').style.backgroundColor = 'violet'
}
.b {
width: 50%;
}
<div class="a">
<div class="b">
Dummy
</div>
</div>
Try this :
document.querySelector('.a').onclick = ()=>{
document.querySelector('.a').style.backgroundColor ='black'
}
document.querySelector('.b').onclick = (e) => {
e.stopImmediatePropagation();
document.querySelector('.b').style.backgroundColor ='violet'
}
<div class="a">a
<br/>
<div class="b">
Click here!
</div>
</div>
Related
I have this:
<div onclick="myFunc()" style="height:200px;width:200px;">
<button></button>
</div>
I want myFunc to execute when any place on the div is clicked EXCEPT for the button. How can I do this?
On the button's click event, you need to cancel propagation. Or stop 'bubbling up'.
See https://developer.mozilla.org/en-US/docs/Web/API/Event/stopPropagation
So on your button's click event - you need something like:
function button_click(event) {
event.stopPropagation();
console.log("button clicked.");
}
By default, an element's click event gets passed to its parent.
document.querySelector('#mydiv').addEventListener('click', myFunc)
function myFunc(event) {
if (event.target.tagName !== 'BUTTON') {
console.log('works')
}
}
#mydiv {
background: red;
height: 200px;
width: 200px;
}
<div id="mydiv">
<button>click me</button>
</div>
If your contents are going to be more complex than just a single button and you want to make sure you're only running when you click on the parent element, you could use: e.target === e.currentTarget to detect when the event is occurring on that element specifically. (Documentation: target, currentTarget)
This avoid having to check for every child element, or prevent every child from propagating events. (But if you only have a single child element, one of the other answers would be simpler)
document.getElementById('example').addEventListener('click', myFunc)
function myFunc(e) {
if (e.target === e.currentTarget) {
console.log('Parent div clicked')
}
}
#example {
width: 100px;
height: 100px;
}
div,
span {
border: 1px solid #555;
}
<div id="example">
<button>A</button>
<div>B</div>
<span>C</span>
</div>
I have a element with a click event with a child with another click event.
And i did the following solution to prevent the parent action to happen when you click in the child element
const parent = document.getElementById("parent")
parent.addEventListener("click", e =>{
alert("clicked")
})
const child = document.getElementById("child")
function prevent(e)
{
e.stopPropagation()
e.preventDefault()
}
child.addEventListener("click", prevent)
child.addEventListener("mousedown", prevent)
#parent{
width:300px;
height:300px;
background-color:yellow;
display: flex;
justify-content: center;
align-items: center;
}
#child{
width:100px;
height:100px;
background-color:red;
}
<div id="parent">
<div id="child">
</div>
</div>
However when you hold down the button in the child element and release in the parent the click happens, is there a way to prevent that?
This is surprisingly tricky (or I'm missing something obvious).
The below handles it by remembering the last mousedown (in a way that's unlikely to be bypassed by other handlers) and then ignoring the click event on parent if the mousedown passed through child.
let lastMouseDown = null;
// Use a capture handler on mousedown to remember that
// mousedown event (a capture handler so we see the event
// even if something stops propagation -- unless somebody
// registered a capture handler before us and stopped
// immediate propagation, which isn't all that likely
document.addEventListener(
"mousedown",
event => {
lastMouseDown = event;
},
true // A capture handler
);
const parent = document.getElementById("parent");
parent.addEventListener("click", e => {
// If the last mousedown event passed through the
// child, ignore this click
if (lastMouseDown && child.contains(lastMouseDown.target)) {
prevent(e);
return;
}
console.log("clicked");
});
const child = document.getElementById("child");
function prevent(e) {
e.stopPropagation();
e.preventDefault();
}
child.addEventListener("click", prevent);
child.addEventListener("mousedown", prevent);
#parent{
width:300px;
height:300px;
background-color:yellow;
display: flex;
justify-content: center;
align-items: center;
}
#child{
width:100px;
height:100px;
background-color:red;
}
<div id="parent">
<div id="child">
</div>
</div>
It works in this example, but I can't say I'm very happy with it.
I'm creating a horizontal scroll website and wondering if I can make the addEventListener disable when the cursor pointer is located within an element.
Here is an example.
<div class="bar">Disable mousewheel event when the cursor pointer is within this div</div>
<script>
window.addEventListener("mousewheel", (e) => {
if (e.deltaX === 0) {
e.stopPropagation();
e.preventDefault();
window.scrollBy(e.deltaY, 0);
}
});
</script>
The key is not about "disabling" or "removing" the event listener...
The key is knowing if the mouse is over a particular element in order to do something else... (actually, doing nothing should be considered "something else").
let barFlag = false;
window.addEventListener("mousewheel", (e) => {
if(!barFlag){
console.log("mousewheel!")
}else{
console.log("No!")
}
});
document.querySelectorAll(".bar").forEach(function(bar){
bar.addEventListener("mouseenter", function(){
barFlag = true;
});
bar.addEventListener("mouseleave", function(){
barFlag = false;
})
})
.spacer{
height: 500px;
}
.bar{
height: 300px;
border: 1px solid red;
}
<div class="spacer"></div>
<div class="bar">Disable mousewheel event when the cursor pointer is within this div</div>
<div class="spacer"></div>
<div class="bar">Disable mousewheel event here too</div>
<div class="spacer"></div>
My question in the title probably looks vague. And I sketched an example for the question:
container.onclick = () => {
alert(0);
};
content.onclick = () => {
alert("how can I prevent here appearance alert(0) from parent element event?");
//how can I prevent parent event by content clicked?
};
#container{
height: 100px;
background-color: gray;
}
#content{
height: 50px;
width: 150px;
background-color: green;
}
<div id="container">
<div id="content"></div>
</div>k
This is a simple example. In a real project, I can't combine these two events into one, because the first one is programmatically assigned somewhere in the bowels of my framework and it shouldn't be removed from the EventListener after clicking on content
In General, is it possible to somehow interrupt the execution of the call chain event by clicking in the DOM layers? I tried to do this:
content.onclick = () => {
alert("how can I prevent here appearance alert(0) from parent element event?");
e.preventDefault();
return false;
//how can I prevent parent event by content clicked?
};
But this, of course, was not successful
You should pass the event by dependency injection to the specific method (content.onclick) and then stop the propagation of it.
container.onclick = () => {
alert(0);
};
content.onclick = (e) => {
e.stopPropagation();
alert("VoilĂ , this prevent that appears alert(0) from parent element event.");
};
#container{
height: 100px;
background-color: gray;
}
#content{
height: 50px;
width: 150px;
background-color: green;
}
<div id="container">
<div id="content"></div>
</div>
For this, you can use stop propogation of js like this
<div id="container">
<div id="content" onclick="event.stopPropagation();">
</div>
</div>
So when you click on content it will not trigger container event only.
This question already has answers here:
Attach event handlers for click event on all elements in the DOM
(5 answers)
Closed 3 years ago.
i try to make onclick event to all the decomnt that give me back the elment id that i click on .
thank you
i tried to you the parent id
document.getElementById("parent").onclick = function(){btnIsClicked(this.id)};
this work but give me the parent id not the clicked one..
document.getElementById(*).onclick = function(){btnIsClicked(this.id)};
function btnIsClicked(id){
console.log(id);
}
please i need some thing like * to make it for all but in same time give me the id of the clicked elment (not the just the parent one)
You can add the event listener to the document and access the element that was clicked as event.target
document.addEventListener('click', (event) => {
console.log(event.target.id);
})
.box {
width: 50px;
height: 50px;
background-color: lightblue;
margin: 10px;
display: inline-block;
}
<div id="box1" class="box"></div>
<div id="box2" class="box"></div>
<div id="box3" class="box"></div>
You can attach an event listener to the document body.
document.getElementsByTagName('body')[0].onclick = function(e) {console.log(e.target.id)};
You can use querySelectorAll and addEventListener for achive this.
const elements = document.querySelectorAll('*');
for (let i = 0; i < elements.length; i++) {
const element = elements[i];
element.addEventListener('click', e => {
e.stopPropagation();
btnIsClicked(e.target.id);
});
}
function btnIsClicked(id) {
console.log(id);
}
div {
display: inline-block;
width: 100px;
height: 100px;
}
#element-one {
background: blue;
}
#element-two {
background: red;
}
<div id="element-one"></div>
<div id="element-two"></div>
A possible approach using querySelectorAll and stopPropagation() to get the exact element clicked.
[...document.querySelectorAll("*")].forEach(em => {
em.addEventListener("click", (e) => {
e.stopPropagation();
console.log(e.target)
})
});
<h1>title</h1>
<div>text inside div
<span>text inside span</span>
</div>