JQuery Click for any child in any children except - javascript

I'm trying to bind an event for any child within any children in a div except for a specified child with the following:
$(document).ready(function(){
$("#holder").find('*').each(function(){
if($(this).context.nodeName !== "SPAN"){
$(this).click(function(){
window.console.log('s');
});
}
});
});
However, because the SPAN is within an element, the click event is still being called. Is there any way around this?
I have a demo on JSBin

Add an else condition to negate the click if it is a span
if($(this).context.nodeName !== "SPAN"){
$(this).click(function(){
window.console.log('s');
});
}
else {
$(this).click(function(e){
e.stopPropagation(); // negate click
});
}

Try this:
$(document).ready(function(){
$("#holder").find('*').on('click', function(e){
if($(e.target).is('span')){
return;
}else{
console.log('s');
}
});
});
Demo
Here we are finding all elements in #holder and binding the click event on every node except the span.

You put a click handler on all the p blocks. The span is in one of the p blocks. It gets the click event, but does nothing with it, it then bubbles up to the p.
You need to put a click handler on the span and then have it swallow the event. By calling event.stopPropagation().
http://api.jquery.com/event.stoppropagation/

What you encountered is known as Event Bubble. The children's event will be bubbled up to container when it is triggered, To read more about it . Please read What is event bubble?
What is the event.stopPropagation used for?
Hope it is helpful.

you can write this code to stop propagating the event to the next level when span is clicked:
$("#holder span").click(function(event,v){
event.stopPropagation();
});

Can you please try this:
<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-1.8.3.min.js"></script>
<meta charset="utf-8">
<script type="text/javascript">
$(document).ready(function(){
$("#holder").find('*').each(function(){
if($(this).context.nodeName != 'SPAN')
{
$(this).click(function(e){
window.console.log('s');
});
}
else
{
$(this).click(function(e){
e.stopPropagation();
});
}
});
});
</script>
<title>JS Bin</title>
</head>
<body>
<div id="holder">
<p>some text</p>
<p>might say</p>
<p>that being</p>
<p>in <span annid="1" style="font-weight:bold">space</span></p>
<p>is like</p>
<p>communicating with</p>
<p>dead pixels</p>
</div>
</body>
</html>
The problem in your code is beacuse of event propagation , the click event is propagating from the <p> event . This is beacuse , the span is inside the <p> element
Hope this helps..

You can use:
$("#holder").find("*:not(span)").on('click', function() { ... });

You can check the type of event source and skip the event handler code when event source is span.
Live Demo
$(document).ready(function(){
$("#holder *").click(function(event){
if(event.target.tagName == 'SPAN') return;
window.console.log('s');
});
});

Related

submit <button> doesn't work after an explode before it

I've looked through stackoverflow for days, and none of the stuff I worked. Anyways, after an explosion and appending a submit button to my document the button doesn't alert when clicked.
$(document).ready(function() {
alert('hi');
$("#a").click(function() {
$(".main, .topbar, button").toggle("explode");
$('body').delay(8100).append("<img src='picture.png'> <form > <input type='text'></form><button id='submit'>submit</button>");
});
$("#submit").click(function() {
alert('hi');
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id='a'>button</button>
Any suggestions?
You are binding click to submit before submit is even added to htmlDOM. To do it that way you have to first add submit to htmlDOM and then bind the event handler.
But, for such dynamic elements you can use jQuery on function and delegate from any parent element. It is not recommended to delegate from body, you can delegate from nearest parent that is present during document.ready event.
$(document).ready(function() {
alert('hi');
$("#a").click(function() {
$(".main, .topbar, button").toggle("explode");
$('body').delay(8100).append("<img src='picture.png'> <form > <input type='text'></form><button id='submit'>submit</button>");
});
$("body").on('click','#submit',function() {
alert('hi');
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id='a'>button</button>
I'm not 100% if I understood what you're trying to do there but check if this works:
<script>
$(document).ready(function () {
alert('hi')
$("#a").click(function () {
$(".main, .topbar, button").toggle("explode");
$('body').delay(8100).append("<img src='img.png'> <form > <input type='text'><button id='submit'>submit</button></form>");
});
$("#submit").click(function () {
alert('hi');
});
});
</script>
I assume you are inserting the button after page load, but calling the click handler before the element is on the page. Therefore jQuery can't find your element.
If you want to assign your click handler on page load, that's fine. Just assign your click handler to any parent element that is on the page when the page loads, like <body> and then using the jQuery .on() method to specify a descendant selector like so :
$('body').on('click', '#submit', function(){ alert('hi'); });

Click on parent, ignore its children [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
jQuery: click function exclude children.
I have two divs, something like this:
<div id="parent" style="width: 100%; height: 100%; background-color:red;" />
<h1>I'm the parent!</h1>
<div id="child" style="width: 300px; height: 200px; background-color:yellow;">
</h2>..and I'm the child!</h2>
</div>
</div>
Additionally, I have the following JavaScript code:
$(document).ready(function(){
$('#parent').click(function(){
alert('Parent was clicked');
});
});
The problem is, if I click on the child, the event is triggered. How can I limit this event to the parent only?
Edit: Just to clarify; I want this action to trigger when the user clicks anywhere in the red. As said in the comments; the h1 is not the parent. Tjirp's answer did the trick, and there's a lots of working variants of this solution in the answers.
This should work
$(document).ready(function() {
$('#parent').click(function(e) {
if (e.target == this) {
alert('Parent was clicked');
}
}
}
This way you won't have to bind anything to your childs. The click event is propagated to your click handler, and it checks if the target of the click event is indeed the element you added the event on.
Edit: I was right. this is not the most efficient way, Alessandro Minoccheri answer should be way faster. I updated my code with his.
Try this:
$('#parent').click(function(data, handler){
if (data.target == this) {
//Do Stuff (only element clicked, not children)
}
});
h1 is not the parent, div#parent is the parent.
clicking div#child triggers click on div#parent because of event bubbling.
this will prevent event bubbling:
$('#child').on("click", function() {
return false;
});
The easiest solution is to check that the element that originated the event (event.target) is the same as the element handling the click event handler (this):
$('#parent').click(function(event){
if(this === event.target) {
alert('Parent was clicked');
}
});
Here's a working jsFiddle.
You can try something like:
$(document).ready(function(){
$('#parent h1').click(function(){
alert('Parent was clicked');
});
});
$(document).ready(function(){
$('#parent').click(function(){
if($(this).not("#parent")) {
return false;
} else {
alert('Parent was clicked');
};
});
});

jquery selector help. Everything but the specified selector

I have the following function to open an overlay menu:
$('.context-switch').click(function() {
$(".context-switch-menu").toggle();
});
To hide the menu, I would like the user to be able to click on any area outside ".context-switch-menu"
I am trying with :not() but with no success..
$('body').click(function(e) {
if ($(e.target).hasClass('context-switch')) {
return;
}
$(".context-switch-menu").hide();
});
$('.context-switch').click(function() {
$(".context-switch-menu").toggle();
return false;
});
The reason this can be difficult is because of event bubbling.
You can try something like this:
$('.context-switch').click(function(e) {
e.stopPropagation();
$(".context-switch-menu").toggle();
});
$(".context-switch-menu").click(function(e){
e.stopPropagation();
});
$("body").click(function(e){
$(".context-switch-menu").hide();
});
The e.stopPropagation() prevents the click event from bubbling to the body handlers. Without it, any click to .context-switch or .context-switch-menu would also trigger the body event handler, which you don't want, as it would nullify the effect of the .context-switch click half the time. (ie, if the state is hidden, and then you click to show, the event would bubble and trigger the body handler that would then hide the .context-switch-menu again.)
Without testing, would something like this work?:
$('.context-switch').click(function() {
$(".context-switch-menu").show();
});
$(document).click(function() {
$(".context-switch-menu").hide();
});
Instead of using document, 'html' or 'body' may work as well.
$(document).on('click', function(e) {
if (e.target.className !='context-switch-menu') {
$(".context-switch-menu").hide();
}
});
Just an idea here, based on what what others have suggested in the past:
$(document).click(function(e){
//this should give you the clicked element's id attribute
var elem = $(e.target).attr('classname');
if(elem !== 'context-switch-menu'){
$('.context-switch-menu').slideUp('slow');
//or however you want to hide it
}
});
try this, we don't want to call a function when you clicked on the element itself, and not when we click inside the element. That's why we need 2 checks.
You want to use e.target which is the element you clicked.
$("html").click(function(e){
if( !$(e.target).is(".context-switch-menu") &&
$(e.target).closest(".context-switch-menu").length == 0
)
{
alert("CLICKED OUTSIDE");
}
});
Live fiddle: http://jsfiddle.net/Xc25K/1/

jquery click event ONLY when wrapped element clicked

I have the following html:
<ul class="treeList2">
<li class="topLevel marked checked"><div class="tlWrap clearfix"><input type="checkbox" checked="checked" class="checkbox"><strong>Level name here blah blah <span>(3)</span></strong></div></li>
...
<script type="text/javascript">
/*<![CDATA[*/
$(function(){
$('.treeList2 li.topLevel .tlWrap').click(function(){
alert(this);
});
});
/*]]>*/
</script>
The problem is that this fires when I click the checkbox (which i don't want). I Only want to alert(this) when the 'div' is clicked (I do this so that I can change the div background).
thanks
You can prevent the click event on the checkbox from bubbling up to the parent like this:
$('.checkbox').click(function(e){
e.stopPropagation();
});
You can try it here.
See http://api.jquery.com/event.stopPropagation/
check if the target is not input element and then only alert.
$(function(){
$('.treeList2 li.topLevel .tlWrap').click(function(e){
if (e.target.nodeName !== 'INPUT') {
alert(this);
}
});
});
Looking at it, you need to call the parent?
$('.treeList2 li.topLevel .tlWrap').parent().click( ...
Although if you want to change the parent div when the checkbox is clicked:
$('.treeList2 li.topLevel .tlWrap').click(function(){
$(this).parent().css('background-color','red');
});
[edit]
Sorry, I mis-read the html.
There's a 'not' function that you can exclude elements with:
$('.treeList2 li.topLevel .tlWrap').not('input').click( ...
This will fire when anything in the div is clicked on, except the checkbox.
You can check whether the element that triggered the event (e.target) has a class of tlWrap.
$(function(){
$('.treeList2 li.topLevel .tlWrap').click(function(e){
if($(e.target).hasClass("tlWrap")) {
alert(this);
}
});
});
See a working demo.

jQuery: Make div clickable to check nested checkbox

<script language="javascript" type="text/javascript">
$(document).ready(function() {
$('#myDiv').click(function() {
var checkBox = $(this).children("input[type='checkbox']");
checkBox.attr('checked', !checkBox.attr('checked'))
});
});
</script>
<div id="myDiv" style="background-color:red;height:50px;width:50px;">
<input type="checkbox" />
</div>
I'm having problems making the div clickable so that it checks the nested checkbox. I would like to make it so this function works only if the mouse is not hovering the checkbox. How can I do this? Something like this:
if (!checkBox.isHover)
checkBox.attr('checked', !checkBox.attr('checked'))
Note this question has been asked here before, but the answers did not seem to solve the problem. The wrapped label solution does not work properly in FireFox. Thank you.
Try this:
$('#myDiv').click(function(evt) {
if (evt.target.type !== 'checkbox') {
var $checkbox = $(":checkbox", this);
$checkbox.attr('checked', !$checkbox.attr('checked'));
evt.stopPropagation();
return false;
}
});
Untested, but I just successfully used something along these lines on a project.
<script language="javascript" type="text/javascript">
$(document).ready(function() {
$('#myDiv').click(function(e) {
e.stopPropagation();
var checkBox = $(this).children("input[type='checkbox']");
checkBox.attr('checked', !checkBox.attr('checked'))
});
});
</script>
The issue is that if you actually click on the checkbox it will still trigger the click event on the div - event bubbling. You can add a click event to the checkbox which stops the bubbling, this way only the div binds to the event.

Categories