0

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.

Brian Tompsett - 汤莱恩
  • 5,195
  • 62
  • 50
  • 120
misner3456
  • 368
  • 1
  • 11
  • @Taplar I added a document.ready and it does not resolve the issue? And I don't know what you mean by "binding" - how do I fix that? – misner3456 Aug 26 '19 at 22:09
  • @Taplar Well I don't know what happened, but I pasted the correct document.ready and somehow the `);` part got omitted. Even so, I tested this (inclusive of the document.ready) and it still does not work. – misner3456 Aug 26 '19 at 22:16
  • @Taplar Is that correct now? – misner3456 Aug 26 '19 at 22:28
  • It looks syntatically correct now. – Taplar Aug 26 '19 at 22:33
  • @Taplar Btw, your solution literally did nothing to fix the code. – misner3456 Aug 26 '19 at 22:33
  • @Taplar What do you mean by "binding"? You mean the order of the html elements and javascript code? – misner3456 Aug 26 '19 at 22:36
  • Yes. I would highly recommend reading that documentation on the document ready. It explains why it is necessary, and what issue it solves. "binding" refers to the use of `on()` or one of it's wrappers (ex. `click()` or `mouesdown()`) to **bind** and event listener to an element. – Taplar Aug 26 '19 at 22:37
  • @Taplar Then that's something you need to complain to stackoverflow about. My code initially had the html above the javascript, but stackoverflow reverses the order when the code is pasted on here. That's not my problem. Regardless, the addition of document.ready did absolutely nothing and has nothing to do with fixing my code. It was a wasted 5 minutes fixing something that supposedly "resolved" nothing. I'm sorry to be harsh, it's the honest truth. – misner3456 Aug 26 '19 at 22:40
  • Looking back at the edit history, you appear to be correct. The fiddle had the blocks in the order I confused with being in the wrong order. There was an issue with the syntax of the function declaration, but the ordering was not an issue. – Taplar Aug 26 '19 at 22:44
  • `if (!here.is(event.target) && here.has(event.target).length === 0)` so I guess this is slightly confusing. `here` is going to be the `.here`, and `event.target` will be a `.clik1` or a nested child of the click1, which are never the same element, so the `is` check will always be true. Then the second part checks to see if the `.clik1` is a child of the `.here`, which it never is. So that should always be 0, so your second conditional should also always be true. So I would expect that conditional to always be true and hide the `here` – Taplar Aug 26 '19 at 22:51
  • @Taplar Thanks for trying to explain it, seems to make a bit sense now. It was a copy and pasted code I used, so I didn't understand it. I'll figure out how to get this to work, thank you – misner3456 Aug 26 '19 at 22:55

2 Answers2

1

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>
Taplar
  • 24,246
  • 4
  • 18
  • 33
  • Thanks for your solution, so I see what you mean when you're referring to how I bind elements. I was bundling the click handlers to one event, even though they were two separate events, total mishap on my end. Though I couldn't get your solution to work, I was able to with suyuan's code. Even so, you led me in the right direction to understanding my code more. Thanks for your help! – misner3456 Aug 26 '19 at 23:59
1

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>
suyuan xu
  • 66
  • 3
  • I almost cried reading this, thank you! I completely ignored how click handlers work and didn't think about it until you brang it up so it makes sense now. I also didn't think stoppropagation would work here, as that was always the case. Otherwise this totally resolved the issue, thank you so much! – misner3456 Aug 26 '19 at 23:55