失去父焦点时隐藏无序列表

Hide unordered list when losing parent focus

本文关键字:无序 列表 隐藏 焦点 失去      更新时间:2023-09-26

我有一个输入字段。当用户关注该输入时,该输入下方会显示一个无序列表。

当用户单击其中一个列表子项时,该数据将插入到输入中,并且无序列表将被隐藏。

当前问题

如果用户单击输入 ,但没有选择任何选项,然后单击文档中的其他位置,则无序列表将继续显示。

我不知道我是否缺少某种事件,我可以用来解决这个问题。

$('body').on('focus blur click', '.autocomplete input , .autocomplete ul,  .autocomplete li' , function() {
if (event.type === 'focus' && event.target.nodeName == 'INPUT') { 
  $(this).siblings('ul').show();
 } else if ((event.type === 'blur' || event.type === 'click' ) && event.target.nodeName == 'LI') {
  $(this).parent('ul').hide();
 }
});
$('body').on('click' ,'li' ,function() {
 
 $('#P1_FIRST_NAME').val($(this).attr('data-value'));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<div class="input__container autocomplete">
    <div class="input__label__container">
        <label for="P1_FIRST_NAME" tabindex="999">Autocomplete</label>
    </div>
    <input type="text" id="P1_FIRST_NAME" class="text_field" autocomplete="off" value="">
    <ul for="P1_FIRST_NAME" style="display: none;">
        <li tabindex="1" data-value="MAD">Madder</li>
        <li tabindex="1" data-value="SAD">Sandy</li>
    </ul>
</div>

检查这个小提琴

您需要在html绑定 Click 事件,并在inputul级别停止事件传播

$('body').on('focus blur click', '.autocomplete input , .autocomplete ul,  .autocomplete li' , function(e) {
if (event.type === 'focus' && event.target.nodeName == 'INPUT') { 
  $(this).siblings('ul').show();
 } else if ((event.type === 'blur' || event.type === 'click' ) && event.target.nodeName == 'LI') {
  $(this).parent('ul').hide();
 }
 e.stopPropagation();
});

$('body').on('click' ,'li' ,function(e) {
 $('#P1_FIRST_NAME').val($(this).attr('data-value'));
 e.stopPropagation();
});
$("html").click( function(e) {
 $('ul').hide();
});

注释

  • 可以使用带有 .on() 的对象传入多个事件处理程序。不要使用 if/else 在不同事件的不同行为之间切换。
  • 不要将要设置的元素的 ID 硬编码到 JS 代码中。使用 data- 属性(请参阅下面的targetSelector)。
  • 使用 .closest() 导航到正确的元素。
  • <ul>使用 CSS 定位,以便它不会向下推送下面的内容。

$('body')
    .on({
        'focus': function() {
            var $ul = $(this).closest('.autocomplete').find('ul');
            $ul.width( $(this).width() ).show();
        },
        'blur': function() {
            var $ul = $(this).closest('.autocomplete').find('ul');
            setTimeout(function () { $ul.fadeOut('fast'); }, 250);
        }
    }, '.autocomplete input')
    .on('click', '.autocomplete li', function() {
        var targetSelector = $(this).closest('ul').data('for');
        $(targetSelector).val( $(this).data('value') );
        $(this).closest('ul').fadeOut('fast');
    });
.autocomplete {
  position: relative;
}
.autocomplete ul {
  display: none;
  position: absolute;
  margin: 0;
  padding: 0;
  list-style: none;
  background-color: white;
  box-shadow: 4px 4px 5px -2px rgba(0,0,0,0.59);
  border: 1px solid #efefef;
}
.autocomplete ul li {
  padding: 3px;
  cursor: pointer;
}
.autocomplete ul li:hover {
  background-color: #FCF3CF;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="input__container autocomplete">
    <div class="input__label__container">
        <label for="P1_FIRST_NAME" tabindex="999">Autocomplete</label>
    </div>
    <input type="text" id="P1_FIRST_NAME" class="text_field" autocomplete="off" value="">
    <ul data-for="#P1_FIRST_NAME">
        <li data-value="MAD">Madder</li>
        <li data-value="SAD">Sandy</li>
    </ul>
</div>
<p>content below content below content below content below content below</p>

如果页面上有多个选择器,则需要使用"this"选择器,但这里有一种方法可以单击该字段以显示 ul 列表,然后单击离开 ul 列表以再次隐藏它:

$( ".text_field" ).click(function() {
  $('ul').show();
});
$(document).mouseup(function(e) {
    var container = $("ul");
    if (!container.is(e.target) && container.has(e.target).length === 0) {
        $('ul').hide();
    }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<div class="input__container autocomplete">
    <div class="input__label__container">
        <label for="P1_FIRST_NAME" tabindex="999">Autocomplete</label>
    </div>
    <input type="text" id="P1_FIRST_NAME" class="text_field" autocomplete="off" value="">
    <ul for="P1_FIRST_NAME" style="display: none;">
        <li tabindex="1" data-value="MAD">Madder</li>
        <li tabindex="1" data-value="SAD">Sandy</li>
    </ul>
</div>