stopPropagation & preventDefault are not working, parent click is still firing - javascript

In my code, I have added onclick on parent div and want to perform other action on inner div, but clicking on inner div also triggering parent click.
how to stop that?
$(document).on('click', '.child', function(e) {
e.preventDefault();
e.stopPropagation();
console.log('child');
});
function parentfun(sender) {
console.log('parent');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="parent" onclick="parentfun(this)">
parent
<div class="child">child</div>
</div>
Above divs are generated on run time on some other event.
Clicking on child, also trigger parent's click. preventDefault & stopPropagation are not working.
FYI: my question is different than How do I prevent a parent's onclick event from firing when a child anchor is clicked?

What you are actually doing here is binding the click-event to the document, not the child-element. So the event has already bubbled up all the way to the document, it's too late to try to stop the bubbling with stopPropagation.
See here when I change the click-handler to the child instead:
$(".child").on('click', function(e) {
e.preventDefault();
e.stopPropagation();
console.log('child');
});
function parentfun(sender) {
console.log('parent');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="parent" onclick="parentfun(this)">
parent
<div class="child">child</div>
</div>
Edit
As the question changed a bit, here is what you can do (for example) if the elements are created dynamically:
$(document).on('click', '.parent, .child', function(e) {
e.stopPropagation();
if ($(this).is(".child")) {
console.log('child');
} else {
console.log('parent');
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="parent">
parent
<div class="child">child</div>
</div>

Using plain vanilla JS it works as expected:
function logEventTarget(e) {
e.stopPropagation();
console.log(e.target.id);
}
parentDiv.addEventListener('click', logEventTarget)
childDiv.addEventListener('click', logEventTarget)
<div id="parentDiv">
parent
<div id="childDiv">child</div>
</div>
Using an inline event handler won't pass the event to the handler function:
function logEventTarget(e) {
e.stopPropagation();
console.log(e.target.id);
}
childDiv.addEventListener('click', logEventTarget)
<div id="parentDiv" onclick="logEventTarget()">
parent
<div id="childDiv">child</div>
</div>
One of the many reasons you shouldn't use inline event handlers at all. Note that e.stopPropagation() still works for the childDiv.

You can notice that when clicking the chlid element the parent triggers first (that is why parent prints first then child ) because of event capturing which precedes event bubbling. In-order to stop the event capturing phase from parent you can stop propagating that event and then only child event will trigger.
$(document).on('click', '.child', function(e) {
//e.preventDefault();
e.stopPropagation();
console.log('child');
});
$(document).on('click', '.parent', parentfun);
function parentfun(e) {
e.stopPropagation();
console.log('parent');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="parent">
parent
<div class="child">child</div>
</div>

You can also resolve this problem by editing little bit in Your html code
<div class="parent" id="parent-div">
<!-- Just adding parent div text inside span tag -->
<span>parent</span>
<div class="child">child</div>
</div>
now go to jquery code
$('.parent span').on('click',function(){
//only print child text u can do more
alert($('.child').text());
//Change color of child
$('.child').css('color','red');
});

Related

Disabling a click event from the child of a parent div

I am trying to add a on click event to a div with a class parent. Now inside that div I have a div with class child that has its own click event.
How can I manage to disable the click event of the parent function for that child element in order to execute the function of child element itself?
I have tried using pointer-event:none; but it does not seem to be working. I have wrote a jsfiddle for better understanding.
https://jsfiddle.net/arq1epbs/
$(document).on('click', '.parent', function() {
var url = $(this).attr("data-url")
document.location.href = url
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="parent" data-url="www.google.com">
Im the parent
<div class="child">
im the child and I don't want to go to Google
</div>
</div>
Thanks for all the help in advance!
You can use stopPropagation():
$(document).on('click', '.parent', function () {
var url = $(this).attr("data-url")
document.location.href = url
});
$(document).on('click', '.child', function (e) {
e.stopPropagation();
});
As it's not working in the Stack Snippet, here a Fiddle
For reference: stopPropagation()
You can simply call event.stopPropagation() inside child click event, to prevent the event from bubbling up the DOM tree, preventing any parent handlers from being notified of the child click event like:
$(document).on('click', '.parent', function() {
//var url = $(this).attr("data-url")
//document.location.href = url
console.log('Parent Clicked');
});
$(document).on('click', '.child', function(event) {
event.stopPropagation();
console.clear();
console.log('Child Clicked');
});
.parent{background:#99c0c3;width:350px;height:120px;position:relative}
.child{background:#ffde99;width:300px;height:50%;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%)}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="parent" data-url="www.google.com">
Im the parent
<div class="child">
im the child and I don't want to go to Google
</div>
</div>
Just add this line:
$(document).on('click', '.parent', function (e) {
if(e.target !== this) return false; //This line added
var url = $(this).attr("data-url")
document.location.href = url
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="parent" data-url="www.google.com">
Im the parent
<div class="child">
im the child and I don't want to go to Google
</div>
</div>
You can do this in "pure" JS
document.querySelector('div.parent').onclick = evt =>
{
if (!evt.target.matches('div.parent')) return // reject sub elements click
document.location.href = evt.target.dataset.url
}
div.parent { cursor: pointer }
div.child { cursor: default }
<div class="parent" data-url="www.google.com">
Im the parent
<div class="child">
Im the child and I don't want to go to Google
</div>
</div>

jquery on event for a dynamically generated child of a dynamically generated child

I have a div that gets added to dynamically and I would like to have a mouseenter event for images that have been dynamically added in another tag. The div that is getting added to looks like this before hand:
<div class="chat_box">
</div>
and looks like this after content has been added:
<div class="chat_box">
<p class="chat">text here <img class="emote" src="emote.png"> more text</p>
</div>
I would like to have a mouseenter event for the image with the class of emote, but I cannot get it to work.
I have tried the following:
$('.chat_box').on('mouseenter', '.chat', function(){
alert();
});
and it works, but if I try to use the child selector
$('.chat_box').on('mouseenter', '.chat > .emote', function(){
alert();
});
and
$('.chat_box').on('mouseenter', '.chat > img', function(){
alert();
});
it doesn't work.
This was previously provided by .live(), but that function has been merged into .on() ... it creates an event watcher.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<div class="chat_box"></div>
<button>Add</button>
<script>
$('button').click(function(){
$('<div class="chat"><img width=10 height=10 class="emote"></div>').appendTo('.chat_box');
});
$('.chat_box').on('mouseenter', 'img.emote', function(){ alert('test'); });
</script>
Just target the parent object and have it watch for the expected child.

How to use event.stopPropagation() JavaScript

I have three elements with events assigned to them. How should I use event.stopPropagation so only events for elements #1 and #2 are executed, but not for #3? I put event.stopPropagation in element #2 as it stops bubbling. In my understanding, it should stop the triggering of the event in #3 but it doesn't seem to be working, all events are still being executed. Here is JS code:
document.addEventListener("DOMContentLoaded", function() {
document.querySelector('#element1').addEventListener('click', function(e) {
console.log('Event in #element1 fired!');
});
document.querySelector('#element2').addEventListener('click', function(e) {
event.stopPropagation();
console.log('Event in #element2 fired!');
});
document.querySelector('#element3').addEventListener('click', function(e) {
console.log('Event in #element3 fired!');
});
});
<div id="element3" class="element">
Element 3
<div id="element2" class="element">
Element 2
<div id="element1" class="element">
Element 1
</div>
</div>
</div>
This line is wrong:
event.stopPropagation();
because the parameter with the event object passed to the function is named e.
You need to write this as:
e.stopPropagation();

How to bind click event to element hasn't specific child using jquery?

I have several elements on a page like bottom code.
<div>
click
some content
</div>
They can be clicked and jQuery picks that click. However one of the elements has a a link that is clicked should not be picked as a click of the parent element.
$('div:not(#notme)').on('click', function(e) {
// do something
});
Doesn't seem to work for some reason...
Use :has selector to selecting div element has specific child. In :has use :not.
$("div:has(a:not(#notme))").on("click", function(e) {
console.log("clicked");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
click
some content
</div>
<div>
<a href="#" >click2</a>
some content 2
</div>
You may try:
$('div').on('click', function(e) {
if($(e.target).attr("id") !== "notme") {
// do something
}
});
$('#notme').on('click', function(e) {
e.stopPropagation();
});

How to make the js function "onClick" work only on the container div?

I got a problem with the onClick function. I have to set
display: none;
in a css container div when the user clicks on it, but not when he clicks on the divs which are in the container.
<div id="msg_background" onclick="javascript:closemsg();">
<div id="new_msg_cont">
</div>
</div>
So, i don't want that clicking on "new_msg_cont" the function still works.
Here's the js:
function closemsg() {
document.getElementById('cont').style.height='';
document.getElementById('cont').style.overflow='';
document.getElementById('cont').style.position='';
document.getElementById('msg_background').style.display='none';
}
Thanks in advance.
This is called "bubbling" where the inner elements event 'bubbles' up to the parent element.
You can cancel this with event.stopPropagation():
Inline script
<div onclick="event.stopPropagation();" id="new_msg_cont"></div>
jsFiddle
External script
div onclick="javascript:cancel(event);" id="new_msg_cont"></div>
javascript:
function cancel(e)
{
e.stopPropagation();
}
jsFiddle
try something like this
javascript
function closemsg(event) {
if(event.target.id == "msg_background" ){
alert('you cliked me');
document.getElementById('cont').style.height='';
document.getElementById('cont').style.overflow='';
document.getElementById('cont').style.position='';
document.getElementById('msg_background').style.display='none';
}
}
html
<div id="msg_background" onclick="closemsg(event);">
div1
<div id="new_msg_cont">
div2
</div>
</div>
Try this approach:
<div id="msg_background" onclick="javascript:closemsg(this);">
<div id="new_msg_cont">
... your code ...
</div>
</div>
JS CODE
function closemsg(ele) {
if(ele.id === 'msg_background'){
document.getElementById('cont').style.height='';
document.getElementById('cont').style.overflow='';
document.getElementById('cont').style.position='';
document.getElementById('msg_background').style.display='none';
}
}
Inside your function check out if the event was fired by your parent div:
if (ev.target.id == "msg_background")
{
//execute the contents of the closemsg function
}
(ev is the event parameter)
Working Demo: http://jsfiddle.net/kVuKA/1/

Categories