jQuery 同位素:组合过滤+多选

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17553076/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 19:17:33  来源:igfitidea点击:

Isotope: combination filtering + multiple selection

jqueryjquery-isotope

提问by Alani

To all jQuery heros out there, I need help! (again)

对于所有的 jQuery 英雄,我需要帮助!(再次)

I found similar questions to mine on the internet but there were no answers so far :-/

我在互联网上发现了类似的问题,但到目前为止还没有答案:-/

I want to filter a bunch of items with jquery isotope. I adapted the combination filter example from the plugin homepage, which works fine and looks like so:

我想用 jquery 同位素过滤一堆项目。我改编了插件主页上的组合过滤器示例,效果很好,看起来像这样:

$(function () {
var $container = $('#container'),
    filters = {};
$container.isotope({
    itemSelector: '.item',
    filter: '',
});

// filter links
$('.filter a').click(function () {
    var $this = $(this);
    // don't proceed if already selected
    if ($this.hasClass('selected')) {
        return;
    }

    var $optionSet = $this.parents('.option-set');
    // change selected class
    $optionSet.find('.selected').removeClass('selected');
    $this.addClass('selected');

    // store filter value in object
    // i.e. filters.color = 'red'
    var group = $optionSet.attr('data-filter-group');
    filters[group] = $this.attr('data-filter-value');

    // convert object into array
    var isoFilters = [];
    for (var prop in filters) {
        isoFilters.push(filters[prop])
    }
    var selector = isoFilters.join('');
    $container.isotope({
        filter: selector
    });
    return false;
}); });

and some html of the filter menu:

和过滤器菜单的一些html:

<div id="nav">
    <ul class="filter option-set" data-filter-group="who">
        <li><a href="#filter-who-any" data-filter-value="" class="selected">Any</a></li>
        <li><a href="#filter-who-boys" data-filter-value=".boys">Boys</a></li>
        <li><a href="#filter-who-girls" data-filter-value=".girls">Girls</a></li>
    </ul>

</div>

I set up a fiddle demo with 3 filter categories which can be combined: jsFiddle

我设置了一个带有 3 个可以组合的过滤器类别的小提琴演示:jsFiddle

Now I'd like to make it possible to select multipletags from each category:

现在我想让从每个类别中选择多个标签成为可能:

Category 1: a ORb ORc

第 1 类:abc

AND

Categoy 2: a ORb ORc

类别 2:abc

AND

Categoy 3: a ORb ORc

第 3 类:abc

There's a check-box-exampleby desandro, but this is not quite the thing I'm searching for, because I want to keep the AND condition between the categories. Basically I want 3 filter categories with some check-boxes for each of them (or links but I guess check-boxes are more functional). I think the methods used in both examples are completely different and I don't know how to combine their functionality.

desandro有一个复选框示例,但这不是我要搜索的内容,因为我想保留类别之间的 AND 条件。基本上我想要 3 个过滤器类别,每个类别都有一些复选框(或链接,但我想复选框更实用)。我认为两个示例中使用的方法完全不同,我不知道如何组合它们的功能。

I hope you get my point and that anyone could help me find a solution.

我希望你明白我的意思,任何人都可以帮助我找到解决方案。

Thanks in advance!

提前致谢!

回答by DrewT

Using multiple filter types with metafizzy isotope filtering requires a multi-dimensional array to hold an array of each filter type.

将多种过滤器类型与 metafizzy 同位素过滤一起使用需要一个多维数组来保存每个过滤器类型的数组。

I have a live example here

这里有一个活生生的例子

And js for the example is here

示例的 js 在这里

For a full code explanation see my answer to this question

有关完整的代码说明,请参阅我对这个问题的回答

回答by baaroz

have a look here

看看这里

http://codepen.io/desandro/pen/btFfG

http://codepen.io/desandro/pen/btFfG

it's the same answer by DrewT but from the Isotope team.

这是 DrewT 的相同答案,但来自 Isotope 团队。

all you have to do in order to filter is put every group under same object

为了过滤你所要做的就是把每个组放在同一个对象下

        var filters = {};//sould be outside the scope of the filtering function


  $a.click(function(){//filtering function
                var group = $optionSet.attr('data-filter-group');
             var filterGroup = filters[group];
                              if (!filterGroup) {
                                  filterGroup = filters[group] = [];
                              }
         filters[ group ].push($this.attr('data-filter-value'));
  })

now all you have to do is call getComboFilter function(you don't have to understand the code inside getComboFilter, think of it as a part of isotope)

现在你要做的就是调用 getComboFilter 函数(你不必理解 getComboFilter 里面的代码,把它当作同位素的一部分)

     var comboFilter = getComboFilter( filters );
 $container.isotope({ filter: comboFilter});

function getComboFilter( filters ) {
  var i = 0;
  var comboFilters = [];
  var message = [];

  for ( var prop in filters ) {
    message.push( filters[ prop ].join(' ') );
    var filterGroup = filters[ prop ];
    // skip to next filter group if it doesn't have any values
    if ( !filterGroup.length ) {
      continue;
    }
    if ( i === 0 ) {
      // copy to new array
      comboFilters = filterGroup.slice(0);
    } else {
      var filterSelectors = [];
      // copy to fresh array
      var groupCombo = comboFilters.slice(0); // [ A, B ]
      // merge filter Groups
      for (var k=0, len3 = filterGroup.length; k < len3; k++) {
        for (var j=0, len2 = groupCombo.length; j < len2; j++) {
          filterSelectors.push( groupCombo[j] + filterGroup[k] ); // [ 1, 2 ]
        }

      }
      // apply filter selectors to combo filters for next group
      comboFilters = filterSelectors;
    }
    i++;
  }

  var comboFilter = comboFilters.join(', ');
  return comboFilter;
}

回答by DevsLounge

Here is the JS Fiddle code you can follow for Isotope Combination Filterwith multiple select dropdown

这是您可以使用多个选择下拉列表的同位素组合过滤器的 JS Fiddle 代码

$(document).ready(function(){
  // init Isotope
  var $grid = $('.grid').isotope({
    itemSelector: '.item'
  });

  // store filter for each group
  var filters = {};

  $('.filters').on('change', '.filters-select', function(){
    var $this = $(this);
    var filterGroup = $this.attr('data-filter-group');
    filters[ filterGroup ] = $this.val();
    var filterValue = concatValues( filters );
    $grid.isotope({ filter: filterValue });
  });

  // flatten object by concatting values
  function concatValues( obj ) {
    var value = '';
    for ( var prop in obj ) {
      value += obj[ prop ];
    }
    return value;
  }
});

https://jsfiddle.net/srikanthLavudia/vhrbqn6p/

https://jsfiddle.net/srikanthLavudia/vhrbqn6p/

回答by Joar

I could make it work but it was not as straightforward as I thought in a firts instance. I think you need to bear on mind a couple of things:

我可以让它工作,但它并不像我在第一个实例中想象的那么简单。我认为您需要牢记以下几点:

  1. If you want to use a restrictive AND condition, then I suggest don′t use the "data-filter-value"option. Instead, put your filter variables as classes. Then, you will need to fire the isotope function by yourself in the onclick event. This is because otherwise you will fire the "default" isotope function when the user clicks the button and you won′t be able to achieve the restrictive AND mentioned.

  2. In the same direction, you will need to use new variable names (so new classes) for each combination of nested filter options you are going to work with. Otherwise, I don′t see other way (at the moment) to get a restrictive AND condition.

  1. 如果你想使用限制性的 AND 条件,那么我建议不要使用“data-filter-value”选项。相反,将您的过滤器变量作为 classes。然后,您需要在 onclick 事件中自行触发同位素函数。这是因为否则您将在用户单击按钮时触发“默认”同位素功能,并且您将无法实现上述限制性 AND。

  2. 在同一方向上,您将需要为要使用的嵌套过滤器选项的每个组合使用新的变量名称(即新类)。否则,我看不到其他方式(目前)获得限制性 AND 条件。

This concept about restrictive and nonrestrictive AND clauses is like the difference between an outer and an inner join. It's the concept you should use if you want to handle two filters, one subfilter of the other one.
One example would be something like a list of ebooks which could be filtered by brand, an other subfilter based on the different range prices they belong to.

这个关于限制性和非限制性 AND 子句的概念就像外连接和内连接之间的区别。如果您想处理两个过滤器,一个是另一个过滤器的子过滤器,那么您应该使用这个概念。
一个例子是可以按品牌过滤的电子书列表,另一个基于它们所属的不同范围价格的子过滤器。

I show you below a code example where I implement this idea, it can give you a hint of what i mean:

我在下面的代码示例中向您展示了我实现这个想法的地方,它可以让您了解我的意思:

HTML:

HTML:

<!--Filters section -->
<div id="filters">
    <ul id="optionSet1" class="option-set" data-option-key="filter">
           <li><a id="filter10" href="#filter" class="selected">Everything</a></li>
        <c:forEach var="brand" items="${brands}" varStatus="status" >
             <li><a id="filter1${status.count}" href="#filter" class='${brand}'>${brand}</a></li>
        </c:forEach>
    </ul>
    <ul id="optionSet2" class="option-set" data-option-key="filter">
        <li><a id="filter20" href="#filter" class="selected">Any Price</a>  </li>
    <c:forEach var="brandPrice" items="${brandPrices}" varStatus="status" >
        <li><a id="filter2${status.count}" href="#filter" class='${brandPrice}'>${brandPrice}</a></li>
    </c:forEach>
    </ul>
</div>  


<!--Elements to filter -->
<div id="portfolio-wrapper" class="row">
    <c:forEach var="publication" items="${publications}" varStatus="status" >               
        <div class='span4 portfolio-item ${publication.filterOption1} ${publication.filterOption2} ${publication.filterOption3}...'>
<!-- filterOption3 would be the combination of filterOption1 and filterOption2, you can make this building a string as the addition of filterOption1 and filterOption2 strings-->
            <!--Content to display-->           
    </c:forEach>
</div>

javascript:

javascript:

$(function(){

        $("a[id^='filter1']").on('click', function() {
//          alert($(this).attr('class'));
//          alert($('#optionSet2 .selected').attr('class'));
            var myclass = $('#optionSet2 .selected').attr('class');
            myclass = myclass.replace(' selected','');
            myclass = myclass.replace('selected','');
            var myclass2 = $(this).attr('class');
            myclass2 = myclass2.replace(' selected','');
            myclass2 = myclass2.replace('selected','');
            if($(myclass=='' && myclass2==''){
                $('#portfolio-wrapper').isotope({ filter: '*'});
            }else if(myclass==''){
                $('#portfolio-wrapper').isotope({ filter: '.'+ myclass2+'' });
            }else if(myclass2==''){
                $('#portfolio-wrapper').isotope({ filter: '.'+myclass+'' });
            }else{

                $('#portfolio-wrapper').isotope({ filter: '.'+myclass2+myclass+''});
            }   
        });

        $("a[id^='filter2']").on('click', function() {
//          alert($(this).attr('class'));
//          alert($('#optionSet1 .selected').attr('class'));
            var myclass = $('#optionSet1 .selected').attr('class');
            myclass = myclass.replace(' selected','');
            myclass = myclass.replace('selected','');
            var myclass2 = $(this).attr('class');
            myclass2 = myclass2.replace(' selected','');
            myclass2 = myclass2.replace('selected','');
            if(myclass=='' && myclass2==''){
                $('#portfolio-wrapper').isotope({ filter: '*'});
            }else if(myclass==''){
                $('#portfolio-wrapper').isotope({ filter: '.'+ myclass2+'' });
            }else if(myclass2==''){
                $('#portfolio-wrapper').isotope({ filter: '.'+myclass+'' });
            }else{

                $('#portfolio-wrapper').isotope({ filter: '.'+myclass+myclass2+''});
            }
        });

});

回答by Christoph Burschka

Sorry to dredge this question up, but I recently ran into the same problem and (imho) wasted a lot of time solving this with combined selectors. (Combine every class from array A with every class from array B, etc.)

很抱歉疏通这个问题,但我最近遇到了同样的问题,(恕我直言)浪费了很多时间用组合选择器解决这个问题。(将数组 A 中的每个类与数组 B 中的每个类组合,等等)

Use a filtering function. It allows arbitrary complexity and is probably the right choice for all non-trivial cases.

使用过滤功能。它允许任意复杂性,并且可能是所有非平凡情况的正确选择。

Most importantly, there is no performance benefit to using selectors (which you might expect if the selector were fed directly into a querySelectoror jQuery call). Isotope iterates through each item and applies the selector as a function regardless:

最重要的是,使用选择器没有性能优势(如果将选择器直接提供给querySelectorjQuery 或 jQuery 调用,您可能会期望这一点)。Isotope 遍历每个项目并将选择器作为函数应用,无论:

return function( item ) {
  return matchesSelector( item.element, filter );
};

Therefore, you might as well just put your filtering logic into a function instead of trying to generate a selector string.

因此,您不妨将过滤逻辑放入函数中,而不是尝试生成选择器字符串。