How to fire child div event without firing parent div event? - javascript

I am trying to fire child div event but it seems that instead of child div , it is the parent div's click event that is getting fired. I tried using stopPropagation in child event but it doesnt seem to work.
$(document).ready(function() {
var lot = '<div class="divlot">This is a lot!</div>'
var lineitem = '<div class="divlineitem">This is a lineitem!</div>'
$("#container").on("click", function() {
$("#container").append(lot);
});
$(".divlot").on("click", function(e) {
e.stopPropagation();
alert($(this).attr("class"));
$(this).append(lineitem);
});
});
#container {
background-color: grey;
}
.divlot {
background-color: red;
padding-left: 20px;
}
.divlineitem {
background-color: blue;
padding-left: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="container">Container</div>

Event handlers are bound only to the currently selected elements; they must exist on the page at the time your code makes the event binding call.
As of now, your are using direct event handler binding for divlot which doesn't exist in the page thus neither event handler work nor e.stopPropagation()
Since you are adding event dynamically you need to use Event Delegation using .on() delegated-events approach.
Bind event using
$("#container").on("click", ".divlot", function(e) {
e.stopPropagation();
alert($(this).attr("class"));
$(this).append(lineitem);
});
$(document).ready(function() {
var lot = '<div class="divlot">This is a lot!</div>'
var lineitem = '<div class="divlineitem">This is a lineitem!</div>'
$("#container").on("click", function() {
$("#container").append(lot);
});
$("#container").on("click", ".divlot", function(e) {
e.stopPropagation();
alert($(this).attr("class"));
$(this).append(lineitem);
});
});
#container {
background-color: grey;
}
.divlot {
background-color: red;
padding-left: 20px;
}
.divlineitem {
background-color: blue;
padding-left: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="container">Container</div>

You are creating the child divs dynamically. So you should use event delegation for properly binding the events.
$("#container").on("click",".divlot", function(e) {
e.stopPropagation();
alert($(this).attr("class"));
$(this).append(lineitem);
});
Fiddle

Related

"input" inside a "div": how to register an "onclick" event listener for the "div", but not for the "input" [duplicate]

This question already has answers here:
How to stop onclick event in div from propagating to the document?
(7 answers)
Closed 5 years ago.
I have a div element, and inside of it an input element. I want to register an event listener when click on the div. It works ok, but the problem is: the "click" on the input is also detected, and I don't want to.
document.getElementById("foo").addEventListener('click', function(event) {
alert();
event.stopPropagation();
})
div {
width: 300px;
height: 300px;
background-color: red;
}
<div id="foo">
<input>
</div>
You are using event.stopPropagation(); in the wrong event that is why it does not work. stopPropagation prevents events from bubbling up so you need to use it in child event.
Try this.
document.getElementById("foo").addEventListener('click', function(event) {
if(event.target === event.currentTarget) {
alert();
}
})
div {
width: 300px;
height: 300px;
background-color: red;
}
<div id="foo">
<input>
</div>
stopPropagation prevents events from bubbling up. Read more about event bubbling here. So you need to place the stopPropagation on the button
document.getElementById("bar")
.addEventListener('click', function(event) {
event.stopPropagation();
})
document.getElementById("foo")
.addEventListener('click', function(event) {
alert();
})
div {
width: 300px;
height: 300px;
background-color: red;
}
<div id="foo">
<input id="bar">
</div>
You can now observe that the alert is not fired when you click on the input.

:not selector with <a> in <div>

I have an a in a div and want to change the window location on click of div.
<div class="div-class">
</div>
$(document).on("click", ".div-class:not(.a-class, .a-class-2)", function() {
window.location = "/somewhere-else";
}
When clicking on either a, a new tab opens and the current window changes location. I want it to be that if you click on any a it will open a new tab, if you click on the containing div it will change window location.
To achieve this you can hook to the a elements directly and call stopPropagation() on the event passed to the handler. This will stop the event bubbling to the div and will ensure only the new tab is opened.
Similarly, you can hook to the click event of the div element to call window.location.assign() to change the page URL. Try this:
$(document).on("click", ".a-class, .a-class-2", function(e) {
e.stopPropagation();
console.log('a clicked');
}).on('click', '.div-class', function() {
console.log('div clicked');
// location.assign("/somewhere-else"); // commented out to stop breaking the snippet
});
/* this is only to make the hit areas more obvious in the snippet */
a { border: 1px solid #C00; }
div { border: 1px solid #0C0; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="div-class">
a-class
a-class-2
</div>
Rory's answer works, but I don't think it needs two handlers or to call stopPropagation (which can be harmful). You can filter on the event target using jQuery.is
$(document).on("click", ".div-class", function(event) {
if (!$(event.target).is(".a-class, .a-class-2")) {
console.log("going /somewhere-else");
}
// You could also do
if( $(event.target).is(".div-class") ) {
console.log("going /somewhere-else v2");
}
});
a { background-color: #eee; }
div { border: 1px solid #0C0; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="div-class">
link 1
link 2
</div>

jQuery checkbox (under a ul > li) check event

I have this code to handle checkbox check event:
<html>
<head>
<style>
#leftPane {
width: 200px;
height: 500px;
border: 1px solid;
float: left;
}
#rightPane {
height: 500px;
width: 600px;
border: 1px solid;
border-left: 0px;
float: left;
}
#addTo {
border: 1px solid;
}
#addTo input {
border: none;
}
#showList ul{
list-style: none;
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
<script>
$(document).ready(function(){
$('#todoItem').keypress(function(e){
if (e.which ==13) {
var item = $('#todoItem').val();
var chkbox = "<input type='checkbox' name='"+item+"'>"
$("#showList ul").append("<li>"+chkbox+""+item+"</li>");
}
})
$("#showList li ul input[type=checkbox]").change(function(){
var $this = $(this);
alert("tell me");
/*if ($this.is(':checked')) {
$(this).parent().remove();
}*/
})
})
</script>
</head>
<body>
<div id="leftPane">
<ul>
<li>Shopping List</li>
<li>Movie List`</li>
<ul>
</div>
<div id="rightPane">
<p>Let's add some todo</p>
<div id="addTo">
<input id="todoItem" type="text" placeholder="Add a todo"></input>
</div>
<div id="showList">
<ul>
</ul>
</div>
</div>
</body>
When I am clicking the checkbox the event handler
( $("#showList li ul input[type=checkbox]").change(function(){ )
is not fired (no alert appears). If I select
$('#showList > ul").click (...)
Then the event handler fires but that means clicking anywhere within the ul not necessarily for a checkbox.
I was following these links to develop the above code:
jQuery checkbox checked state changed event
Use JQuery to check a checkbox in a parent list-item?
The jsfiddle page: https://jsfiddle.net/
Any help would be much appreciated.
Thanks
my solution
$(document).on('change', "#showList ul li input[type=checkbox]", function(){
var $this = $(this);
alert("tell me");
/*if ($this.is(':checked')) {
$(this).parent().remove();
}*/
})
Problems in your solution:
you have written li before ul; you are expecting li to enclose ul tag, which is not the case rather opposite
You are dynamically adding checkbox in runtime, so normal event handler wont work like .change. You need to implement event delegation technique to work in your case.
in this code $('#showList > ul").click (...) you know what is your mistake
The majority of browser events bubble, or propagate, from the deepest,
innermost element (the event target) in the document. Delegated events
have the advantage that they can process events from descendant
elements that are added to the document at a later time.
By picking an element that is guaranteed to be present at the time the delegated event handler is attached, you can use delegated events to avoid the need to frequently attach and remove event handlers. document object is guranteed to be present all the time. So, document object will delegate the change event to element matching the selector #showList ul li input[type=checkbox].
When you register the onChange event, you do it for the matching elements currently in the page. New elements will not have that event listener registered to them.
To solve the problem, you could either add the event when creating the item itself, or you could use event delegation.
Taking advantage of events bubbling up the DOM and event delegation, register the event on a static parent (i.e #showlist), like so:
$('#showlist').on('change', 'input[type=checkbox]', function(event) {
// your handler here
});
What'll happen is that when you click on the desired element, the event will bubble up until it reaches an element that has a registered handler for its type. You'll notice that event.target is the actual event target, not the element handling the event.
Aside from that, your selector should be #showlist ul li input[type='checkbox'], not #showlist li ul input[type='checkbox'].
Let's follow KISS method.
<script>
$(document).ready(function () {
$('#todoItem').change(function () {
$('<li />').append(
$('<input type="checkbox" name="' + this.value + '" id="' + this.value + '">')
.click(function () {
var $this = this;
alert('tell me ' + $this.name);
})//click
)//append
.append('<label for="' + this.value + '">' + this.value + '</label>')
.appendTo($("#showList ul"));
});
});
</script>
Is it what you want?

How to prevent click event from outer div if inner div is clicked

I have 2 divs with a js click event. One div is located in the other one.
But I dont want the outer div's click event to be triggered if I click the inner one. How can I prevent that?
By default, event handling starts at the lowest level of the DOM where you have defined a handler to handle the target event. Assuming you have defined event listeners higher in the parent chain to handle the same event, you will need to stop the propagation of the event if you do not wish for the event to be handled beyond the layer you intend for it to be handled in:
e.stopPropagation();
See what happens when you remove that line in the example below:
document.querySelector('.inner').addEventListener('click', function(e) {
alert('inner div clicked!');
e.stopPropagation();
});
document.querySelector('.outer').addEventListener('click', function() {
alert('outer div clicked!');
});
.outer {
width: 200px;
height: 200px;
background: blue;
}
.inner {
width: 100px;
height: 100px;
background: green;
}
<div class='outer'>
Outer
<div class='inner'>
Inner
</div>
</div>
Use event.stopPropagation();
Like this
document.getElementById("#seconddiv").addEventListener("click", function($event){
$event.stopPropagation();
});
Use event.stopPropagation:
document.getElementById('inner').addEventListener('click', function (event){
event.stopPropagation();
console.log ('Inner div clicked!');
});
https://jsfiddle.net/4L87qLte/

Get id parent element

I have function that start working when I click on parent and get parent id ( tmp ), but when I click on child my function works too but return undefind. How to get parent id doesn't matter on what I click child or parent or other elemnts in parent div ?
<div class="parent" id="tmp">
<div class="child"></div>
</div>
.parent {
width: 100px;
height: 100px;
}
.child {
width: 50px;
height: 50px;
}
'click .parent': function(e){
console.log($(e.target).attr("id")); // from MeteorJS framework , but same sense
}
In your click handler you should use this to refer to the element that is handling the event:
'click .parent': function(){
console.log(this.id);
}
By using e.target you're targeting the element which originated the event - which in the cases you describe would be the .child element which has no id attribute.
If you are unable to use the this keyword due to restrictions imposed by Meteor, you could instead use the currentTarget property on the event, as it should have the same effect:
'click .parent': function(e){
console.log(e.currentTarget.id); // or $(e.currentTarget).prop('id')
}
try:
$('.parent').click(function(){
console.log($(this).attr('id'));
//console.log($(this)[0].id)
});
or
$('.parent').click(function(e){
console.log(e.currentTarget.id);
});
or
$('.parent').click(function(e){
console.log(e.delegateTarget.id);
});
Is this what you want?
$(function() {
$('div').click(function(e) {
var id = $(e.target).parent().attr('id');
if (typeof id === 'undefined') {
//return current element as this is a parent
console.log($(e.target).attr('id'));
} else {
//return parent's id
console.log(id);
}
});
});
.parent {
width:100px;
height:100px;
background: red;
}
.child {
width:50px;
height:50px;
background: black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="parent" id="tmp">
<div class="child">
</div>
</div>

Categories

Resources