首页 > 解决方案 > 如何使用多个选择过滤 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();
    }
});

标签: jqueryfilterdate-range

解决方案


因此,对于非日期项目,您的技术是计算应包含的元素的 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();

在https://jsfiddle.net/JamesE442/qktfbp15/38/上查看我的工作小提琴


推荐阅读