构建复选框过滤器的最佳方式,以显示/隐藏基于多个data-*属性的元素

Best way to build checkbox filter to show/hide elements based on multiple data-* attributes

本文关键字:于多个 隐藏 data- 元素 属性 显示 过滤器 复选框 最佳 方式 构建      更新时间:2023-09-26

我试图建立一个复选框过滤器,将显示/隐藏基于这些元素上的多个数据*属性的元素。我已经做了几次尝试,但都没有达到我想要的过滤效果。

我做了一个简单的操作:

http://jsfiddle.net/7ez8o1ra/

$('input[type="checkbox"]').click(function() {
    var $checked = $('input[type="checkbox"]:checked');
    var $productItem = $('.productItem');
    if ($checked.length > 0) {
        $productItem.hide();
        $checked.each(function() {
            $('.productItem[data-level=' + this.value + ']').show();
            $('.productItem[data-price=' + this.value + ']').show();
            $('.productItem[data-network=' + this.value + ']').show();
        });
    } else {
        $productItem.show();
    }
});

我知道这段代码是不正确的,这就是我从头开始的地方。

我所追求的过滤是一个"answers"过滤器,你应用的过滤器越多,你通常得到的结果就越少。

例如,在小提琴中,如果你选择"gold",你只会得到金色的结果。如果你添加"银"过滤器,你会得到金和银,目前为止还不错。所以我在一个data-*属性中很好。

问题是,如果您添加另一个data-*过滤器,例如,选择黄金和白银,添加"网络A"过滤器。在这种情况下,我希望将结果过滤到金元素和银元素,并且金/银元素也具有网络A数据属性。

构建这种过滤的最佳方法是什么?当应用价格过滤器时,它会过滤更多的结果。

下面是一个基本的shell

$('input[type="checkbox"]').click(function() {
    var $checked = $('input[type="checkbox"]:checked');
    var $items = $('.productItem');
    var filters = {};
    if ($checked.length) {
        $('.productItem').hide();
        $checked.each(function() {
           filters[$(this).data('filter-type')] = $(this).val();
        });
        $items.each(function(i) {
            for (var key in filters) {
                if ($(this).data(key) == filters[key]) {
                    $(this).show();
                }
            }
        });
    } else {
        $('.productItem').show();
    }
});

让我看看能不能用一种简单的方式来解释。您试图完成的本质上是将过滤器映射到产品列表。对于每个过滤器,只显示与过滤器匹配的产品。为了实现这一点,我将筛选器存储为键/值对。过滤器的键是过滤器类型(级别、价格或网络),为了存储过滤器类型,我向每个复选框添加了一个数据属性data-filter-type。因此,对于过滤器类型为level的复选框,属性将是data-filter-type="level"。再加上现有的value属性,过滤器可以在JavaScript中整齐地表示为键/值对:

data-filter-type: value

因此,当用户选择过滤器"白金"answers"网络A"时,过滤器关联数组看起来像:

{
    level: platinum,
    network: networkA
}

现在可以在过滤器数组中运行一个基本循环,并针对包含这些过滤器之一的所有项。由于您的问题不明确,我假设您需要or关系,这意味着只需要将一个过滤器应用于该项目。如果您需要将所有选定的筛选器应用于每个项,则需要相应地修改代码。

这段代码的另一个问题是当过滤器被添加到过滤器数组时:

filters[$(this).data('filter-type')] = $(this).val();

这只在每个过滤器是唯一的情况下才会起作用,也就是说,每个过滤器只检查一个。例如,如果检查了两个级别的过滤器,则只应用第二个过滤器,因为键将被覆盖。您需要修改该部分以将两个值存储在同一键下。每个键的基本值数组就可以完成这项工作。

正如我所说,这是一个最小的例子。当然,您还需要解决更多的问题,但我概述的一般步骤是一个很好的起点。好运!

差点忘了小提琴链接!http://jsfiddle.net/7ez8o1ra/3/

我认为您需要向复选框添加一个额外的属性,以便在应用后续标准之前显式地为$productItem定义顶级过滤器。我还更改了你的UI。对于最终用户来说,隐藏过滤过的卡片似乎是一种惩罚性的用户体验,所以将卡片变灰(带有CSS不透明度样式)似乎更好,但也许只是我的看法……

<input type="checkbox" data-type="level" value="platinum" /> ...
<input type="checkbox" data-type="price" value="0-2" /> ...
<input type="checkbox" data-type="network" value="networkA" /> ...

$('input[type="checkbox"]').click(function() {
    var $checked = $('input[type="checkbox"]:checked');
    var $productItem = $('.productItem');
    var filters = [];
    var productFilter = '';
    if ($checked.length > 0) {
        $productItem.css('opacity',0.25);
        $checked.each(function() {
           dataType = $(this).attr('data-type');
           if (!filters[dataType]) filters[dataType] = [];  
           filters[dataType].push(this.value);
        });
        for(var filterType in filters) { 
            for (i in filters[filterType]) {
                productFilter += '[data-'+filterType+'="'+filters[filterType][i]+'"],';
            }
            productFilter = productFilter.replace(/,$/,'');
        }
        $productItem
            .filter(productFilter)
            .map(function() {
                $(this).css('opacity',1);
            });
    } else {
        $productItem.css('opacity',1);
    }
});

请参阅此处:https://jsfiddle.net/7ez8o1ra/35/