Disabling a click event from the child of a parent div - javascript

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>

Related

JavaScript loop over clickable elements on click event, and skip the specific clicked element

<div>
<div class="clickable">1</div>
<div class="clickable">2</div>
<div class="clickable">3</div>
<div class="clickable">4</div>
</div>
Upon clicking one of the 'clickable' elements i want to add a new class to all elements with 'clickable' class except the one that has been clicked.
$('.clickable').on('click', function (e) {
$('.clickable').each(function () {
$(this).addClass('new-class')
});
})
How, inside the loop, can i skip the specific element that was clicked?
$('.clickable').on('click', function() {
$(this).removeClass('new-class').siblings().addClass('new-class');
});
This is the simplest to control and read
You do not need the each
$('.clickable').on('click', function(e) {
$('.clickable').addClass('new-class');
$(this).removeClass('new-class');
})
.new-class {
color: red
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<div class="clickable">1</div>
<div class="clickable">2</div>
<div class="clickable">3</div>
<div class="clickable">4</div>
</div>
If they are surely all in the same container, you can use siblings.
To chain you MUST remove before adding
$('.clickable').on('click', function(e) {
$(this)
.removeClass('new-class') // still necessary for the second click of another element
.siblings().addClass('new-class');
})
.new-class {
color: red
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<div class="clickable">1</div>
<div class="clickable">2</div>
<div class="clickable">3</div>
<div class="clickable">4</div>
</div>
There is a not method in jQuery so the simplest thing you can do in my opinion is with the help of not method like below:
$('.clickable').on('click', function (e) {
$('.clickable').not(this).addClass('new-class');
})

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

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');
});

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 select the clicked child element within a parent element in Jquery?

I have a parent div within which elements are added dynamically. I want to find out the class of the element which was clicked, if none of the child element was clicked but parent was clicked then I would like to get the class of parent element.
$(document).ready(function() {
$('.parent').on('click', function(event) {
// event.stopPropagation();
alert($(this).attr('class'));
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div class='parent'>Parent//clicking here should alert parent
<ol>
<li class='type1'>NEW</li>//clicking on this should alert type 1
</ol>
</div>
try this:
$(document).ready(function() {
$('.parent').on('click', function(event) {
// event.stopPropagation();
alert($(event.target).attr('class'));
});
});
this will get the target tag of the clicked position.
see the DEMO

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