jquery - 如何使用多个选择过滤 jQuery 中的结果,包括日期范围?
问题描述
我正在尝试根据数据属性过滤结果。在大多数情况下,我认为我在那里(它适用于前 3 个选择器),但我在尝试将日期选择器纳入等式时遇到了麻烦。在这一点上,我对我的方法的质疑是完全正确的——如果需要,我可以更改 HTML——所以请随时提供更好的解决方案。
为了方便任何愿意帮助的人,这里是小提琴: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();
}
});
解决方案
因此,对于非日期项目,您的技术是计算应包含的元素的 jquery 选择器,然后将其应用于数据 div。
相当不错的方法是在构建“包含”变量时构建多个 jquery 过滤器。
对日期应用相同技术的困难在于,这会产生一个很难放入 jquery 选择器的范围测试。我的解决方案是构造一个符合条件的数据日期值数组,并在最后一步执行第二个过滤器。
这些变化是:
步骤 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 运行。因此,在 show() 操作中应用 dateInclude 过滤器作为第二步。
$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();
接下来的几行(下面)对过滤器进行操作,以确保它们都有一个值。如果不存在日期过滤器,我们会注入一个全匹配,对于其他选择框的“包含”过滤器也是如此。
include = (dateInclude.length > 0 && include === '' ? '*' : include);
dateInclude = (dateInclude.length === 0 ? ['*'] : dateInclude );
最后我们把它放在一起如下。
$statsSection.filter(include).filter(dateInclude.join()).show();
为了帮助可视化它,我在小提琴中添加了一些输出
例如,选择 server=NicNicFunGame 和 date=last 六个月会生成过滤器:
$statsSection.filter("[data-server='NicNicFunGame']").filter("[data-date='27/09/2019'],[data-date='03/07/2019']").show();
推荐阅读
- python - 如何在单元格之间打印一行带有单个空格的数据框?
- java - 我如何计算每个省有多少男性和女性,并且这些省按国家字母顺序排列?
- javascript - 在 javascript 中执行 http 请求响应
- php - 在 GCP App Engine 上安装 PHP 扩展
- r - R - 删除除最近日期以外的所有行?
- lua - 桌面模拟器中的 LUA 脚本
- regex - DFA 到 RE 的转换但是如果初始状态和最终状态相同怎么办?
- javascript - 在功能 cartNumbers 我收到此错误:Cannot set property 'textContent' of null at cartNumbers
- javascript - 将 if 语句脚本添加到电子表格的新行
- html - 如何使用 HTML CSS 在登录表单中创建弹出窗口?