I am trying to do a simple hide & show of a DOM on click event.I am showing the
loadMenu container on clicking of span#dwnTrigger.
But my problem is even when I am clicking on the div#loadMenu , this div#loadMenu is getting hidden. I am not sure how can this happen as the event is attached to span#dwnTrigger.
<span id="dwnTrigger" class="dwnPrint" aria-label="Download" ng-controller="dwnCtrl" > Start
<div class="dwnCtrl menuContainer ng-hide" id="loadMenu">
//rest of DOM
</div>
</span>
Controller
abc.controller('dwnCtrl',['$scope',function($scope){
$scope.$element = $("#dwnTrigger");
($scope.$element).on('click',function() {
if ($("#loadMenu").hasClass('ng-hide')) {
$("#loadMenu").removeClass('ng-hide').addClass('ng-show');
//rest of code
}
else if ($("#loadMenu").hasClass('ng-show')) {
$("#loadMenu").removeClass('ng-show').addClass('ng-hide')
}
})
}]);
This is called event propagation/bubbling. When you click on an element the event propagates through all it's parents. So as the div#loadMenu is a child of span#dwnTrigger the click on div#loadMenu propagates to span#dwnTrigger and triggers it's event handler.
You can use 'event.stopPropagation()' to prevent this. You have to bind an click event handler to div#loadMenu, capture the event and stop propagation.
$('div#loadMenu').click(function(event) {
event.stopPropagation();
});
For more on event.stopPropagation() https://api.jquery.com/event.stoppropagation/ and https://developer.mozilla.org/en-US/docs/Web/API/Event/stopPropagation
Alternatively you can check which element dispatched the event by event.target and act based on that. For example your click handler can be like following
($scope.$element).on('click',function(event) {
if($(event.target).closest('#loadMenu').length > 0) {
return;
}
if ($("#loadMenu").hasClass('ng-hide')) {
$("#loadMenu").removeClass('ng-hide').addClass('ng-show');
//rest of code
}
else if ($("#loadMenu").hasClass('ng-show')) {
$("#loadMenu").removeClass('ng-show').addClass('ng-hide')
}
})
For more on event.target https://developer.mozilla.org/en-US/docs/Web/API/Event/target
Related
I'm inserting this html dynamically:
<div class="outerDiv">
<div class="innerDivLeft"></div>
<div class="innerDivRight"></div>
</div>```
And I want to add an event listener to the outerDiv.
This is what I've tried:
document.body.addEventListener("click", function(e) {
if (e.target.classList = "outerDiv") {
console.log("e.target")
}
});
My problem is that when I click inside the "outerDiv", often e.target === "innerDivLeft" or "innerDivRight" and that means that the event is not firing. How can I make sure that e.target === "outerDiv"
How can I stop the trigger of the outer div event when I click the inner element?
And all the events are bound to $(document.body),so i think i should not stop event stopPropagation.
When I click $(".logLi"), I just want to trigger the inner ele event.
What is wrong with my code and how can i solve the problem?
here is my code
<div class="clomn">
<div class="logLi">
<span>aaaaaaa</span><em>bbbbbb</em>
</div>
</div>
$(document.body).on("click", ".clomn .logLi", function(e) {
console.log("inner");
})
$(document.body).on("click", ".clomn", function(e) {
console.log("outer")
})
You can prevent the propagation of the event, but I prefer to check in the parent click handler to check whether it has occurred in a child element then discard it
$(document.body).on("click", ".colmn .logLi", function(e) {
console.log("inner: 2");
})
$(document.body).on("click", ".colmn", function(e) {
if ($(e.target).closest('.colmn .logLi').length == 0) {
console.log("outer");
}
})
$(".colmn .logLi").click(function() {
console.log('inner: 1')
})
.colmn {
border: 1px solid red;
padding: 15px;
}
.logLi {
border: 1px solid green;
padding: 15px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="colmn">
<div class="logLi">
<span>aaaaaaa</span><em>bbbbbb</em>
</div>
</div>
find by parent class name of e.target ,if you clicked inside .logLi your parent class will be .logLi . Do not need two click functions .
$(document.body).on("click", ".clomn .logLi", function(e) {
if($(e.target).parent().attr("class") == "logLi"){
console.log("inner");
}
else{
console.log("outer");
}
});
I'm on a React.js app but I use dom properties here, and I solved it using e.target.id and e.target.localName
I have an outer div with a certain id, and an inner div (or actually button inside it and a click handler for the div and another for the button), so I just check the ids via e.target.id. (or whether it was the button clicked or the div via e.target.localName).
If you have a button inside a div you can use e.target.localName, for example inside your click handler.
What the react component returns:
<div id='outerDiv' onClick={outerDivHandler}>
<div id='innerDiv' onClick={innerDivHandler}>
...
</div>
</div>
The handler functions:
function outerDivHandler(e) {
if (e.target.id !=== 'innerDiv') {
// stuff for your outer div exclusively here //
}
}
Like that or any other combination you want to handle your divs (or any other nested elements' handlers for that matter) click events.
The events of course will still trigger, but if you check the divs' id on the handler or e.target.localNamee to check whether it was a button click or a div click you are the one that controls whether the actions will happen.
I'm using a hidden input to keybind my app with it but without triggering events when i write on other input-fields
-clicks on element {
-hide element
-creates an input text-field(to edit the element)
-focus the input
- on blur or submit changes the element and remove the input
}
but if you add this new event :
- click anywhere in the container {
-focus the hidden app input (so it can use keybinding)
}
when user clicks on the element it ends firing the blur event without letting the user edit it first because its activating the second block event.
so it's either skipping the focus part of the first block
or the focus of the second block is activating after the focus on the first one
I'm maybe using the wrong approach to solving it
but I don't know why it's behaving that way.
actual code:
$("#hiddenInput").focus()
var elem = $("#nameClip");
function evenConditional(id) {
if ($(id).val() !== "") {
elem.text($(id).val())
storedObj.name = $(id).val();
}
$(id).parent().remove();
elem.show();
}
$("#name").on("click", function() {
elem.hide();
elem.after(
$("<form/>").append(
$("<input/>").addClass("rename")
)
);
$(".rename").focus();
});
$(".rename").blur(function() {
evenConditional(this);
});
$(".rename").closest("form").on("submit", function(e) {
e.preventDefault();
evenConditional(this);
});
/// regaining focus on click
$(".container").on("click", function(e) {
$("#hiddenInput").focus()
});
css:
#hiddenInput {
position:absolute;
top: -2000;
}
Since the #name element is in the .container element, when you click on it, the click event bubbles up to the container, causing the click-event handler for the container to get executed.
One way to fix this would be to stop the click event from bubbling:
$("#name").on("click", function(e) {
e.stopPropagation();
There can be side effects from doing that though. Particularly, there may be other event handlers that will not get executed because of that. Such as handlers that close opened menus.
The other option would be to place conditional logic in the click handler for the container so it does not execute if the click originated with the name element.
$(".container").on("click", function(e) {
var nameElement = $("#name")[0];
if ((e.target != nameElement) and !$.contains(nameElement , e.target)) {
$("#hiddenInput").focus();
}
});
Sorry the title maybe a bit bogus. but here its, imagine I have 3 divs like this :
<div id="1" class="clickable">
<div id="2" class="some random thing">
<div id="3" class="clickable">
</div>
</div>
</div>
now imagine I have
$('.clickable').on('click',function(){blahblah});
I want them both to be clickable but not at the same time.
When I click the inside clickable class div (where the id is 3) both the the inner one and the parent one will trigger the blahblah. I know I can use something like
$('.clickable').on('click',function(e){e.stopPropagation(); blahblah});
but the problem is even if I do that, clicking the middle child (the one with the id of 2) will trigger the blah blah on the parent as well.
Is there anyway to stop that? For example if this div and only this div not parent not child, only this div has the class of clickable, be clickable.
Thank you very much.
event.stopPropogation stops the event from bubbling up the event chain, but this conflicts when you click on the middle div. I am posting the javascript code that you can refer to. Inside the click event listener, the conditional if block checks whether the event was triggered in that particular div element, hence stopping the event bubbling.
document.getElementById("outer").addEventListener('click', function(event) {
if (event.target !== this) {
return;
}
alert("You clicked outer div!");
});
document.getElementById("middle").addEventListener('click', function(event) {
if (event.target !== this) {
return;
}
alert("You clicked middle div!");
});
document.getElementById("inner").addEventListener('click', function(event) {
alert("You clicked inner div!");
});
You can also refer to this fiddle : https://jsfiddle.net/9fskuunr/3/
You might want to do something like this
$(".clickable").click(function(e){
e.stopPropagation();
var id = $(e.target).attr('id');
alert(id + ' is clicked');
}).children(':not(.clickable)').click(function(e) {
return false;
});
See the JSFiddle here: https://jsfiddle.net/3h4yvfv4/1/
One approach you might want to consider is to use event delegation. That way you only assign one event handler, rather than multiple event handlers for every .clickable element, which may give you a performance benefit depending on how many .clickable elements you have on a given page.
The code using event delegation looks something like this:
$(document).on('click', function(e) {
var target = $(e.target),
isClickable,
closestClickable,
isNestedInClickable;
isClickable = target.hasClass('clickable');
if (isClickable) {
handleClick(e);
} else {
closestClickable = target.closest('.clickable');
isNestedInClickable = !!closestClickable;
}
if (isClickable || isNestedInClickable) {
e.stopPropagation();
}
});
function handleClick(e) {
console.log(e.target.id + ' clicked');
}
JSFiddle: https://jsfiddle.net/sytkvgng/2/
I got a double event to manage. The two events are both "click" and they're handled with jquery. The html is the following:
<div class="siteMap" style="width:23%;">
<h5>Divisione Anticontraffazione</h5>
<span class="menufooter">
<span class="link1">Introduzione</span><br>
<span class="link2">Filosofia</span><br>
<span class="link3">Negozio online</span></span><br>
</div>
Then i have my click events which fires inside the menufooter span and inside every single link span. The code is like this:
$(document).ready(function() {
$('span.menufooter').click(function() {
//my code here
});
$("span.link1").click(function() {
//my code here
});
});
I need an event capturing action, the click on the span menufooter has to fire the event before the click on the span link1 fires. At this point, none of the two events is firing. Any hint?
How about only fire event on .menufooter
$(document).ready(function() {
$('span.menufooter').click(function(e) {
//my code here 1
// Capture Event Propagation
if ( $("span .link1").find(e.target).length>0 ){
//my code here 2
};
});
});
http://jsfiddle.net/9QLtG/
You could prevent the click from bubbling, and then trigger the click on the parent element so whatever is in that handler executes first (unless it's async)
$(document).ready(function () {
$('.menufooter').click(function () {
// fires before ....
});
$("span.link1").click(function (e) {
e.stopPropagation();
$('.menufooter').trigger('click');
// .... this fires, as it's triggered above
});
});
FIDDLE
I would have 1 click listener that listens to the wrapper. You can check the event's target to see if they actually clicked on a link and run code accordingly.
For example:
$(document).ready(function() {
$('.container').click(function(e) {
// Perform action when they clicked in the main wrapper,
// regardless of whether or not it was a link.
console.log("I clicked in the wrapper...");
if ($(e.target).hasClass('link')) {
// Perform action if they clicked on a link.
console.log("...but more specifically, on a link.");
}
});
});
Here's a fiddle that demonstrates this: http://jsfiddle.net/WaYFr/
Try this event.stopPropagation();
$("span.link1").click(function(event) {
event.stopPropagation();
...
});