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

myss37ts  于 2023-01-16  发布在  jQuery
关注(0)|答案(6)|浏览(162)

对于所有的jQuery英雄,我需要帮助!(再次)
我在网上找到了和我类似的问题,但到目前为止还没有答案:-/
我想用jquery isotope过滤一堆条目,我改编了插件主页上的组合过滤器示例,它工作正常,看起来像这样:

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

以及过滤器菜单的一些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>

我设置了一个小提琴演示3过滤器类别,可以组合:* * 一个
现在,我希望能够从每个类别中选择多个标记:
第1类:abc

    • 和**

第2类:abc

    • 和**

类别3:abc
desandro有一个check-box-example,但这不是我想要的,因为我想保持类别之间的AND条件。基本上我想要3个过滤器类别,每个类别都有一些复选框(或者链接,但我猜复选框更有用)。我认为两个例子中使用的方法完全不同,我不知道如何结合它们的功能。
我希望你明白我的意思,希望任何人都能帮我找到解决办法。
先谢了!

3qpi33ja

3qpi33ja1#

将多个过滤器类型与metafizzy同位素过滤一起使用需要多维数组来保存每个过滤器类型的数组。
有关完整的代码说明,请参阅我对this question的回答

nszi6y05

nszi6y052#

看这里
http://codepen.io/desandro/pen/btFfG
这和DrewT的答案是一样的,只是来自同位素小组。
所有你要做的,以过滤是把每个组下相同的对象

var filters = {}; // should be outside the scope of the filtering function
 
//filtering function
$a.click(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'));
})

现在,您所要做的就是调用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;
 }
ss2ws0br

ss2ws0br3#

以下是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/

mrfwxfqh

mrfwxfqh4#

我可以让它工作,但它不是那么简单,因为我想在第一个例子。我认为你需要记住几件事:
1.如果你想使用一个限制性的AND条件,那么我建议不要使用**"data-filter-value"选项。相反,把你的filter变量作为类**。那么,你需要在onclick事件中自己触发同位素函数。这是因为否则你将触发"default"同位素功能,当用户点击按钮,你将无法实现的限制性和提到。
1.在相同的方向上,你将需要使用新的变量名(所以新的类)为每一个嵌套的过滤器选项的组合你要使用。否则,我不认为其他的方式(目前)获得一个限制性的AND条件。

    • 这个关于限制性和非限制性AND子句的概念就像外部连接和内部连接的区别**,如果你想处理两个过滤器,一个是另一个的子过滤器,你应该使用这个概念。

一个例子是类似于电子书列表的东西,它可以按品牌过滤,另一个子过滤器基于它们所属的不同价格范围。
我在下面给你展示了一个代码示例,我在那里实现了这个想法,它可以给你一个暗示我的意思是什么:
超文本:

<!--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>

浏览器:

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

});
jdgnovmf

jdgnovmf5#

很抱歉重提这个问题,但是我最近遇到了同样的问题,并且(恕我直言)浪费了很多时间使用组合选择器来解决这个问题(将数组A中的每个类与数组B中的每个类组合起来,等等)。
使用一个过滤函数,它允许任意的复杂度,并且可能是所有重要情况的正确选择。
最重要的是,使用选择器没有任何性能优势(如果选择器被直接提供给querySelector或jQuery调用,您可能会想到这一点)。

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

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

tzcvj98z

tzcvj98z6#

不喜欢jQuery?我修改了http://codepen.io/desandro/pen/btFfG的代码,@Luke将其作为ESNext/Vanilla的答案发布。
我想我会把这个贴出来,因为这是一个相当值得一看的问题。
这里唯一的区别是,您必须自己创建HTML。

class Metafizzy {
constructor(isotope) {
    this.isotope = isotope; // pass Isotope
    this.filters = {};
}

run(optionsContainerID, filterDisplayID) {
    let options = document.getElementById(optionsContainerID);
    let filterDisplay = document.getElementById(filterDisplayID);
    
    // do stuff when checkbox change
    options.addEventListener('change', (event) => {
        let inputElem = event.target;
        this.manageInputElement(inputElem);
        
        let comboFilter = this.getComboFilter(this.filters);
        
        this.isotope.arrange({ filter: comboFilter });
        
        //console.log(comboFilter); // uncomment to see the current filter output
    });
}

manageInputElement(inputElem) {
    let _this = this;
    // get the closest matching parent, and it's attribute value
    let parent = inputElem.closest('.iso-option-set');
    let group = parent.getAttribute('data-group');
    // create array for filter group, if not there yet
    let filterGroup = this.filters[group];
    if ( ! filterGroup) {
        filterGroup = this.filters[group] = [];
    }
    
    let isAll = inputElem.classList.contains('iso-all');
    // reset filter group if the all box was checked
    
    if (inputElem.type === 'checkbox') {
        this.doCheckBoxStuff(inputElem, parent, group, filterGroup, isAll)
    } else if (inputElem.type === 'range') {
        console.log('is element type "range"')
    }
    
}

doCheckBoxStuff(checkbox, parent, group, filterGroup, isAll) {
    if (isAll) {
        delete this.filters[group];
        if ( ! checkbox.checked) {
            checkbox.checked = true;
        }
    }
    // index of
    let hasCheckboxValue = filterGroup.includes(checkbox.value);
    let index = hasCheckboxValue ? 1 : -1;
    
    if (checkbox.checked) {
        let selector = isAll ? 'input' : 'input.iso-all';
        let allButton = parent.querySelector(selector);
        if (allButton) {
            allButton.checked = false;
        }
        
        if ( ! isAll && hasCheckboxValue === false) {
            // add filter to group
            this.filters[group].push(checkbox.value);
        }
        
    } else if ( ! isAll) {
        // remove filter from group
        // gets the index of the property by value
        function findWithAttr(array, value) {
            for(let i = 0; i < array.length; i += 1) {
                if(array[i] === value) {
                    return i;
                }
            }
            return -1;
        }
        let startIndex = findWithAttr(this.filters[ group ], checkbox.value)
        
        this.filters[ group ].splice( startIndex, 1 );
        // if all boxes unchecked, check the iso-all
        if ( ! parent.querySelectorAll('input:not(.iso-all):checked').length) {
            parent.querySelector('input.iso-all').checked = true;
        }
    }
}

getComboFilter(filters) {
    let i = 0;
    let comboFilters = [];
    let message = [];
    
    for (let prop in filters) {
        message.push(filters[prop].join(' '));
        let 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 {
            let filterSelectors = [];
            // copy to fresh array
            let groupCombo = comboFilters.slice(0); // [ A, B ]
            // merge filter Groups
            for (let k = 0, len3 = filterGroup.length; k < len3; k++) {
                for (let 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++;
    }
    
    let comboFilter = comboFilters.join(', ');
    return comboFilter;
 }
}

下面是示例化它的方法:

<script>
    window.onload = function () {
        let element = document.getElementById('iso-filter-display');
        let iso = new Isotope(element, {
            // options
            itemSelector: '.iso-display-element'
        });
        let isoFilter = new Metafizzy(iso);
        isoFilter.run('iso-options-container','iso-filter-display')
    };
  </script>

相关问题