jQuery selecting all except one element not working

231 Views Asked by At

I need to make a function, which show menu, if user click on specific div. Then I need to hide it, if user click anywhere on website, except that one specific div.

For example

<div class="showMeHideMe" style="display:none;">Example</div>
<div class="showIt">Show it!</div>

And then my JavaScript

jQuery('.showIt').click(function(){
$('.showMeHideMe').show();
});

jQuery(document).not('.showMeHideMe').click(function(){
$('.showMeHideMe').hide();
});

If i click on .showIt, everyting working fine and .showMeHideMe is showing. Then if I click anywhere on page, .showMeHideMe is hiding. Also OK. But if it's shown and I click on .showMeHideMe, it hides itself. Which is wrong.

Can you please tell me what I'm doing wrong?

UPDATE

Thank you very much for very fast replies.

I guess it will be better to show it exactly on the page that I need to fix. Now my code looks like this :

<div class="search--box">
<div class="search--box-inner">
<form role="search" method="get" id ="searchform" action="">
<input class="search--box--input" name="s">
</input>
</form>
</div>
</div>

And JavaScript which should handle this

jQuery(".search--box").hide();
jQuery(".desktop-search").mouseenter(function (e) {
e.stopPropagation();
jQuery(".search--box").show();
jQuery(".search--box--input").focus();
});
jQuery(document).not('input.search--box--input').click(function (e) {
e.stopPropagation();
jQuery(".search--box").hide();
});

Also the variant with :not, instead of .not() is not working. Still if I click on the input, it's still hiding.

4

There are 4 best solutions below

0
On BEST ANSWER

Finally we handle it with condition, that check if clicked element have specific class.

$(document).not('input.search--box--input').click(function (e) {
                e.stopPropagation();
                if ($(e.target).hasClass('search--box--input')) {
                    return;
                }
                $(".search--box").hide();
            });

Maybe it could be usable for someone who have the same issue as me :)

0
On

You can use the stopPropagation inside the click on the showIt, and the other function will just handle clicks on the document.

jQuery('.showIt').click(function(e){
  e.stopPropagation();
  $('.showMeHideMe').show();
});

jQuery(document).click(function(){
  $('.showMeHideMe').hide();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="showMeHideMe" style="display:none;">Example</div>
<div class="showIt">Show it!</div>

This way - when you have any click on the document - the .showMeHideMe will be hidden, unless the click was on the .showIt element, and here the call to stopPropagation() will make sure the other hide function will not get called.

0
On

Instead of this line:

jQuery(document).not('.showMeHideMe').click(function(){

you may delegate:

jQuery(document).on('click', ':not(.showIt)', function(e) {

In this way you will match each current and future element in the dom, but not the 'showIt' element.

When the user click outside the 'showIt' element the event sequences (bubling) is:

  • element
  • ....
  • html
  • window

So, you can stop the propagation of these events and use only the first one to close the menu. The same apply when you click on the menu title.

The snippet:

jQuery('.showIt').on('click', function(e) {
  e.stopPropagation();
  $('.showMeHideMe').show();
  console.log('.showIt clicked');
});

jQuery(document).on('click', ':not(.showIt)', function(e) {
  e.stopPropagation();
  $('.showMeHideMe').hide();
  console.log(this.tagName + ' clicked');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>


<div class="showMeHideMe" style="display:none;">Example</div>
<div class="showIt">Show it!</div>

1
On

I cant tell without looking at the actual site, however... I think what is happening is that your .hide() does work but since your other function works on mouse enter and you never left that area, it just triggers .show() again.

If this is the problem I would suggest instead adding a class. So addClass(); and removeClass(); and on your css display: none that class