根据 optgroup 标签文本过滤选项
Filter options according to optgroup label text
我有一个 select 框,里面有游戏列表,另一个框里有控制台列表。每个游戏都有可能属于多个控制台。我希望根据第一个 selected 的游戏过滤第二个 select 框。
例如,如果我 select 一款像 Forza Horizon 这样的游戏属于多个控制台,那么控制台 select 框将只过滤那些并隐藏其他的。
现在我设置了它在 select 事件中捕获游戏文本值的位置。从那里我想通过他们各自的 optgroup 标签 属性 进行过滤,这是它所属的控制台。我似乎无法弄清楚如何检索它可能属于 selected 选项以外的其他可能的控制台。
<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();
}
});
});
这是你想要的吗?
$(".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);
});
});
我有一个 select 框,里面有游戏列表,另一个框里有控制台列表。每个游戏都有可能属于多个控制台。我希望根据第一个 selected 的游戏过滤第二个 select 框。
例如,如果我 select 一款像 Forza Horizon 这样的游戏属于多个控制台,那么控制台 select 框将只过滤那些并隐藏其他的。
现在我设置了它在 select 事件中捕获游戏文本值的位置。从那里我想通过他们各自的 optgroup 标签 属性 进行过滤,这是它所属的控制台。我似乎无法弄清楚如何检索它可能属于 selected 选项以外的其他可能的控制台。
<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();
}
});
});
这是你想要的吗?
$(".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);
});
});