javascripthtmljquery-uijquery-ui-menu

How do you use JQuery UI menu with ENTER key?


I'm working on an application that needs to be fully keyboard controllable, everything is working great up until now, but i can't make the JQuery UI Menu widget works when using the ENTER key.

From the documentation, there seems to be no specifics method to make this work so i'm using "onclick" on the list elements

  <li onclick="alert('Books Action')"><div>Books</div></li>

Here is a jsfiddle (https://jsfiddle.net/djbh6r82/) with the example from JQuery UI documentation and an alert on the first menu item -> It works fine when i click on it but with 'ENTER' it just bring me back to the start (focus on menu is not lost)

$(function() {
  $("#menu").menu();
});
.ui-menu {
  width: 150px;
}
<link rel="stylesheet" href="//code.jquery.com/ui/1.13.0/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-3.6.0.js"></script>
<script src="https://code.jquery.com/ui/1.13.0/jquery-ui.js"></script>

<ul id="menu">
  <li class="ui-state-disabled">
    <div>Toys (n/a)</div>
  </li>
  <li onclick="alert('Books Action')">
    <div>Books</div>
  </li>
  <li>
    <div>Clothing</div>
  </li>
  <li>
    <div>Electronics</div>
    <ul>
      <li class="ui-state-disabled">
        <div>Home Entertainment</div>
      </li>
      <li>
        <div>Car Hifi</div>
      </li>
      <li>
        <div>Utilities</div>
      </li>
    </ul>
  </li>
  <li>
    <div>Movies</div>
  </li>
  <li>
    <div>Music</div>
    <ul>
      <li>
        <div>Rock</div>
        <ul>
          <li>
            <div>Alternative</div>
          </li>
          <li>
            <div>Classic</div>
          </li>
        </ul>
      </li>
      <li>
        <div>Jazz</div>
        <ul>
          <li>
            <div>Freejazz</div>
          </li>
          <li>
            <div>Big Band</div>
          </li>
          <li>
            <div>Modern</div>
          </li>
        </ul>
      </li>
      <li>
        <div>Pop</div>
      </li>
    </ul>
  </li>
  <li class="ui-state-disabled">
    <div>Specials (n/a)</div>
  </li>
</ul>

Am I doing this wrong ? I tried different thing (<a href='#' onclick="xxx"></a> instead of div, onclick on div instead of ul) but nothing seems to work


Solution

  • When you review the API Docs, you will see under https://api.jqueryui.com/menu/ the following details:

    Keyboard interaction

    Typing a letter moves focus to the first item whose title starts with that character. Repeating the same character cycles through matching items. Typing more characters within the one second timer matches those characters.

    Disabled items can receive keyboard focus, but do not allow any other interaction.

    So the Enter is already engaged and will trigger the select event for the Menu. You will then want to perform some action in the select callback.

    $(function() {
      $("#menu").menu({
        select: function(e, ui) {
          console.log(ui.item.text().trim(), "Selected");
        }
      }).focus();
    });
    .ui-menu {
      width: 150px;
    }
    <link rel="stylesheet" href="//code.jquery.com/ui/1.13.0/themes/base/jquery-ui.css">
    <script src="https://code.jquery.com/jquery-3.6.0.js"></script>
    <script src="https://code.jquery.com/ui/1.13.0/jquery-ui.js"></script>
    
    <ul id="menu">
      <li class="ui-state-disabled">
        <div>Toys (n/a)</div>
      </li>
      <li>
        <div>Books</div>
      </li>
      <li>
        <div>Clothing</div>
      </li>
      <li>
        <div>Electronics</div>
        <ul>
          <li class="ui-state-disabled">
            <div>Home Entertainment</div>
          </li>
          <li>
            <div>Car Hifi</div>
          </li>
          <li>
            <div>Utilities</div>
          </li>
        </ul>
      </li>
      <li>
        <div>Movies</div>
      </li>
      <li>
        <div>Music</div>
        <ul>
          <li>
            <div>Rock</div>
            <ul>
              <li>
                <div>Alternative</div>
              </li>
              <li>
                <div>Classic</div>
              </li>
            </ul>
          </li>
          <li>
            <div>Jazz</div>
            <ul>
              <li>
                <div>Freejazz</div>
              </li>
              <li>
                <div>Big Band</div>
              </li>
              <li>
                <div>Modern</div>
              </li>
            </ul>
          </li>
          <li>
            <div>Pop</div>
          </li>
        </ul>
      </li>
      <li class="ui-state-disabled">
        <div>Specials (n/a)</div>
      </li>
    </ul>

    Giving it focus up front allows it to already be invoked.