I have a Div inside a Div, I am trying to keep different onClick handlers for both the div, but when Clicked on inner div, Both the event Handlers executes and the one of inner div first excuted and then Oter div,
I dont want to actually execute both.
Code:
<div style="width:100%;height:200px;background-color:yellow" onclick="alert('Div A');return false;">
This is Div A
<div style="width:20%;height:100px;background-color:red" onclick="alert('Div B');return false;">
This is Div B
</div>
</div>
Jsfiddle: fiddle
Just add event.stopPropagation(); inside the onclick of the inside <div>.
Like this :
<div style="width:100%;height:200px;background-color:yellow" onclick="alert('Div A');return false;">
This is Div A
<div style="width:20%;height:100px;background-color:red" onclick="event.stopPropagation(); alert('Div B');return false;">
This is Div B
</div>
</div>
<div style="width:100%;height:200px;background-color:yellow" onclick=" if (!e) var e = window.event;
e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();alert('Div A');return false;">This is Div A
<div style="width:20%;height:100px;background-color:red" onclick=" if (!e) var e = window.event;
e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();alert('Div B');return false;"> This is Div B</div>
</div>
add this code in your onclick function
if (!e) var e = window.event;
e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();
fiddle
read more about event capturing and event bubbling here and here
$(document).ready(function () {
$(".yellow").click(function () {
alert("Div A");
});
$(".red").click(function (objEvent) {
objEvent.stopPropagation();
alert("Div B");
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div style="width:100%;height:200px;background-color:yellow" class="yellow">This is Div A
<div style="width:20%;height:100px;background-color:red" class="red"> This is Div B</div>
</div>
First: don't use inline click handlers. It's unsafe and inline handlers spawn a new js-interpreter on every activation;
Second: use some mechanism to identify your divs (for example data-id or just an id);
Third: using event delegation, you'll need only one handler and you don't have to worry about event capturing/bubbling.
For example:
// append handler to click for anything within the body of your document
document.body.addEventListener('click', reportFromDiv);
// one handler for divs with data-id attribute
function reportFromDiv(evt) {
var from = evt.target || evt.srcElement;
// do nothing for elements without the data-id attribute
if (!from.getAttribute('data-id')) {
return true;
}
return report(from.getAttribute('data-id'));
}
function report(str) {
document.querySelector('#report').textContent += 'clicked: ' + str + '\n';
}
<div style="width:100%;height:200px;background-color:yellow" data-id="divA">
This is Div A
<div style="width:20%;height:100px;background-color:red" data-id="divB">
This is Div B
</div>
</div>
<pre id="report"></pre>
Related
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>
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');
});
I have two div's that I open that kinda belong together, but for programming reasons can't be connected. I simplified the code here because it's a lot of code. This is the basic.
<div id="container">
<div id="div1">
<div> when I am clicked I will open div2 </div>
</div>
<div id="div2">
<div> I can be clicked and all the div's stay open </div>
</div>
</div>
And this is the connected JavaScript
$(document).mouseup(function (e) {
var container = $("#div1");
if (!container.is(e.target) && container.has(e.target).length === 0) {
container.hide();
}
});
$(document).mouseup(function (e) {
var container = $("#div2");
if (!container.is(e.target) && container.has(e.target).length === 0) {
container.hide();
}
});
Now what I would like to do is when I click outside div1 it should close div1.
When I click on div1 it opens div2.
Currently with the above when I click in div2 it closes div1, because it is not a child of div1. So it should keep div2 opened.
And when I click outside div1 or div2 it should close the two div's.
How can I combine the two JavaScript codes to get the explained behaviour?
Summary of what I try to accomplish:
Click on the div inside div1 will open div2
Click outside div1 or div2 will close both div1 and div2.
In case the div inside div1 is not clicked and one clicks outside
div1, it should close div1.
Using closest() and a common class makes this simpler
$(document).mouseup(function(e) {
!$(e.target).closest('.content').length && $('.content').hide();
});
$('#div1').click(function() {
$('#div2').show();
})
#div2{display:none}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<div id="div1" class="content">
<div> when i am clicked i will open div2 </div>
</div>
<div id="div2" class="content">
<div> i can be clicked and all the div's stay open </div>
</div>
</div>
Pretty theorical....
But requirements are quite clear. I would do it using .stopPropagation().
e.target is the element clicked. If it is a child of an element having a "concurring handler" on the same event, the handler from the parent will execute. Except if you stop the propagation, which you should look at here.
Having a handler on a top-most parent that say "hide all", will will overcome the handler of the child saying somthing else. So in this case... From the child, you do not want the click (or mouseup... or whatever the event) to propagate to the top parent.
In short: .stopPropagation() will keep the event on the releveant element and you can "not care about" any concurring handler from the parents.
$("#div1").on("click", function(e){
e.stopPropagation();
whoAmI(e);
$("#div2").show();
});
$("#div2").on("click", function(e){
e.stopPropagation();
whoAmI(e);
console.log("I was clicked and #div1 stayed opened.");
});
$("#container").on("click",function(e){
$("#div1,#div2").hide();
whoAmI(e);
});
function whoAmI(e){
console.clear();
console.log( "I'm "+e.target.tagName+" "+((e.target.id=='')? "child" : e.target.id) );
}
#container{
height:1000px;
}
#div1, #div2{
border:1px solid red;
padding:2em;
margin:3em;
}
#div2{
display:none;
}
#container>div>div{
border:1px solid blue;
padding:0.5em;
margin:1em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<div id="div1">
<div> When I am clicked I will open div2 </div>
<div> I also do the same. </div>
</div>
<div id="div2">
<div> I can be clicked and all the div's stay open </div>
<div> I also do the same. </div>
<div> And me too! </div>
</div>
</div>
I suggest this the code written with jQuery:
$(document).on('click', function (e) {
if ( e.currentTarget.id == 'div1' ) {
$("#div2").show();
} else if ( e.currentTarget.id == 'div2' ) {
$("#div1").hide();
} else {
$("#div1").hide();
$("#div2").hide();
}
return false;
});
or in plain Javascript:
function handleClicks(e) {
var first = document.getElementById('div1'),
second = document.getElementById('div2');
if ( e.currentTarget.id == 'div1' ) {
second.style.display = 'block';
} else if ( e.currentTarget.id == 'div2' ) {
first.style.display = 'none';
} else {
first.style.display = 'none';
second.style.display = 'none';
}
}
document.body.addEventListener('click', handleClicks, false);
Also check the if-else statements there.
I have one drop target div which have some nested div's, i add dragover event to parent div and add 'drag-allow' attrib to nested divs. I want to add custom event fires when mouse enters or leave any child div.
<div id="container">
<div id="page1" drag-allow >
Page #1
</div>
<div id="page2" drag-allow>
Page #2
</div>
<div id="page3" drag-allow>
Page #3
</div>
var ground = document.getElementById('container');
...
ground.addEventListener('dragover', function(e){
evt.preventDefault();
evt.stopPropagation();
evt.target.id; // custom event will fire based on child div's id
}, false);
You need to add two more events like
ground.addEventListener('dragenter', function(e){
if(e.target.nodeType == Node.ELEMENT_NODE && e.target.hasAttribute('drag-allow')){
// this will check drop area is div and must have attribute drag-allow
console.log(e.target);
}
}, false);
ground.addEventListener('dragleave', function(e){
// on leave event fires on every nested div like above event
}, false);
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/