如何使用多个选择(包括日期范围)过滤 jQuery 中的结果?
How to filter results in jQuery with multiple selects, including a date range?
我正在尝试根据数据属性过滤结果。在大多数情况下,我认为我在那里(它适用于前 3 个选择器),但我在尝试将日期选择器纳入等式时遇到了麻烦。
在这一点上,我质疑我的方法是否完全正确 - 如果需要,我可以更改 HTML - 所以请随时提供更好的解决方案。
为了方便任何愿意提供帮助的人,这里是fiddle:https://jsfiddle.net/rnbx0c3j/
谢谢你
选择器:
<div id="stats_filter">
<div id="stats_filter_wrapper" class="grids">
<div class="grid-3 select-wrapper server first">
<label class="server">Server</label>
<select id="select-server">
<option value="all">All</option>
<option value="NicNicFunGame">NicNicFunGame</option>
<option value="GT3_races">GT3_races</option>
</select>
</div>
<div class="grid-3 select-wrapper track">
<label class="track">Track</label>
<select id="select-track">
<option value="all">All</option>
<option value="ks_brands_hatch">ks_brands_hatch</option>
<option value="Imola">Imola</option>
<option value="Spa">Spa</option>
</select>
</div>
<div class="grid-3 select-wrapper car">
<label class="car">Car</label>
<select id="select-car">
<option value="all">All</option>
<option value="ariel_atom_v8">ariel_atom_v8</option>
<option value="rr_caterham_academy_620r">rr_caterham_academy_620r</option>
<option value="ks_porsche_911_gt1">ks_porsche_911_gt1</option>
</select>
</div>
<div class="grid-3 select-wrapper date">
<label class="date">Date</label>
<select id="select-date">
<option value="all">All</option>
<option value="7">Last 7 days</option>
<option value="30">Last 30 days</option>
<option value="182">Last 6 months</option>
<option value="365">Last 12 months</option>
</select>
</div>
</div>
</div>
HTML待过滤
<div class="stats-section" id="sectionID_1" data-server="NicNicFunGame" data-track="ks_brands_hatch" data-date="27/09/2019" data-car="ariel_atom_v8">sectionID_1</div>
<div class="stats-section" id="sectionID_2" data-server="NicNicFunGame" data-track="Imola" data-date="03/07/2019" data-car="rr_caterham_academy_620r">sectionID_2</div>
<div class="stats-section" id="sectionID_3" data-server="GT3_races" data-track="Spa" data-date="14/01/2019" data-car="ariel_atom_v8, ks_porsche_911_gt1">sectionID_3</div>
JS
var $select = $('#stats_filter select');
var $statsSection = $('.stats-section');
$select.change(function () {
var include = '';
var exclude = [];
var showAll = true;
var filterDate = false;
$select.each(function () {
var val = $(this).children(':selected').val();
if (val !== 'all') {
switch ($(this).prop('id')) {
case 'select-server':
include += "[data-server='" + val + "']";
break;
case 'select-track':
include += "[data-track='" + val + "']";
break;
case 'select-car':
include += "[data-car*='" + val + "']";
break;
case 'select-date':
var selectedDate = new Date(new Date().setDate(new Date().getDate() - val));
var dd = selectedDate.getDate();
var mm = selectedDate.getMonth() + 1;
var yyyy = selectedDate.getFullYear();
if (dd < 10) {
dd = '0' + dd;
}
if (mm < 10) {
mm = '0' + mm;
}
selectedDate = dd + '/' + mm + '/' + yyyy;
//exclude when date is out of range
$statsSection.each(function () {
var sectionDate = $(this).data('date');
if (process(sectionDate) < process(selectedDate)) {
exclude.push("[data-date='" + sectionDate + "']");
}
exclude.join(',');
});
function process(date) {
var parts = date.split("/");
return new Date(parts[2], parts[1] - 1, parts[0]);
}
filterDate = true;
break;
}
showAll = false;
}
});
if (showAll) {
$statsSection.show();
} else {
//HOW TO DEAL WITH THE DATES??
if (filterDate == true) {
alert('the following dates should be excluded from the results: ' + exclude);
}
//this works for the non-date selectors
$statsSection.not($(include)).hide();
$statsSection.filter($(include)).show();
}
});
您可以将所有 stats-section
存储到对象数组中并使用 array filter
进行搜索
var t0 = performance.now();
var initialized = false;
var $select = $('#stats_filter select');
function initialize() {
mySelectors = [];
$statsSection = $('.stats-section');
console.log("First search will be costly");
$($statsSection).each(function (i, e) {
let temp = $(e).data();
temp.element = $(e);
let myDate = temp.date.split("/");
temp.date = new Date(myDate[1] + "/" + myDate[0] + "/" + myDate[2]).getTime();//fix date format and convert to timestamp
mySelectors.push(temp);
});
initialized = true;
}
$select.change(function () {
var t0 = performance.now();
if (!initialized)
initialize();
var result = mySelectors;
$select.each(function () {
var val = $(this).val(); //you don't need to search the selected child
if (val !== 'all') {
switch ($(this).prop('id')) {
case 'select-server':
result = result.filter(obj => {
return obj.server === val;
});
break;
case 'select-track':
result = result.filter(obj => {
return obj.track === val;
});
break;
case 'select-car':
result = result.filter(obj => {
return obj.car === val;
});
break;
case 'select-date':
var selectedDate = new Date(new Date().setDate(new Date().getDate() - val)).getTime(); // timestamp
result = result.filter(obj => {
return obj.date > selectedDate;
});
}
}
});
$($statsSection).hide();
$.each(result, function (i, e) {
$(e.element).show();
});
var t1 = performance.now();
console.log("Search performance " + (t1 - t0) + " milliseconds.");
});
var t1 = performance.now();
console.log("Initialize performance " + (t1 - t0) + " milliseconds.");
.grids { clear: both;max-width: 1920px;margin: 0;}
#stats_filter_wrapper .select-wrapper { width: 25%; float:left; }
#stats_filter_wrapper .select-wrapper label { overflow: hidden; font-weight: 700; }
#stats_filter_wrapper .select-wrapper select { display: block; font-size: 16px; color: #6a6d73; line-height: 1.3; padding: 8px 25px 5px 8px; width: 100%; max-width: 100%; box-sizing: border-box; margin: 0; }
.stats-section{padding:20px 0;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="stats_filter">
<div id="stats_filter_wrapper" class="grids">
<div class="grid-3 select-wrapper server first">
<label class="server">Server</label>
<select id="select-server">
<option value="all">All</option>
<option value="NicNicFunGame">NicNicFunGame</option>
<option value="GT3_races">GT3_races</option>
</select>
</div>
<div class="grid-3 select-wrapper track">
<label class="track">Track</label>
<select id="select-track">
<option value="all">All</option>
<option value="ks_brands_hatch">ks_brands_hatch</option>
<option value="Imola">Imola</option>
<option value="Spa">Spa</option>
</select>
</div>
<div class="grid-3 select-wrapper car">
<label class="car">Car</label>
<select id="select-car">
<option value="all">All</option>
<option value="ariel_atom_v8">ariel_atom_v8</option>
<option value="rr_caterham_academy_620r">rr_caterham_academy_620r</option>
<option value="ks_porsche_911_gt1">ks_porsche_911_gt1</option>
</select>
</div>
<div class="grid-3 select-wrapper date">
<label class="date">Date</label>
<select id="select-date">
<option value="all">All</option>
<option value="7">Last 7 days</option>
<option value="30">Last 30 days</option>
<option value="182">Last 6 months</option>
<option value="365">Last 12 months</option>
</select>
</div>
</div>
</div>
<div class="stats-section" id="sectionID_1" data-server="NicNicFunGame" data-track="ks_brands_hatch" data-date="27/09/2019" data-car="ariel_atom_v8">sectionID_1</div>
<div class="stats-section" id="sectionID_2" data-server="NicNicFunGame" data-track="Imola" data-date="03/07/2019" data-car="rr_caterham_academy_620r">sectionID_2</div>
<div class="stats-section" id="sectionID_3" data-server="GT3_races" data-track="Spa" data-date="14/01/2019" data-car="ariel_atom_v8, ks_porsche_911_gt1">sectionID_3</div>
因此,对于非日期项目,您的技术是计算 jquery select 或计算应包含的元素,然后将其应用于数据 div。
在构建 'include' 变量时构建多个 jquery 过滤器是一种很好的方法。
对日期应用相同技术的困难在于,这会产生难以放入 jquery selector 中的范围测试。我的解决方案是构造一个符合条件的数据日期值数组,并在最后一步执行第二个过滤器。
变化是:
步骤 1. 定义一个新变量:
var dateInclude = [];
第 2 步。在确定日期是否有效的部分,将有效值推入 dataInclude 过滤器数组
//exclude when date is out of range
$statsSection.each(function () {
var sectionDate = $(this).data('date');
if (process(sectionDate) > process(selectedDate)) {
dateInclude.push("[data-date='" + sectionDate + "']");
}
});
第 3 步:在输出部分,我们现在将 dateInclude 组合为第二个过滤器。请注意,您的初始过滤器以布尔值 AND 的形式运行,但日期过滤器必须以布尔值 OR 的形式运行。因此,dateInclude 过滤器作为第二步应用于 show() 操作。
$statsSection.hide();
include = (dateInclude.length > 0 && include === '' ? '*' : include);
dateInclude = (dateInclude.length === 0 ? ['*'] : dateInclude );
$('#info').html(include + ' :: ' + dateInclude.join());
$statsSection.filter(include).filter(dateInclude.join()).show();
第一行(下)预先隐藏所有数据div。
$statsSection.hide();
下一行(下方)对过滤器进行操作以确保它们都有值。如果不存在日期过滤器,我们会注入一个全匹配项,对于其他 select 个框的 'include' 过滤器也是如此。
include = (dateInclude.length > 0 && include === '' ? '*' : include);
dateInclude = (dateInclude.length === 0 ? ['*'] : dateInclude );
最后我们将其汇总如下。
$statsSection.filter(include).filter(dateInclude.join()).show();
为了帮助可视化它,我在 fiddle
中添加了一些输出
例如,selecting server=NicNicFunGame 和 date=last six months 生成过滤器:
$statsSection.filter("[data-server='NicNicFunGame']").filter("[data-date='27/09/2019'],[data-date='03/07/2019']").show();
查看我的作品 fiddle
我正在尝试根据数据属性过滤结果。在大多数情况下,我认为我在那里(它适用于前 3 个选择器),但我在尝试将日期选择器纳入等式时遇到了麻烦。 在这一点上,我质疑我的方法是否完全正确 - 如果需要,我可以更改 HTML - 所以请随时提供更好的解决方案。
为了方便任何愿意提供帮助的人,这里是fiddle:https://jsfiddle.net/rnbx0c3j/
谢谢你
选择器:
<div id="stats_filter">
<div id="stats_filter_wrapper" class="grids">
<div class="grid-3 select-wrapper server first">
<label class="server">Server</label>
<select id="select-server">
<option value="all">All</option>
<option value="NicNicFunGame">NicNicFunGame</option>
<option value="GT3_races">GT3_races</option>
</select>
</div>
<div class="grid-3 select-wrapper track">
<label class="track">Track</label>
<select id="select-track">
<option value="all">All</option>
<option value="ks_brands_hatch">ks_brands_hatch</option>
<option value="Imola">Imola</option>
<option value="Spa">Spa</option>
</select>
</div>
<div class="grid-3 select-wrapper car">
<label class="car">Car</label>
<select id="select-car">
<option value="all">All</option>
<option value="ariel_atom_v8">ariel_atom_v8</option>
<option value="rr_caterham_academy_620r">rr_caterham_academy_620r</option>
<option value="ks_porsche_911_gt1">ks_porsche_911_gt1</option>
</select>
</div>
<div class="grid-3 select-wrapper date">
<label class="date">Date</label>
<select id="select-date">
<option value="all">All</option>
<option value="7">Last 7 days</option>
<option value="30">Last 30 days</option>
<option value="182">Last 6 months</option>
<option value="365">Last 12 months</option>
</select>
</div>
</div>
</div>
HTML待过滤
<div class="stats-section" id="sectionID_1" data-server="NicNicFunGame" data-track="ks_brands_hatch" data-date="27/09/2019" data-car="ariel_atom_v8">sectionID_1</div>
<div class="stats-section" id="sectionID_2" data-server="NicNicFunGame" data-track="Imola" data-date="03/07/2019" data-car="rr_caterham_academy_620r">sectionID_2</div>
<div class="stats-section" id="sectionID_3" data-server="GT3_races" data-track="Spa" data-date="14/01/2019" data-car="ariel_atom_v8, ks_porsche_911_gt1">sectionID_3</div>
JS
var $select = $('#stats_filter select');
var $statsSection = $('.stats-section');
$select.change(function () {
var include = '';
var exclude = [];
var showAll = true;
var filterDate = false;
$select.each(function () {
var val = $(this).children(':selected').val();
if (val !== 'all') {
switch ($(this).prop('id')) {
case 'select-server':
include += "[data-server='" + val + "']";
break;
case 'select-track':
include += "[data-track='" + val + "']";
break;
case 'select-car':
include += "[data-car*='" + val + "']";
break;
case 'select-date':
var selectedDate = new Date(new Date().setDate(new Date().getDate() - val));
var dd = selectedDate.getDate();
var mm = selectedDate.getMonth() + 1;
var yyyy = selectedDate.getFullYear();
if (dd < 10) {
dd = '0' + dd;
}
if (mm < 10) {
mm = '0' + mm;
}
selectedDate = dd + '/' + mm + '/' + yyyy;
//exclude when date is out of range
$statsSection.each(function () {
var sectionDate = $(this).data('date');
if (process(sectionDate) < process(selectedDate)) {
exclude.push("[data-date='" + sectionDate + "']");
}
exclude.join(',');
});
function process(date) {
var parts = date.split("/");
return new Date(parts[2], parts[1] - 1, parts[0]);
}
filterDate = true;
break;
}
showAll = false;
}
});
if (showAll) {
$statsSection.show();
} else {
//HOW TO DEAL WITH THE DATES??
if (filterDate == true) {
alert('the following dates should be excluded from the results: ' + exclude);
}
//this works for the non-date selectors
$statsSection.not($(include)).hide();
$statsSection.filter($(include)).show();
}
});
您可以将所有 stats-section
存储到对象数组中并使用 array filter
var t0 = performance.now();
var initialized = false;
var $select = $('#stats_filter select');
function initialize() {
mySelectors = [];
$statsSection = $('.stats-section');
console.log("First search will be costly");
$($statsSection).each(function (i, e) {
let temp = $(e).data();
temp.element = $(e);
let myDate = temp.date.split("/");
temp.date = new Date(myDate[1] + "/" + myDate[0] + "/" + myDate[2]).getTime();//fix date format and convert to timestamp
mySelectors.push(temp);
});
initialized = true;
}
$select.change(function () {
var t0 = performance.now();
if (!initialized)
initialize();
var result = mySelectors;
$select.each(function () {
var val = $(this).val(); //you don't need to search the selected child
if (val !== 'all') {
switch ($(this).prop('id')) {
case 'select-server':
result = result.filter(obj => {
return obj.server === val;
});
break;
case 'select-track':
result = result.filter(obj => {
return obj.track === val;
});
break;
case 'select-car':
result = result.filter(obj => {
return obj.car === val;
});
break;
case 'select-date':
var selectedDate = new Date(new Date().setDate(new Date().getDate() - val)).getTime(); // timestamp
result = result.filter(obj => {
return obj.date > selectedDate;
});
}
}
});
$($statsSection).hide();
$.each(result, function (i, e) {
$(e.element).show();
});
var t1 = performance.now();
console.log("Search performance " + (t1 - t0) + " milliseconds.");
});
var t1 = performance.now();
console.log("Initialize performance " + (t1 - t0) + " milliseconds.");
.grids { clear: both;max-width: 1920px;margin: 0;}
#stats_filter_wrapper .select-wrapper { width: 25%; float:left; }
#stats_filter_wrapper .select-wrapper label { overflow: hidden; font-weight: 700; }
#stats_filter_wrapper .select-wrapper select { display: block; font-size: 16px; color: #6a6d73; line-height: 1.3; padding: 8px 25px 5px 8px; width: 100%; max-width: 100%; box-sizing: border-box; margin: 0; }
.stats-section{padding:20px 0;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="stats_filter">
<div id="stats_filter_wrapper" class="grids">
<div class="grid-3 select-wrapper server first">
<label class="server">Server</label>
<select id="select-server">
<option value="all">All</option>
<option value="NicNicFunGame">NicNicFunGame</option>
<option value="GT3_races">GT3_races</option>
</select>
</div>
<div class="grid-3 select-wrapper track">
<label class="track">Track</label>
<select id="select-track">
<option value="all">All</option>
<option value="ks_brands_hatch">ks_brands_hatch</option>
<option value="Imola">Imola</option>
<option value="Spa">Spa</option>
</select>
</div>
<div class="grid-3 select-wrapper car">
<label class="car">Car</label>
<select id="select-car">
<option value="all">All</option>
<option value="ariel_atom_v8">ariel_atom_v8</option>
<option value="rr_caterham_academy_620r">rr_caterham_academy_620r</option>
<option value="ks_porsche_911_gt1">ks_porsche_911_gt1</option>
</select>
</div>
<div class="grid-3 select-wrapper date">
<label class="date">Date</label>
<select id="select-date">
<option value="all">All</option>
<option value="7">Last 7 days</option>
<option value="30">Last 30 days</option>
<option value="182">Last 6 months</option>
<option value="365">Last 12 months</option>
</select>
</div>
</div>
</div>
<div class="stats-section" id="sectionID_1" data-server="NicNicFunGame" data-track="ks_brands_hatch" data-date="27/09/2019" data-car="ariel_atom_v8">sectionID_1</div>
<div class="stats-section" id="sectionID_2" data-server="NicNicFunGame" data-track="Imola" data-date="03/07/2019" data-car="rr_caterham_academy_620r">sectionID_2</div>
<div class="stats-section" id="sectionID_3" data-server="GT3_races" data-track="Spa" data-date="14/01/2019" data-car="ariel_atom_v8, ks_porsche_911_gt1">sectionID_3</div>
因此,对于非日期项目,您的技术是计算 jquery select 或计算应包含的元素,然后将其应用于数据 div。
在构建 'include' 变量时构建多个 jquery 过滤器是一种很好的方法。
对日期应用相同技术的困难在于,这会产生难以放入 jquery selector 中的范围测试。我的解决方案是构造一个符合条件的数据日期值数组,并在最后一步执行第二个过滤器。
变化是:
步骤 1. 定义一个新变量:
var dateInclude = [];
第 2 步。在确定日期是否有效的部分,将有效值推入 dataInclude 过滤器数组
//exclude when date is out of range
$statsSection.each(function () {
var sectionDate = $(this).data('date');
if (process(sectionDate) > process(selectedDate)) {
dateInclude.push("[data-date='" + sectionDate + "']");
}
});
第 3 步:在输出部分,我们现在将 dateInclude 组合为第二个过滤器。请注意,您的初始过滤器以布尔值 AND 的形式运行,但日期过滤器必须以布尔值 OR 的形式运行。因此,dateInclude 过滤器作为第二步应用于 show() 操作。
$statsSection.hide();
include = (dateInclude.length > 0 && include === '' ? '*' : include);
dateInclude = (dateInclude.length === 0 ? ['*'] : dateInclude );
$('#info').html(include + ' :: ' + dateInclude.join());
$statsSection.filter(include).filter(dateInclude.join()).show();
第一行(下)预先隐藏所有数据div。
$statsSection.hide();
下一行(下方)对过滤器进行操作以确保它们都有值。如果不存在日期过滤器,我们会注入一个全匹配项,对于其他 select 个框的 'include' 过滤器也是如此。
include = (dateInclude.length > 0 && include === '' ? '*' : include);
dateInclude = (dateInclude.length === 0 ? ['*'] : dateInclude );
最后我们将其汇总如下。
$statsSection.filter(include).filter(dateInclude.join()).show();
为了帮助可视化它,我在 fiddle
中添加了一些输出例如,selecting server=NicNicFunGame 和 date=last six months 生成过滤器:
$statsSection.filter("[data-server='NicNicFunGame']").filter("[data-date='27/09/2019'],[data-date='03/07/2019']").show();
查看我的作品 fiddle