jQuery在单击元素外部时隐藏该元素,按预期工作,但实际上并非如此

rryofs0p  于 2023-03-01  发布在  jQuery
关注(0)|答案(3)|浏览(97)

我创建了一个多选下拉列表,当你点击一个div时它会打开。然后当你点击下拉列表内部时,它需要打开才能选择多个东西。然后当你点击下拉列表外部时,它应该关闭。
我得到了这个代码,它的工作如预期,给定的日志:

$(document).mouseup(function(e){
    if(!e.target.parentNode.id.includes('multipleSelectDropdown')){
        $('*[id*=multipleSelectDropdown]').css('display', 'none');
    console.log("Outside!");
    }
  else{
    console.log("Inside!");
  }
});

function clickedMultiSelectDropdown(optionsWrapperInput){
    var optionsWrapper = document.getElementById(optionsWrapperInput);
    if(optionsWrapper.style.display == 'none'){
        optionsWrapper.style.display = 'block';
    }
    else{
        optionsWrapper.style.display = 'none';
    }
}
.multiple-select-wrapper{
  width: 1000px;
  height: 1000px;
}
.multiple-select{
  cursor: pointer;
}
.multiple-select-options-wrapper {
  box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;
}
.own-input-field{
    border: 1px solid rgb(180 180 180);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
  <div class="multiple-select-wrapper">
    <div class="multiple-select">

      <div class="own-input-field" tabindex="0" onclick="clickedMultiSelectDropdown('multipleSelectDropdownSize')">Size...</div>

      <div id="multipleSelectDropdownSize" class="multiple-select-options-wrapper" style="display: none;">
        <div class="multiple-select-options-item">1</div>
        <div class="multiple-select-options-item">2</div>
      </div>

    </div>
  </div>
</body>

如果我点击"大小..."元素,则带有选项的框打开。当我点击框时,它记录为"内部",并保持打开状态。当我点击所有元素的下方或外部时,它显示为"外部",框关闭。

    • 问题**

由于某种原因,当我再次点击"大小..." div时,当盒子打开时,它又一次像预期的那样记录"外面",但是盒子没有关闭。为什么?这让我很生气...

vatpfxk5

vatpfxk51#

您的代码令人困惑。使用2个处理程序会创建一个竞争条件,其中mouseup获胜(如@Pointy所述)。
下面是一个普通的js解决方案,它使用event delegation,只处理click事件,并使用classList.toggle来处理值的显示/隐藏。
由您决定是否将其转换为jquery(如果deemed necessary)。

document.addEventListener(`click`, handle);

function handle(evt) {
  if (!evt.target.closest(`#multipleSelectDropdownSize`)) {
    return document.querySelector(`#multipleSelectDropdownSize`)
      .classList.toggle(`visible`);
  }
  if (evt.target.classList
    .contains(`multiple-select-options-item`)) {
    return evt.target.classList.toggle(`selected`);
  }
}
.multiple-select-wrapper {
  width: 100px;
  height: 100px;
}

.multiple-select {
  cursor: pointer;
}

.multiple-select-options-wrapper {
  display: block;
}

#multipleSelectDropdownSize {
  display: none;
}

.visible {
  display: block !important;
}

.selected {
  background-color: blue;
  color: white;
}

.multiple-select-options-wrapper {
  box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;
}

.own-input-field {
  border: 1px solid rgb(180 180 180);
}
<div class="multiple-select-wrapper">
  <div class="multiple-select">

    <div class="own-input-field" tabindex="0">Size...</div>

    <div id="multipleSelectDropdownSize" class="multiple-select-options-wrapper">
      <div class="multiple-select-options-item">1</div>
      <div class="multiple-select-options-item">2</div>
    </div>

  </div>
</div>
gmol1639

gmol16392#

我从@KooiInc和@Pointy那里得到了一些灵感,他们几乎解决了我的问题。对于我的情况,下面的代码做了我想要的。当你点击"大小..."时,它会打开选项,当你点击它们时,它会保持打开状态,当你点击其他任何地方时,它会关闭它们:

document.addEventListener('mouseup', handleSearchClick);

function handleSearchClick(evt){

    if(evt.target.classList.contains('own-input-field')){
        var optionsWrapper = evt.target.nextElementSibling;
        if(optionsWrapper.style.display == 'none'){
            optionsWrapper.style.display = 'block';
        }
        else{
            optionsWrapper.style.display = 'none';
        }
    }
    else if(!evt.target.classList.contains('multiple-select-options-item')){
        document.querySelectorAll('.multiple-select-options-wrapper').forEach((dropdownItem) => {
            dropdownItem.style.display = 'none';
        });
    }
}
.multiple-select-wrapper{
  width: 1000px;
  height: 1000px;
}
.multiple-select{
  cursor: pointer;
}
.multiple-select-options-wrapper {
  box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;
}
.own-input-field{
    border: 1px solid rgb(180 180 180);
}
<body>
  <div class="multiple-select-wrapper">
    <div class="multiple-select">

      <div class="own-input-field" tabindex="0">Size...</div>

      <div id="multipleSelectDropdownSize" class="multiple-select-options-wrapper" style="display: none;">
        <div class="multiple-select-options-item">1</div>
        <div class="multiple-select-options-item">2</div>
      </div>

    </div>
  </div>
</body>

谢谢你们两个,没有你们不可能解决这个问题!

hfwmuf9z

hfwmuf9z3#

“mouseup”处理程序为目标元素的祖先链中的每个元素触发,当它冒泡到DOM中的某个点时,父id没有匹配的内容,它将隐藏该元素。
处理完该事件后,浏览器将触发“click”事件,select元素的处理程序将看到select下拉列表是隐藏的,因此它将重新打开它。
我会这么做:

$(document).on("click", ".own-input-field", function(e) {
 e.stopImmediatePropagation();
 $(this).closest(".multiple-select").find(".multiple-select-options-wrapper").show();
});

$(document).on("click", function(e) {
  e.stopImmediatePropagation();
  if ($(e.target).is(".own-input-field"))
    return;
  $(".multiple-select-options-wrapper").hide();
});
.multiple-select-wrapper{
  height: 100px;
}
.multiple-select{
  cursor: pointer;
}
.multiple-select-options-wrapper {
  box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;
}
.own-input-field{
    border: 1px solid rgb(180 180 180);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
  <div class="multiple-select-wrapper">
    <div class="multiple-select">

      <div class="own-input-field" tabindex="0">Size...</div>
      
      <div class="multiple-select-options-wrapper" style="display: none">
        <div class="multiple-select-options-item">1</div>
        <div class="multiple-select-options-item">2</div>
      </div>

    </div>
  </div>
  
  This is other content.
</body>

相关问题