在 Select2 v3 上选择值后隐藏虚拟键盘

Hide virtual keyboard after selecting value on Select2 v3

我只为我的项目使用 select2 v.3.4.5。目前,在移动设备上查看时,键盘在打开并选择值后不会关闭,我想关闭它。我只想在用户关注它并输入内容时打开它。

$(document).ready(function() {
  $('#Salutation,#Gender').select2()
    .on('change select-open', function(e) {
      setTimeout(function() {
        $('.select2-input').blur();
      }, 500);
    });
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<script src="https://stackpath.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/select2/3.4.5/select2.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/3.4.5/select2.min.js"></script>


<div class="container">
  <div class="row">
    <div class="col-xs-4 col-xs-offset-4">
      <h3>Application Form</h3>
      <form class="form" action="/action_page.php">
        <div class="form-group">
          <label for="GivenName">Given Name:</label>
          <input class="form-control" type="text" id="GivenName">
        </div>
        <div class="form-group">
          <label for="Surname">Surname:</label>
          <input class="form-control" type="text" id="Surname">
        </div>
        <div class="form-group">
          <label for="Salutation">Salutation:</label>
          <select class="" name="" id="Salutation">
            <option value="Mrs">Mrs</option>
            <option value="Mr">Mr</option>
            <option value="Miss">Miss</option>
          </select>
        </div>
        <div class="form-group">
          <label for="Gender">Gender:</label>
          <select class="" name="" id="Gender">
            <option value="Female">Female</option>
            <option value="Male">Male</option>
            <option value="Transgender">Transgender</option>
          </select>
        </div>
        <button type="submit" class="btn btn-default">Submit</button>
      </form>
    </div>
  </div>
</div>

作为这个 js

    $('#Salutation,#Gender').select2()
    .on('change select2-open',function(e){
        setTimeout(function(){
            $('.select2-input').blur();
        }, 500);
    });

我已经将输入搜索框设置为模糊,但键盘没有关闭。

我该怎么做才能存档这个目的?请帮忙。谢谢

PS: 可以理解,select2 v4 修复了这个错误,但我无法升级我的 select2 版本,因为我的项目完全依赖于 v3。*

确保搜索框不自动对焦

在 Select2 中无法很好地做到这一点 - 每当您尝试在此输入上调用 blur() 函数时,它只会重新聚焦它。

然而,通过监听 open 事件,我们可以用我们自己的搜索框替换搜索框,它不会自动对焦。只有当前活动的搜索框有 class select2-focused,所以我们用它来找到它,然后创建一个新的搜索框(与相同的 select2-input class 所以它保留相同的外观),然后我们自己重新实现搜索功能,最后将其插入 DOM,并删除旧的搜索框。

关闭 selection 弹出窗口后不显示键盘

Select2 似乎试图以一种非常奇怪的方式实现它自己的 blur() 事件(参见 here)。

因此,与其尝试使用它,不如利用 CSS select 或者。 :focus select 或 CSS select 中的任何具有焦点的内容。由于 Select2 实际上并没有添加任何新的 DOM 元素(即一旦在 HTML 中,它就变成了标准的 <div> 元素、<input> 元素等),我们可以找到一个有焦点,并成功对其调用模糊。

因此,通过调用$(":focus").blur(),我们找到了当前有焦点的DOM元素,并对其进行了模糊处理。

此外,通过使用 select2-close 而不是 change 作为我们的事件,即使用户没有 select 一个项目,而是点击了,键盘也不会打开在它之外。


我已经测试过了,它确实适用于 iPad 运行 iOS 11。这是最终的工作代码:

$(document).ready(function() {

 $("#Salutation,#Gender").select2().on("select2-open",()=>{
  let oldSearchBox = $(".select2-focused")[0]; //Get the current search box
  let parent = oldSearchBox.parentNode; //The parent of the search box (i.e. the element that holds it)

  let search = document.createElement("input"); //Create a new input box
  search.classList.add("select2-input"); //Make it look like the old one
  search.addEventListener("keyup", ()=>{ //Whenever someone releases a key, filter the results
   let results = parent.parentNode.getElementsByClassName("select2-result"); //Get all of the select box options
   let query = search.value.toLowerCase(); //Get what the user has typed (in lower case so search is case-insensitive)
   for (let result of results) { //Loop through all of the select box options
    let resultText = result.children[0].childNodes[1].nodeValue.toLowerCase(); //Get the text for that option (also in lower case)
    result.style.display =  (resultText.indexOf(query)==-1) ? "none" : "block"; //If the result text contains the search, it is displayed, otherwise it is hidden
   }
  })
  
  parent.appendChild(search); //Add the new search box to the page
  oldSearchBox.remove(); //Remove the old one
 });
  
  $("#Salutation,#Gender").select2().on("select2-close",()=>{
   setTimeout(()=>{
   $(":focus").blur();
    }, 50);
  });

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<script src="https://stackpath.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/select2/3.4.5/select2.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/3.4.5/select2.min.js"></script>


<div class="container">
  <div class="row">
    <div class="col-xs-4 col-xs-offset-4">
      <h3>Application Form</h3>
      <form class="form" action="/action_page.php">
        <div class="form-group">
          <label for="GivenName">Given Name:</label>
          <input class="form-control" type="text" id="GivenName">
        </div>
        <div class="form-group">
          <label for="Surname">Surname:</label>
          <input class="form-control" type="text" id="Surname">
        </div>
        <div class="form-group">
          <label for="Salutation">Salutation:</label>
          <select class="" name="" id="Salutation">
            <option value="Mrs">Mrs</option>
            <option value="Mr">Mr</option>
            <option value="Miss">Miss</option>
          </select>
        </div>
        <div class="form-group">
          <label for="Gender">Gender:</label>
          <select class="" name="" id="Gender">
            <option value="Female">Female</option>
            <option value="Male">Male</option>
            <option value="Transgender">Transgender</option>
          </select>
        </div>
        <button type="submit" class="btn btn-default">Submit</button>
      </form>
    </div>
  </div>
</div>

我有一个替代的解决方法,我已经使用了大约一个星期了。到目前为止,它似乎在我尝试过的所有 android 和 ios 设备上都运行良好。我在 'multiple' 设置为 false(即 'single' 类型)的 select2 实例上使用它。在这种情况下,我希望用户进行单一选择,键盘应该消失。

简而言之,在 select2-close 事件期间,您设置了一个标志,指示您要禁用 select2-focusser 接收的任何焦点事件。当焦点事件被触发时,您检查标志是否已设置,如果是,您只需将焦点移动到另一个目标。我将标志添加为数据 属性 并在一秒钟后使用 setTimeOut 重置此标志。

这是有效的,因为 select2 关闭处理程序分为两部分,并且 'select2-close' 事件在第 1 部分结束时(和第 2 部分之前)触发。第 1 部分是 'abstract' 关闭处理程序,它实际上关闭了选择对话框,并设置了控件的值。第 2 部分是 'single' 关闭处理程序,它实际上只是导致 select2 重新聚焦于自身(这就是问题所在!)。

对我来说,我在我的导航栏按钮之一中添加了一个“.focus-bait”class,我用它在 focusser 的焦点事件执行期间转移焦点。如果您在使此重新聚焦步骤起作用时遇到问题,请尝试使用不同的元素(我在为聚焦目的而制作的按钮上使其起作用时遇到了问题。我仍然不确定为什么,但我没有调查更多,因为我的导航按钮解决方案非常适合我的需要)。

$('body').on('focus','.select2-focusser', function(e) { 
    let isDisabled = $(this).parent().first().data("disable-focus");
    if (isDisabled) {
        console.log('Focusser: focus event aborted');
       $('.focus-bait').focus();
    }   
});

//select2_focus_ctrl is a class that I add to any select2 container
//that I wish to use this focus logic e.g. add it to #Salutation,#Gender
$('body').on('select2-close','select2_focus_ctrl', function(e) {
    console.log('Focusser: disabling focus event');
    if ($(this).data('select2').opts.multiple != true) {
        $(this).prev().data("disable-focus",true);
        setTimeout(function() { 
            console.log('Focusser: enabling focusser');
            $(this).prev().data("disable-focus",false);
        }, 1000);               
    }
});

这是完整的代码片段。在编写它时,我注意到如果 select2 容器来自 'select' 元素,则 'multiple' 属性 不存在(我使用的是 'div'),所以我已经更改了一行代码:.opts.multiple != true(而不是 == false)。

$(document).ready(function() {

$('#Salutation').select2(

);

    
$('body').on('focus','.select2-focusser', function(e) { 
    let isDisabled = $(this).parent().first().data("disable-focus");
    if (isDisabled) {
        console.log('Focusser: focus event aborted');
       $('.focus-bait').focus(); 
    }   
});

$('body').on('select2-close','.select2_focus_ctrl', function(e) {
    console.log('Focusser: disabling focus event');
    if ($(this).data('select2').opts.multiple != true) {
        $(this).prev().data("disable-focus",true);
        setTimeout(function() { 
            console.log('Focusser: enabling focusser');
            $(this).prev().data("disable-focus",false);
     }, 1000);
    }
});


$('body').on('change','#Salutation', function(e) {
      let theVal = $('#Salutation').select2("val");
      $('#currentVal').val(theVal);
});
      
});
body {
  background: #dddddd;
  padding: 20px;
  font-family: Helvetica;
}

button {
  background: #0084ff;
  border: none;
  border-radius: 5px;
  padding: 8px 14px;
  font-size: 15px;
  color: #fff;
  cursor: pointer;
}

button:focus {
  background: #fff;
  color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/3.5.4/select2.css" rel="stylesheet"/>

<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/3.5.4/select2.js"></script>


<button type="button" class="focus-bait">
Just the bait!
</button>
<br>
<div>
<input id="currentVal"  style="height:20px;width:150px"/>
</div>

<br><br>

<select class="select2_focus_ctrl" id="Salutation" style="width:200px;">
  <option value="Mrs">Mrs</option>
  <option value="Mr">Mr</option>
  <option value="Miss">Miss</option>
  <option value="Esquire">Esquire</option> 
  <option value="Other Options">Other Options</option> 
  <option value="Just for interest">Interesting longer item</option>    
</select>