I want to run a javascript function everytime a user clicks anywhere on the page (div "maincontent") EXCEPT on any of the two buttons (div "btnNew" and "btnRegister"). How can I do that? My first approach doesn't work.
<div id="mainContent" class="content" onclick="hidePopUps(document.this)">
[...]
<div id="btnNew" class="btn-welcome" onclick="showRegister()">New user</div>
<div id="btnRegister" class="btn-welcome" onclick="showLogin()">Existing user</div>
[...]
</div>
function hidePopUps(element) {
if(element == $("#mainContent")) {
hideLogin();
hideRegister();
}
}
You can do this with jQuery and the :not() selector:
$(":not(body):not(html):not(#btnNew):not(#btnRegister)").click(function() {
// the :not(body) and :not(html) are to prevent it
// from setting off additional event listeners because
// everything is on top of the html and body tags
// ... handler here
});
This should select everything but those two buttons.
See a working example at JSFiddle.net.
To make things work the way you want I would:
change your onlick events:
a. you don't need hidePopUps(document.this), just hidePopUps(this)
b. in showRegister() and showLogin() put 'event' variable inside brackets to pass it to these functions to avoid bubbling
prevent bubbling when buttons are clicked in called functions
use id to check if container was clicked: should read as if(element.id == 'mainContent') { instead of if(element == $("#mainContent")) {
So your code could look like:
<div id="mainContent" class="content" onclick="hidePopUps(this)">
<div>some content before</div>
<div id="btnNew" class="btn-welcome" onclick="showRegister(event)">New user</div>
<div id="btnRegister" class="btn-welcome" onclick="showLogin(event)">Existing user</div>
<div>some content after</div>
</div>
function showRegister(event) {
event.stopPropagation();
...
}
function showLogin(event) {
event.stopPropagation();
...
}
function hidePopUps(element) {
if(element.id == 'mainContent') {
hideLogin();
hideRegister();
}
}
Check out this fiddle: JSFiddle
Related
This is my code:
<div class="titfx">
<div class="clk1">CLICKME</div>
</div>
<div class="here" style="display:none;">info for here</div>
<script src="https://code.jquery.com/jquery-3.3.1.js" integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60=" crossorigin="anonymous"></script>
<script>
$(document).ready(function() {
$('.clk1').on("click", function(event) {
//first code
var here = $(this).parent(".titfx").next(".here");
here.toggle();
//second code
if (!here.is(event.target) && here.has(event.target).length === 0) {
here.hide();
}
});
});
</script>
What the first part of javascript code does: When the word "CLICKME" is clicked, then the hidden div with text "info for here" shows.
What the second part of javascript code should do: When any part of the screen that is not class="here" is clicked on, then the text "info for here" should hide. The second part of my code is unable to achieve that. I'm not sure what I'm doing wrong. Please help me fix this issue.
you need to bind two event listeners to achieve this, one for the "clk1" element, and one for the whole page.
when fires document click event, just hide the text,
when fires ".clk1" click element, you need to stop propagation first and then write the toggle behaviour.
this is my solution
$(document).ready(function() {
$('.clk1').on("click", function(event) {
//first code
event.stopPropagation();
$(".here").toggle();
});
//second code
$(document).on("click", function(event){
$(".here").hide();
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="titfx">
<div class="clk1">CLICKME</div>
</div>
<div class="here" style="display:none;">info for here</div>
Here is a potential solution. The first click binding works for the toggle logic. However, for your second scenario, you said you want it to close them if they click any where on the page, other than the two areas. In that regard, you are concerned with the click events for the body, not just the two areas.
The second logic binds to the body, and checks to see if the clicked element is a child of the .clk1 or the .here. If it is not a child of either one, it will hide the .here.
The css was added to force the page size to be larger than just the html provided so you could actually click on something not them, :)
$(document).ready(function() {
$('.clk1').on("click", function(event) {
var here = $(this).parent(".titfx").next(".here");
here.toggle();
});
$(document.body).on('click', function(event){
var clickedElement = $(event.target);
if (!clickedElement.closest('.clk1').length
&& !clickedElement.closest('.here').length) {
$('.here').hide();
}
});
});
body {
min-width: 800px;
min-height: 600px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="titfx">
<div class="clk1">CLICKME</div>
</div>
<div class="here" style="display:none;">info for here</div>
I have a JS global event handler which looks like this (this is temp code):
$(document).on('click', '.my-class, #box-in-my-class', function(e) {
console.log($(this), 'was clicked!');
if ($(this).is('my-class')) {
$(this).children('.dropdown').toggleClass('active');
}
if ($(this).is('#box-in-my-class')) {
$('#expander').toggleClass('active');
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="my-class">
<div class="other-bit"></div>
<div class="dropdown">
<div id="box-in-my-class"></div>
</div>
</div>
<div id="expander"></div>
(the .active class added makes the div bigger - through css).
However, in running this, when I click the #box-in-my-class, I get this in the console:
#box-in-my-class was clicked!
.my-class was clicked!
which toggles the dropdown (closing it).
How do I set it so that when you click the child of an element it does not bubble/propagate/etc. so that I can click the #box-in-my-class w/o running .my-class
Because your event bubbles. In the code you must call e.stopPropagation(); And also you have some missed ')'.
$(document).on('click', '.my-class, #box-in-my-class', function(e) {
e.stopPropagation();
console.log(e.target, 'was clicked!');
if ($(this).is('my-class')) {
$(this).children('.dropdown').toggleClass('active');
}
if ($(this).is('#box-in-my-class')) {
$('#expander').toggleClass('active');
}
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="my-class">
<div class="other-bit"></div>
<div class="dropdown">
<div id="box-in-my-class">Test 1</div>
</div>
</div>
<div id="expander">Test 2</div>
For more see event bubbling
and e.stopPropagation()
try the following
$(document).on('click', '.my-class, #box-in-my-class', function(e) {
if ($(this).is('.my-class') && $(e.target).is(':not(#box-in-my-class')) {//check if the clicked element is not box-in-my-class
console.log($(this), 'was clicked!');
$(this).children('.dropdown').toggleClass('active');
}
if ($(this).is('#box-in-my-class')) {
$('#expander').toggleClass('active');
}
}
demo:http://jsfiddle.net/0yvuzm0c/
I think you shouldn't use 2 if class when you only need one response.
If I were you, I would write my JS function like this:
if ($(this).is('#box-in-my-class') {
$('#expander').toggleClass('active');
return;
}else if ($(this).is('my-class') {
$(this).children('.dropdown').toggleClass('active');
return;
}
I will check this $('#box-in-my-class') first due to the reason that $('#box-in-my-class') is the child of $(.'my-class').
In this case, if it detected $('#box-in-my-class') is clicked, it will stop the loop. instead of checking $(.'my-class') too.
You may study http://www.w3schools.com/js/js_if_else.asp to be more familiar with if, else, else if loop.
I have a <div class="stock"></div>wrapped around :
<div class="stockAdd"></div>
<div class="stockRemove"></div>
<div class="stockInput"></div>
I want to prevent a click inside my .stock to trigger a function. For now i have the following :
if ($(event.target).is('.stockInput') || $(event.target).is('.stockAdd') || $(event.target).is('.stockRemove')) {
console.log("Ajout stock");
return
}
Isn't there a better way to select thos three divs ? The $(event.target).is('.stock') don't get the job done when i click my nested divs.
Thanks
If I understand you correctly, you want to catch click events on .stockAdd, .stockRemove, and .stockInput, but not on other elements within .stock itself, is that correct?
If so, a delegated event can take care of that without any need to manually check the event target:
$('.stock').on('click', '.stockAdd, .stockRemove, .stockInput', function() {
alert("Clicked");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="stock">
<div class="stockAdd">stockAdd</div>
<div class="stockRemove">stockRemove</div>
<div class="stockInput">stockInput</div>
<div>No event</div>
</div>
I would strongly recommend against depending on event.target here; it's too fragile. Any HTML tags nested inside your desired targets would break things:
$('.stock').on('click', function(event) {
if (event.target.className=="stockAll") {
alert("clicked");
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="stock">
<div class="stockAll">
This <b> will not work if someone clicks in the bold area</b> but works outside
</div>
</div>
You can add a separate class to all of them like .stock-inner and then grab them all with $('.stock-inner') or you can use a $("div[class^='stock-inner']) - this will grab the parent .stock div...
Also, to reject a click event within the handler you're gunna want to use e.preventDefault() where e is the event object.
the reason it doesn't work well on nested divs is they pass the conditional if in your example, to make it stricter you could add div to selector:
if ($(event.target).is('div.stockInput') || $(event.target).is('div.stockAdd') || $(event.target).is('div.stockRemove'))
You can attach the event on .stock and then filter using the event.target.
HTML
<div class="stock" style="border: 10px solid #000;">
<div class="stockAdd">Add</div>
<div class="stockRemove">Remove</div>
<div class="stockInput">Input</div>
</div>
JavaScript
$('.stock').on('click', function(e) {
if( e.target.className !== 'stock' ) {
console.log(e.target.className);
}
});
jsfiddle
I have an app I'm developing and I need a onclick() event to be fired when a <div> is clicked.
So in other words,
<div id="panda"></div>
$("#panda").click(function () {
console.log("some text");
});
So this statement works but now lets say I have,
<div id="panda">
<lots of children>
<div id="koala">
</div>
</lots of children>
</div>
$("#koala").click(function () {
console.log("doesnt work");
});
Now you see for the life of me I can't get koala to be clickable. The click event on parents works fine, and click evens for some empty divs I use as buttons work fine, but for some reason I cant get I filled child <div> to be clickable.
Any ideas what the case could be?
I tried this,
$('#panda').click(function(e){
if ($(e.target).is('#koala'))
{
console.log("koala");
}
});
But it just logs every click on the parent.
One option is to listen to the div children for panda.
$("#panda").on('click','div',function() {
console.log($(this).text()+' '+$(this).attr('id'));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="panda">
<div id="koala">
koala
</div>
<div id="bear">
bear
</div>
</div>
Try making the selector '#panda #koala' like this
$("#panda #koala").click(function () {
console.log("koala");
});
Here is an example,
<div id="panda">Panda
<div id="koala">Koala</div>
</div>
$("#panda").on('click', '#koala', function () {
alert("koala!!!");
});
Here is a Fiddle
Inside that I have other child divs. Those have child divs too.
<div class="parent">
<div class="child_1">//children elements</div>
<div class="child_1">//children elements</div>
<div class="child_1">//children elements</div>
<div class="child_1">//children elements</div>
</div>
I want to add a click event that fires when I click any element inside parent div, including parent div, excluding child_1 div and its descendants.
Currently I tried with
jQuery(".parent").not(".child_1").click(function(event) {
});
But the click event works when I click on child_1 div and it's descendants.
What is the problem here? please help.
UPDATE
here i have another click event for child_1
jQuery(".child_1").click(function(event) {
});
You should do it like this.
$('.parent').on('click', function () {
// do your stuff here
}).find('.child_1').on('click', function (e) {
e.stopPropagation();
});
Here is a fiddle http://jsfiddle.net/BbX7D/1/
You still have to catch the click event on the elements that you want to exclude, otherwise the click will just bubble up to the .parent element.
Use the closest method to check if the clicked element is, or is a child of, an element with the class .child_1. Use stopPropagation to keep the event from bubbling:
$('.parent,.parent *').click(function(e){
if ($(this).closest('.child_1').length > 0) {
alert('in child_1');
} else {
alert('not in child_1');
}
e.stopPropagation();
});
Demo: http://jsfiddle.net/Guffa/tETCQ/
I think it should be
jQuery(".parent, .parent *").not(".child_1").click(function(event) {
});
Try this (fiddle):
(edit + updated fiddle)
I spotted a flaw. This version checks if the clicked element is or is inside an element which has the class 'exclude':
<div class="parent">
<div class="child_1 exclude">//children elements</div>
<div class="child_1">//children elements</div>
<div class="child_1">//children elements</div>
<div class="child_1">//children elements</div>
</div>
jQuery(".parent").click(function(event)
{
if ($(event.target).closest('.exclude').length>0) return false;
alert('hi');
});
a bit of an old question, but figured i'd throw out my resolution in case it helps anyone else.
this is pretty much what i did. this example uses your markup:
$('.parent').on('click', function(e) {
var $target = $(e.target);
if (!$target.parents('.child_1').length && !$target.hasClass('child_1')) {
// do what you need on the parent's click event
// add 'e.preventDefault()' here if you need
}
// no need to prevent default or stop propagation here
// this will allow click events on child elements to work
});