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

时间:2015-09-04 15:50:37

标签: javascript jquery checkbox filter filtering

我正在尝试构建一个复选框过滤器,该过滤器将根据这些元素上的多个data- *属性显示/隐藏元素。我已经做了几次尝试,但这些尝试都没有达到我想要的过滤效果。

我做了一个简单的小提琴:

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();
    }
});

我知道这段代码不正确,它就是我从一个小提琴开始从同一个墙上开始的地方。

我之后的过滤是"和"过滤您应用的过滤器越多,结果就越少。

例如,在小提琴中,如果你选择" gold"你只是获得金牌结果。如果你添加"银"过滤你获得金银,这是目前为止的好。因此,我在一个data- *属性中处于良好状态。

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

构建此类过滤的最佳方式是什么?因此,当应用价格过滤器时,它会过滤结果甚至更多?

2 个答案:

答案 0 :(得分:1)

以下是您想要做的基本外壳

$('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。因此,对于具有级别的过滤器类型的复选框,该属性将为data-filter-type="level"。与现有的value属性相结合,过滤器可以在JavaScript中作为键/值对整齐地表示:

data-filter-type: value

因此,当用户选择过滤器“platinum”和“network A”时,过滤器关联数组将如下所示:

{
    level: platinum,
    network: networkA
}

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

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

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

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

正如我所说,这是一个很小的例子。肯定会有更多需要修复的案例,但我概述的一般步骤对你来说是一个很好的起点。祝你好运!

几乎忘记了小提琴的链接! http://jsfiddle.net/7ez8o1ra/3/

答案 1 :(得分:1)

我认为在应用后续条件之前,您需要在复选框中添加一个额外的属性,以明确定义$ productItem的顶级过滤器。我也改变了你的用户界面。隐藏过滤后的卡片对你的终端用户来说似乎是惩罚性的用户体验,所以灰卡(带有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/