Search code examples
javascriptjqueryjquery-uiselect-menujquery-ui-selectmenu

How to iterate through jQuery UI selectmenu by using 2 buttons?


Please try the jsFiddle with jQuery UI selectmenu and 2 buttons.

With the help of 2 buttons prevGame and nextGame I am able to change the selectedIndex variable tracking the currently selected game number.

The jQuery UI selectmenu doc unfortunately does not explain how to set and get (so that I can update the span currGame) the currently selected item:

screenshot

Please explain: how to set and get the selected item in jQuery UI selectmenu?

HTML-code:

<form>
  <select name="games" id="games"></select>
  <button id="prevGame">&lt;</button>
  <span id="currGame">Loading...</span>
  <button id="nextGame">&gt;</button>
</form>

JavaScript-code:

var yourGames = [1, 3, 5];
var hisGames = [8, 10, 12, 14];
var selectedIndex = 0;

$("#games").selectmenu();

// emulate repeating server responses
setInterval(function() {
  updateMenu();
}, 5000);

$('#prevGame').button().click(function(e) {
  e.preventDefault();
  selectedIndex = Math.max(selectedIndex - 1, 0);
  updateButtons();
});

$('#nextGame').button().click(function(e) {
  e.preventDefault();
  selectedIndex = Math.min(selectedIndex + 1, lastIndex());
  updateButtons();
});

function lastIndex() {
  return yourGames.length + hisGames.length - 1;
}

function updateButtons() {
  $('#currGame').html('selectedIndex=' + selectedIndex); // TODO: change to "Game #"
  $('#prevGame').button(selectedIndex == 0 ? "disable" : "enable");
  $('#nextGame').button(selectedIndex == lastIndex() ? "disable" : "enable");
}

function updateMenu() {
  var yourGroup = ['<optgroup label="YOUR TURN">'];
  for (var i = 0; i < yourGames.length; i++) {
    var gameNumber = yourGames[i];
    var selectedTag = (i == selectedIndex ? 'selected="selected"' : '');
    yourGroup.push(
      '<option ' +
      selectedTag +
      ' value="' +
      gameNumber +
      '">Game #' +
      gameNumber +
      '</option>');
  }
  yourGroup.push('</optgroup>');

  var hisGroup = ['<optgroup label="HIS TURN">'];
  for (var i = 0; i < hisGames.length; i++) {
    var gameNumber = hisGames[i];
    var selectedTag = (i - yourGames.length == selectedIndex ? 'selected="selected"' : '');
    hisGroup.push(
      '<option ' +
      selectedTag +
      ' value="' +
      gameNumber +
      '">Game #' +
      gameNumber +
      '</option>');
  }
  hisGroup.push('</optgroup>');

  $("#games").selectmenu('destroy')
    .empty()
    .append(yourGroup.length > 2 ? yourGroup.join('') : '')
    .append(hisGroup.length > 2 ? hisGroup.join('') : '')
    .selectmenu(); // TODO: select the game at selectIndex
}

UPDATE:

I have prepared a newer jsFiddle using selectmenu("refresh") instead of selectmenu("destroy"), but it still has some issues.


Solution

  • jQuery and jQuery UI provides no way to directly set selected index of a select menu. You can use pure javascript way to set the selected index. Also I assume you want to change the text between buttons every time select menu changes. You can do it like so:

    var yourGames = [1, 3, 5];
    var hisGames = [8, 10, 12, 14];
    var selectedIndex = 0;
    
    setInterval(function() {
      updateMenu();
      updateCurrentGame();
      updateButtons();
    }, 5000);
    
    $("#games").selectmenu();
    
    $('#prevGame').button().click(function(e) {
      e.preventDefault();
      selectedIndex = Math.max(selectedIndex - 1, 0);
      updateButtons();
      updateCurrentGame();
    });
    
    $('#nextGame').button().click(function(e) {
      e.preventDefault();
      selectedIndex = Math.min(selectedIndex + 1, lastIndex());
      updateButtons();
      updateCurrentGame();
    });
    
    function lastIndex() {
      return yourGames.length + hisGames.length - 1;
    }
    
    function updateButtons() {
      $('#prevGame').button(selectedIndex == 0 ? "disable" : "enable");
      $('#nextGame').button(selectedIndex == lastIndex() ? "disable" : "enable");
    }
    
    // Update the select menu when prev & next buttons are pressed
    function updateCurrentGame() {
      var selectedText = $($("select#games option")[selectedIndex]).text();
      $('#currGame').html(selectedText);
      // pure js vay to set selected index
      $("#games")[0].selectedIndex = selectedIndex;
      $("#games").selectmenu("refresh");
    }
    
    // Update the selected index every time the select menu is changed manually
    $("#games").on("selectmenuchange", function(e, ui) {
      console.log(ui);
      selectedIndex = ui.item.index;
      var selectedText = ui.item.element.text();
      $('#currGame').html(selectedText);
      updateButtons();
    })
    
    function updateMenu() {
      var yourGroup = ['<optgroup label="YOUR TURN">'];
      for (var i = 0; i < yourGames.length; i++) {
        var gameNumber = yourGames[i];
        var selectedTag = (i == selectedIndex ? 'selected="selected"' : '');
        yourGroup.push(
          '<option ' +
          selectedTag +
          ' value="' +
          gameNumber +
          '">Game #' +
          gameNumber +
          '</option>');
      }
      yourGroup.push('</optgroup>');
    
      var hisGroup = ['<optgroup label="HIS TURN">'];
      for (var i = 0; i < hisGames.length; i++) {
        var gameNumber = hisGames[i];
        var selectedTag = (yourGames.length + i == selectedIndex ? 'selected="selected"' : '');
        hisGroup.push(
          '<option ' +
          selectedTag +
          ' value="' +
          gameNumber +
          '">Game #' +
          gameNumber +
          '</option>');
      }
      hisGroup.push('</optgroup>');
    
      $("#games").selectmenu('destroy')
        .empty()
        .append(yourGroup.length > 2 ? yourGroup.join('') : '')
        .append(hisGroup.length > 2 ? hisGroup.join('') : '')
        .selectmenu();
    }
    button#prevGame,
    span#currGame,
    button#nextGame,
    button#newGame {
      vertical-align: top;
    }
    select#games {
      width: 300px;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
    <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
    <link href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.min.css" rel="stylesheet" />
    
    <form>
      <select name="games" id="games"></select>
      <button id="prevGame">&lt;</button>
      <span id="currGame">Loading...</span>
      <button id="nextGame">&gt;</button>
    </form>