javascriptjquery-select2-3

Hide virtual keyboard after selecting value on Select2 v3


I'm using select2 v.3.4.5 solely for my project. Currently, when viewing on mobile, the keyboard does not close after it open and value selected, I would like to close it thought. I would like open only when user focus on it and type something.

$(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>

As this js

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

I set input-search box to blur already but keyboard does not close.

How can I do to archive this purpose? Please kindly help. Thanks.

PS: Understandably, select2 v4 fixed this bug, yet I could not upgrade my select2 version since my project is solely depend on v3.*


Solution

  • Ensuring the search box does not autofocus

    There is no way to do this well in Select2 - whenever you try to call the blur() function on this input, it just refocuses it.

    However, by listening on the open event, we can replace the search box with our own one, that does not autofocus. Only the currently active search box has the class select2-focused, so we use that to find it, and then create a new search box (with the same select2-input class so it retains the same look and feel), and then re-implement the search feature ourselves, finally inserting that into the DOM, and removing the old search box.

    Not showing the keyboard after closing the selection popup

    Select2 seems to try and implement its own blur() event in a very weird way (see here).

    So, rather than try and use that, take advantage of CSS selectors. The :focus selector in CSS selects anything that has focus. Since Select2 doesn't actually add any new DOM elements (i.e. once in the HTML, it becomes standard <div> elements, <input> elements, etc), we can find the one that has focus, and successfully call blur on it.

    Therefore, by calling $(":focus").blur(), we find the DOM element that currently has focus, and we blur it.

    Also, by using select2-close as our event, rather than change, the keyboard won't open even if the user doesn't select an item, but instead clicks outside of it.


    I have tested it, and it does work for me on an iPad running iOS 11. Here is the final, working code:

    $(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>