jQuery(JS?)如何根据数组中的值过滤元素

时间:2014-01-21 22:39:47

标签: jquery arrays filtering

我在页面上有一系列要求用户能够过滤的元素。

元素具有存储在数据属性中的标签。我已将其设置为当用户单击过滤器区域中的一个标记名称(#filters)时,标记将添加到数组中。再次单击标记时,它将从数组中删除。

单击标记时,我希望jQuery扫描要过滤的元素(#elementstofilter)并隐藏那些没有当前保存在过滤器数组中的所有标记的元素。

过滤器是一个AND过滤器,因此如果选择了 Tag1 Tag2 ,它只会显示包含两个标签的元素(#d1和#d3在下面的例子中。)

我觉得解决方案可能很简单,但我很难找到答案。也许有一种更有效的方法可以完全做到这一点。

<ul id="filters">
<li data-filter="tag1">Tag1</li>
<li data-filter="tag2">Tag2</li>
<li data-filter="tag3">Tag3</li>
<li data-filter="tag4">Tag4</li>
<li data-filter="tag5">Tag5</li>
</ul>

<ul id="elementstofilter">
<li class="project" id="d1" data-tags="tag1 tag2 tag3 tag4 tag5"></li>
<li class="project" id="d2" data-tags="tag1"></li>
<li class="project" id="d3" data-tags="tag1 tag2 tag5"></li>
<li class="project" id="d4" data-tags="tag3 tag4"></li>
</ul>

这是我到目前为止的jQ。它还没有很多。

var filter=[]; // Array to hold filter values
$('#filters li').click(function() {
    var sel=$(this).attr('data-filter');
    if($(this).hasClass('sel')) { // Add or remove values from the filter
        filter.push(sel);
    } else {
        filter=$.grep(filter, function(value) {
            return value!=sel;
        });
    }
    if(filter.length==0) { // Show all projects if no filters are selected
        $('.project:hidden').show();
    } else { // At least one filter is on
        /*
        if all of the values in the filter are represented in the data-tags of a project
            if that project is hidden
                show that project
        else
            hide that project
        */
    }
});

4 个答案:

答案 0 :(得分:2)

更改您的代码以将您的代码用作类,以便您可以使用标准选择器。

过滤变得非常简单:

$('.project').hide().filter('.tag1,.tag2').show();

答案 1 :(得分:1)

这可能有点脏......请查看this fiddle

我已经摆脱了数组的想法(虽然这不是一个坏主意,所以不要误会我的意思)并且只使用简单的类来显示和隐藏。我相信有人会向你展示一种“更快”或“更好”的方式,甚至可能认为在某些情况下阵列会更快,但这就是我应对的方法。我还为你的所有项目lis添加了.show

假设我理解你所说的内容,我已经为点击的标签制作了jquery get标签

$('#filters li').click(function(){
   var tag = $(this).attr('data-filter');

这将存储点击标签的变量(就像你一样)

然后我遍历所有项目标签

$('.project').each(function(){

并编写一些代码以显示和隐藏它们,如果它们具有该标记

    var tags = $(this).attr('data-tags').split(" "); //Get all of the tag names and put them in an array called tags
    for(var i=0; i < tags.length; i++){ //Loop through all of the tags
        if(tags[i] == tag){ //if one of the tags == the tag
            if($(this).hasClass('show')){ //and if it is showing
                console.log("hide");
                $(this).removeClass("show").addClass("hide"); //hide it
            } else {
                console.log("show");
                $(this).removeClass("hide").addClass("show"); 
            }
        }
    }

答案 2 :(得分:1)

如果您愿意,请重定向到我为您的逻辑做的页面,如下所示:

var filters = [];
$("#filters").on("click", "li", function() {
    var $scope = $(this);
    var filterTag = $scope.data("filter");
    if ($scope.hasClass("sel-filter")) {
        filters = $.grep(filters, function(obj) {
            return filterTag != obj;
        });
        $scope.removeClass("sel-filter");
    } else {
        filters.push(filterTag);
        $scope.addClass("sel-filter");
    }

    if (filters.length === 0) {
        $(".project:hidden").show();
    } else {
        $("#elementstofilter").trigger("projectToFilter");
    }
});

$("#elementstofilter").bind("projectToFilter", function() {
    $.each($(".project", $(this)), function(i, obj) {
        var $obj = $(obj);
        var storeTags = $obj.data("tags").split(" ");
        var found = false;
        for (var j in filters) {
            if ($.inArray(filters[j], storeTags) == -1) {
                $obj.hide();
                found = true;
                break;
            }
        }

        if (!found) {
            $obj.show();
        }
    });
});

click here to see run result.

答案 3 :(得分:0)

这是一个坚持阵列的解决方案。它有点长,我确信它可以被压缩,但逻辑就在那里。 http://jsfiddle.net/csrow/PczUm/4/

var filter=[]; // Array to hold filter values 21270555
var matchCount=[]; //Array to hold matched count
$('.project').each(function(i){
    matchCount[i]=0;
});
var totalFilter=0;
$('#filters li').click(function() {
    var sel=$(this).attr('data-filter');
    if ($(this).css("color") == "rgb(255, 0, 0)") {
        $(this).css("color","black");
    } else {
        $(this).css("color","red");
    };
    if($.inArray(sel,filter)===-1) {
        filter.push(sel);
        totalFilter+=1;
        $('.project').each(function(i) {
            var target=$(this).attr('data-tags');
            if (target.indexOf(sel)>=0) {
                matchCount[i]+=1;
                if (matchCount[i] == totalFilter) {
                    $(this).css("display","none");
                } else {
                    $(this).css("display","list-item");
                };
            } else {
                $(this).css("display","list-item");
            };
        });
    } else {
        filter=$.grep(filter, function(value) {
            return value!=sel;
        });
        totalFilter -= 1;
        $('.project').each(function(i) {
            var target=$(this).attr('data-tags');
            if (target.indexOf(sel)>=0) {
                matchCount[i]-=1;
                if (matchCount[i] !== totalFilter || totalFilter == 0) {
                    $(this).css("display","list-item");
                } else {
                    $(this).css("display","none");
                };
            } else {
                if (matchCount[i] == totalFilter && totalFilter != 0) {
                    $(this).css("display","none");
                } else {
                    $(this).css("display","list-item");
                };
            };
        });    
    };
});