根据 optgroup 标签文本过滤选项

Filter options according to optgroup label text

我有一个 select 框,里面有游戏列表,另一个框里有控制台列表。每个游戏都有可能属于多个控制台。我希望根据第一个 selected 的游戏过滤第二个 select 框。

例如,如果我 select 一款像 Forza Horizo​​n 这样的游戏属于多个控制台,那么控制台 select 框将只过滤那些并隐藏其他的。

现在我设置了它在 select 事件中捕获游戏文本值的位置。从那里我想通过他们各自的 optgroup 标签 属性 进行过滤,这是它所属的控制台。我似乎无法弄清楚如何检索它可能属于 selected 选项以外的其他可能的控制台。

Fiddle

<select class="game-select">
  <option value="">Select a game</option>
  <optgroup label="PS4"></optgroup>
    <option value="1">Forza Horizon 2</option>
    <option value="2">The Last of Us</option>
    <option value="3">Bioshock Infinite</option>
  </optgroup>
  <optgroup label="Xbox One">
    <option value="1">Forza Horizon</option>
    <option value="2">Halo</option>
    <option value="3">Bioshock Infinite</option>
  </optgroup>
</select>

<select class="console-select">
  <option value="">Select a console</option>
  <option value="1">PS4</option>
  <option value="2">Xbox One</option>
</select>

JS

$(function() {
  var gameConsoles = $(".console-select").html();

  $(".game-select").on("change", function() {
    var game    = $(this).find("option:selected").text(),
        options = gameConsoles.filter().html(); // Not sure how to filter
    if (options) {
      $(".console-select").html(options);
    } else {
      $(".console-select").empty();
    }
  });
});

更新 2

你可以这样做

$(function () {
    var consoleSelect = $('.console-select'),
        gameConsoleOptions = $('.console-select option');

    $(".game-select").on("change", function () {
        var selectedGame = $(this).find("option:selected").data('game'), 
            games = [],
            selectedCategory = $(this).find("option:selected").closest('optgroup').attr('label');
        if (selectedGame) {
            games = $.makeArray($(this).find('option[data-game="' + selectedGame + '"]').map(function () {
                return $(this).closest('optgroup').attr('label');
            }));
        }

        if (games.length) {
            gameConsoleOptions.hide();
            gameConsoleOptions.filter(function (i, v) {
                return games.indexOf($(v).text()) != -1;
            }).show();
            consoleSelect.find('option:contains('+selectedCategory+')').prop('selected', 'selected');
        } else {
            gameConsoleOptions.show();
        }
    });
});

这是一个演示 http://jsfiddle.net/dhirajbodicherla/m178xpc3/11/


更新

我使用 data-* 属性为每个游戏添加了代码。 例如下面两个游戏有相同的data-game属性,可以用来判断这两个是同一类别。

<option value="1" data-game="FH">Forza Horizon 2</option>
<option value="2" data-game="FH">Forza Horizon</option>

完整示例

<select class="game-select">
    <option value="">Select a game</option>
    <optgroup label="PS4">
        <option value="1" data-game="FH">Forza Horizon 2</option>
        <option value="2" data-game="LU">The Last of Us</option>
        <option value="3" data-game="BI">Bioshock Infinite</option>
    </optgroup>
    <optgroup label="Xbox One">
        <option value="1" data-game="FH">Forza Horizon</option>
        <option value="2" data-game="HA">Halo</option>
        <option value="3" data-game="BI">Bioshock Infinite</option>
    </optgroup>
</select>
<select class="console-select">
    <option value="">Select a console</option>
    <option value="1">PS4</option>
    <option value="2">Xbox One</option>
</select>

这是脚本

$(function () {
    var gameConsoleOptions = $('.console-select option');

    $(".game-select").on("change", function () {
        var selectedGame = $(this).find("option:selected").data('game'), games = [];
        console.log(selectedGame);
        if (selectedGame) {
            games = $.makeArray($(this).find('option[data-game="' + selectedGame + '"]').map(function () {
                return $(this).closest('optgroup').attr('label');
            }));
        }
        console.log(games);
        if (games) {
            gameConsoleOptions.hide();
            gameConsoleOptions.filter(function (i, v) {
                return games.indexOf($(v).text()) != -1;
            }).show();
        } else {
            gameConsoleOptions.show();
        }
    });
});

这是一个演示 http://jsfiddle.net/dhirajbodicherla/m178xpc3/10/


你可以这样做

$(function () {
    var gameConsoleOptions = $('.console-select option');

    $(".game-select").on("change", function () {
        var label = $(this).find("option:selected").closest('optgroup').prop('label');
        if (label) {
            gameConsoleOptions.hide();
            gameConsoleOptions.filter(function (i, v) {
                return $(v).text() === label;
            }).show();
        }else{
            gameConsoleOptions.show();
        }
    });
});

这是一个演示 http://jsfiddle.net/dhirajbodicherla/m178xpc3/5/

这是你想要的吗?

$(".game-select").on("change", function() {
  var o = $('option:selected', $(this));
  if (!o.val()) {
    $('.game-select optgroup').show();
    $('.console-select option').show();
    return;
  }
  $('.console-select > option').hide();
  var a = $('option:contains("' + o.text() + '")').filter(function() {
    return $(this).text() == o.text();
  }).each(function() {
    var t = $(this);
    var l = t.parent().attr('label');
    $('.console-select option:contains("' + l + '")').filter(function() {
      return l == $(this).text();
    }).show();
  });
});

$(".console-select").on("change", function() {
  var o = $('option:selected', $(this));
  if (!o.val()) {
    $('.game-select optgroup').show();
    $('.console-select option').show();
    return;
  }
  $('.game-select optgroup').hide();
  console.log($('.game-select optgroup[label="' + o.text() + '"]'));
  $('.game-select optgroup[label="' + o.text() + '"]').show();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select class="game-select">
  <option value="">Select a game</option>
  <optgroup label="PS4">
    <option value="c1">Forza Horizon 2</option>
    <option value="c2">The Last of Us</option>
    <option value="c3">Bioshock Infinite</option>
  </optgroup>
  <optgroup label="Xbox One">
    <option value="s1">Forza Horizon</option>
    <option value="s2">Halo</option>
    <option value="s3">Bioshock Infinite</option>
  </optgroup>
</select>

<select class="console-select">
  <option value="">Select a console</option>
  <div>
    <option value="c">PS4</option>
    <option value="s">Xbox One</option>
  </div>
</select>

代码应该不言自明,但这一切都归结为多个 jQuery 过滤函数和带有选项的集合的克隆。一个建议:使用数据属性而不是依赖选项元素文本。我更新了 fiddle,请参阅下面的 link。

$(function() {
      var gameConsoles = $(".console-select");
      var consoleOptions = gameConsoles.find('option').clone();
      var gameSelect = $(".game-select").on("change", function() {
          var game = $(this).find("option:selected").text();
          var filteredOptions = $();
          gameSelect.find('optgroup').filter(function() {
              return $(this).find('option').filter(function() {
                  return $(this).text() == game;
              }).length;
          }).each(function () {
              var label = $(this).attr('label');
              filteredOptions = filteredOptions.add(consoleOptions.filter(function() {
                  return $(this).text() == label;
              }));
           });
          gameConsoles.html(filteredOptions);
  });
});

Fiddle update