0

In this code I can open the .options menu when I click the .select element however because I use e.stopPropagation(); on the input option to allow the menu to close, I need to incorporate e.target so that if it isn't the target, the menu will close (allowing for click outside).

How do I use e.target to hide the .options menu when clicking away or if I click .select a second time?

$(".select").each(function(e) {
  var $this = $(this),
    options = $this.find(".options");

  $this.click(function(e) {
    $(".options").attr("hidden", "hidden");
    options.attr("hidden") ?
      options.removeAttr("hidden") :
      options.attr("hidden", "hidden");
  });
  options.find("input").click(function(e) {
    e.stopPropagation();
    $(".options").attr("hidden", "hidden");
  });
});
.select {
  border: 1px solid #dedede;
  border-radius: 6px;
  margin: 1.3rem 0;
  width: 250px;
  min-height: 40px;
  box-sizing: border-box;
  overflow: hidden;
  cursor: pointer
}

.selected {
  display: flex;
  padding: 10px;
}

.options {
  display: flex;
  flex-direction: column
}

.options[hidden] {
  display: none;
  flex-direction: column;
  width: 250px;
}

.options input {
  display: none;
}

.options label {
  transition: all 0.2s ease-out;
  padding: 10px;
}

.options label:hover {
  background-color: #f5f5f5;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="select">
  <div class='selected'>
    <div class="selected__text">Click Me</div>
  </div>
  <div class="options" hidden="hidden">
    <label>
      <input type="radio" value="First">Click to Close
    </label>
    <label>
      <input type="radio" value="Second">Click to Close
    </label>
  </div>
</div>

3 Answers 3

1
  • No need for .each it'll be enough to work with a single event
  • Working with a class it will be much easier than hidden attribute
  • For window click I used to use this function below

Your code will looks like this [This code will work with multiple select]

$(document).ready(function(){
  $(".select").on('click' ,function(e) {
    var options = $(this).find(".options");
    $('.options').not(options).addClass('hidden');
    options.toggleClass('hidden');
  });
  $(".select .options").find("input").click(function(e) {
    e.stopPropagation();
    $(this).closest(".options").addClass('hidden');
  });
  on_window_click('.select , .options' , function(){
    $(".options").addClass('hidden');
  });
});


// Functions
function on_window_click(elem , action){
  $(document).on('click',function(e){
    if (!$(elem).is(e.target)
    && $(elem).has(e.target).length === 0)
    {
      action();
    }
  });
}
.select {
  border: 1px solid #dedede;
  border-radius: 6px;
  margin: 1.3rem 0;
  width: 250px;
  min-height: 40px;
  box-sizing: border-box;
  overflow: hidden;
  cursor: pointer
}

.selected {
  display: flex;
  padding: 10px;
}

.options {
  display: flex;
  flex-direction: column
}

.options.hidden {
  display: none;
  flex-direction: column;
  width: 250px;
}

.options input {
  display: none;
}

.options label {
  transition: all 0.2s ease-out;
  padding: 10px;
}

.options label:hover {
  background-color: #f5f5f5;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="select">
  <div class='selected'>
    <div class="selected__text">Click Me</div>
  </div>
  <div class="options hidden">
    <label>
      <input type="radio" value="First">Click to Close
    </label>
    <label>
      <input type="radio" value="Second">Click to Close
    </label>
  </div>
</div>
<div>Another Select</div>
<div class="select">
  <div class='selected'>
    <div class="selected__text">Click Me</div>
  </div>
  <div class="options hidden">
    <label>
      <input type="radio" value="First">Click to Close
    </label>
    <label>
      <input type="radio" value="Second">Click to Close
    </label>
  </div>
</div>

Function Explanation:

on_window_click(elem , action);

elem : The elements you need to avoid/target

action : The action function to run when clicking outside the avoid/target elements

Don't forget to replace

html : class="options" hidden="hidden" with class="options hidden"

css : .options[hidden] with .options.hidden

Sign up to request clarification or add additional context in comments.

Comments

1

You can try toggle attr:

$(document).click(function(e) {
  let options = $('.select').find(".options");
  options.each(function(e){
    !$(this).attr("hidden") && $(this).attr("hidden", "hidden");
  })
});

$(".select").each(function(e) {
  var $this = $(this),
    options = $this.find(".options");

  $this.click(function(e) {
    e.stopPropagation();
    options.attr('hidden', function(index, attr){
        return attr == 'hidden' ? null : 'hidden';
        });
  });
  options.find("input").click(function(e) {
    e.stopPropagation();
    $(".options").attr("hidden", "hidden");
  });
});
.select {
  border: 1px solid #dedede;
  border-radius: 6px;
  margin: 1.3rem 0;
  width: 250px;
  min-height: 40px;
  box-sizing: border-box;
  overflow: hidden;
  cursor: pointer
}

.selected {
  display: flex;
  padding: 10px;
}

.options {
  display: flex;
  flex-direction: column
}

.options[hidden] {
  display: none;
  flex-direction: column;
  width: 250px;
}

.options input {
  display: none;
}

.options label {
  transition: all 0.2s ease-out;
  padding: 10px;
}

.options label:hover {
  background-color: #f5f5f5;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="select">
  <div class='selected'>
    <div class="selected__text">Click Me</div>
  </div>
  <div class="options" hidden="hidden">
    <label>
      <input type="radio" value="First">Click to Close
    </label>
    <label>
      <input type="radio" value="Second">Click to Close
    </label>
  </div>
</div>

Comments

0

If you add a tabindex to the options div, you can use an onblur on it, which should do the trick. See also this answer. It would be better to use a styled select in this case though, both for accessibility and because it seems like you're replicating the same functionality using divs which is the hard way around :)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.