Home > Net >  Keep current bootstrap menu open when the input is on focus
Keep current bootstrap menu open when the input is on focus

Time:10-07

I have many (dynamic) input with each having its own dropdown

I want to keep the dropdown popup in focus when the current input is active/being typed , now the issue is my dropdown menu closes when I type in textbox

I cannot use ID selector and hard code since the number of dropdowns are dynamic.

I have tried with

<!doctype html>
<html lang="en">
  <head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA 058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>

  </head>
  <body>


    <div >
      <input type="text"  aria-label="Text input with segmented dropdown button">
      <div >
        <button type="button"  data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
        </button>
        <div >
<input type="text" placeholder="Search.." id="myInput" >
          <a  data-value="{{Action}}" href="#">Action</a>
          <a  data-value="{{Another action}}" href="#">Another action</a>
          <a  data-value="{{Something else here}}" href="#">Something else here</a>
          <div role="separator" ></div>
          <a  data-value="{{Separated lin}}" href="#">Separated link</a>                                    
        </div>
      </div>
    </div>
    
    
    <div >
      <input type="text"  aria-label="Text input with segmented dropdown button">
      <div >
        <button type="button"  data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
        </button>
        <div >
<input type="text" placeholder="Search.."  >
          <a  data-value="{{Action}}" href="#">Action</a>
          <a  data-value="{{Another action}}" href="#">Another action</a>
          <a  data-value="{{Something else here}}" href="#">Something else here</a>
          <div role="separator" ></div>
          <a  data-value="{{Separated lin}}" href="#">Separated link</a>                                    
        </div>
      </div>
    </div>        
    
    <div >
      <input type="text"  aria-label="Text input with segmented dropdown button">
      <div >
        <button type="button"  data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
        </button>
        <div >
<input type="text" placeholder="Search.."  >
          <a  data-value="{{Action}}" href="#">Action</a>
          <a  data-value="{{Another action}}" href="#">Another action</a>
          <a  data-value="{{Something else here}}" href="#">Something else here</a>
          <div role="separator" ></div>
          <a  data-value="{{Separated lin}}" href="#">Separated link</a>                                    
        </div>
      </div>
    </div>        
            
    
    
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-ApNbgh9B Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5 76PVCmYl" crossorigin="anonymous"></script>



<script>
$(function(){

  $('.dropdown-item').click(function(e){
var value = $(this).data('value');
var textElement = $(this).parent().parent().prev()
textElement = textElement.val(textElement.val()   value);
event.preventDefault();
event.stopPropagation();
textElement.focus()
  });
  
});


$(".search").keyup(function(){
  var input, filter, ul, li, a, i;
  input = $(this).get(0);
  filter = input.value.toUpperCase();
  div = $(this).parent().get(0);

  a = div.getElementsByTagName("a");
  for (i = 0; i < a.length; i  ) {
txtValue = a[i].textContent || a[i].innerText;
if (txtValue.toUpperCase().indexOf(filter) > -1) {
  a[i].style.display = "";
} else {
  a[i].style.display = "none";
}
  }
});

(function() {
var disable = false;
$('.dropdown-toggle').on('mousedown touchstart', function() {
        disable = true;
        console.log("inside1")
    })
    .on('focus', function() {
        if (!disable) {
            $(this).dropdown('toggle');            console.log("inside2")
        }
    })
    .on('mouseup touchend',function() {
        disable = false;console.log("inside3")
    })
})()

</script>
  </body>
</html>

CodePudding user response:

$(document).ready(() => {
  $(".input-group > input")
    .on("focus", (e) => {
      let inputEl = e.currentTarget;
      let dropdownEl = inputEl.parentElement.querySelector(".dropdown-menu");
      $(dropdownEl).show();
    })
    .on("blur", (e) => {
      // If click outside the input, check for condition to hide the dropdown
      let inputEl = e.currentTarget;
      let dropdownEl = inputEl.parentElement.querySelector(".dropdown-menu");
      let dropdownSearchEl = dropdownEl.querySelector('.search');
      if (e.relatedTarget == dropdownSearchEl) {
        // Check if the target is the input insdie dropdown, then return to prevent the dropdown hiding
        return;
      }
      $(dropdownEl).hide();
    })
    .on('keyup', (e) => {
      let inputEl = e.currentTarget;
      let dropdownEl = inputEl.parentElement.querySelector(".dropdown-menu");
      let dropdownSearchEl = dropdownEl.querySelector('.search');

      // Un-comment here if you want to set the value of the dropdown input as the value of the actual input
      // dropdownSearchEl.value = inputEl.value;
    });

  $(".search")
    .on("blur", (e) => {
      // When click outside the dropdown search input, hide the dropdown
      let dropdownInputEl = e.currentTarget;
      let dropdownEl = dropdownInputEl.parentElement;
      $(dropdownEl).hide();
    })
    .on("keyup", function() {
      var input, filter, ul, li, a, i;
      input = $(this).get(0);
      filter = input.value.toUpperCase();
      div = $(this).parent().get(0);

      a = div.getElementsByTagName("a");
      for (i = 0; i < a.length; i  ) {
        txtValue = a[i].textContent || a[i].innerText;
        if (txtValue.toUpperCase().indexOf(filter) > -1) {
          a[i].style.display = "";
        } else {
          a[i].style.display = "none";
        }
      }
    });
});
<!doctype html>
<html lang="en">

<head>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA 058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>

</head>

<body>


  <div >
    <input type="text"  aria-label="Text input with segmented dropdown button">
    <div >
      <button type="button"  data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
            </button>
      <div >
        <input type="text" placeholder="Search.." id="myInput" >
        <a  data-value="{{Action}}" href="#">Action</a>
        <a  data-value="{{Another action}}" href="#">Another action</a>
        <a  data-value="{{Something else here}}" href="#">Something else here</a>
        <div role="separator" ></div>
        <a  data-value="{{Separated lin}}" href="#">Separated link</a>
      </div>
    </div>
  </div>

  <div >
    <input type="text"  aria-label="Text input with segmented dropdown button">
    <div >
      <button type="button"  data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
            </button>
      <div >
        <input type="text" placeholder="Search.." >
        <a  data-value="{{Action}}" href="#">Action</a>
        <a  data-value="{{Another action}}" href="#">Another action</a>
        <a  data-value="{{Something else here}}" href="#">Something else here</a>
        <div role="separator" ></div>
        <a  data-value="{{Separated lin}}" href="#">Separated link</a>
      </div>
    </div>
  </div>

  <div >
    <input type="text"  aria-label="Text input with segmented dropdown button">
    <div >
      <button type="button"  data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
            </button>
      <div >
        <input type="text" placeholder="Search.." >
        <a  data-value="{{Action}}" href="#">Action</a>
        <a  data-value="{{Another action}}" href="#">Another action</a>
        <a  data-value="{{Something else here}}" href="#">Something else here</a>
        <div role="separator" ></div>
        <a  data-value="{{Separated lin}}" href="#">Separated link</a>
      </div>
    </div>
  </div>



  <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-ApNbgh9B Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5 76PVCmYl" crossorigin="anonymous"></script>

  </script>
</body>

</html>

Since you are using Bootstrap dropdown, you can use its Popover methods to toggle show/hide the dropdown Bootstrap Popover. The steps I do to achieve what you want:

  1. Assign event focus and blur on the input to show/hide the dropdown. Inside the blur event, I check for the condition if the user click on the dropdown's input, then still keep the dropdown opening
  2. Assign the event blur on the dropdown input to hide the dropdown

Ps: Using the jQuery event you can get the related DOM element, to experiment a little bit further, you can log the event then use the Devtool to look for the element you want to get. As you can see, in the script, I use event.currentTarget to get the element that the user click on. That's solve the problem.

  • Related