简体   繁体   English

jQuery 过滤多个数据属性

[英]jQuery Filtering Multiple Data Attributes

I have a list of cars for sale on my site, and five filters:我的网站上有一份待售汽车清单和五个过滤器:

  1. Make制作
  2. Model模型
  3. Year
  4. Mileage里程
  5. Price价格

...each with multiple options that users can filter by. ...每个都有多个用户可以过滤的选项。

When users check one or more options in the filter list, I need to hide the cars that don't match all of the selected filters.当用户检查过滤器列表中的一个或多个选项时,我需要隐藏与所有选定过滤器不匹配的汽车。

Here's the HTML for one of the cars:这是其中一辆车的 HTML:

<div class="home-car-div">
    <div class="home-car-description-div">
        <p class="home-car-info" data-year="2018" data-make="Ford" data-model="Escape" data-mileage="10000" data-price="18900">
            2018 Ford Escape
        </p>
    </div>
</div>

And here is one of the filters:这是过滤器之一:

<div class="car-filters">
    <div class="make-section">
        <p class="filter-title">Make</p>
        <div id="makeSection" data-group="make">
            <label class="filter-input">
                <input type="checkbox" name="make" class="make" value=“Ford”>Ford
            </label>
            <label class="filter-input">
                <input type="checkbox" name="make" class="make" value="Subaru"> Subaru
            </label>
        </div>
    </div>
</div>

I have followed some other questions on the site, and I seem to have most of this working.我在网站上关注了其他一些问题,我似乎已经完成了大部分工作。 Whenever the user checks one of the filter checkboxes, I get all the values for each attribute in arrays of key/value pairs:每当用户选中过滤器复选框之一时,我都会获取键/值对数组中每个属性的所有值:

var $filterCheckboxes = $( '.filter-input input' );

$filterCheckboxes.on( 'change', function() {
        
    $('.home-car-div').show();
        
    var selectedFilters = {};
            
    $filterCheckboxes.filter( ':checked' ).each( function() {
        
        if ( ! selectedFilters.hasOwnProperty( this.name ) ) {
            selectedFilters[ this.name ] = [];
        }
            
        selectedFilters[ this.name ].push( this.value );
        
    });
          
    $('.home-car-info').each(function() {
        var carMake = $(this).data('make');
        var carModel = $(this).data('model');
        var carYear = $(this).data('year');
        var carPrice = $(this).data('price');
        var carMileage = $(this).data('mileage');
                    
        var filteredMake = selectedFilters.make;
        var filteredModel = selectedFilters.model;
        var filteredYear = selectedFilters.year;
        var filteredPrice = selectedFilters.price;
        var filteredMileage = selectedFilters.mileage;
                
    });
        
});

So now I have variables for each of the cars' attributes, and variables of each of the filtered selections, but I now need to compare each of these, and somehow hide cars that aren't matching ALL of the attributes.所以现在我有每个汽车属性的变量,以及每个过滤选择的变量,但我现在需要比较每一个,并以某种方式隐藏与所有属性不匹配的汽车。

I'd also like to show a message if there are no results.如果没有结果,我还想显示一条消息。

Am I on the right track, and how do I do the filtering?我是否在正确的轨道上,我该如何进行过滤?

I believe that this is close to what you were after.我相信这与您所追求的很接近。 I used functional programing to perform actions on categories of data instead of individual elements.我使用函数式编程对数据类别而不是单个元素执行操作。 Doesn't really adhere to this requirement: "hide cars that aren't matching ALL of the attributes", because that requirement doesn't make sense for mutually exclusive properties such as "make" and "model".并不真正遵守此要求:“隐藏与所有属性不匹配的汽车”,因为该要求对于“制造”和“型号”等互斥属性没有意义。 Also removed some extraneous classes and used the "for" attribute on labels (see this ).还删除了一些无关的类并在标签上使用了“for”属性(请参阅)。

The implementation depends the assumption that a car matches a category if nothing in that category is selected.实现取决于这样的假设:如果没有选择任何类别,则汽车与类别匹配。

Note: There is an issue with JQuery that causes it's .data() method to be functionally different to the DOM's .dataset property, hence the use of this.dataset[category] instead of $(this).data(category) .注意:JQuery 存在一个问题,导致它的.data()方法在功能上与 DOM 的.dataset属性不同,因此使用this.dataset[category]而不是$(this).data(category) Technically this should also be better performance and is arguably more readable as well.从技术上讲,这也应该是更好的性能,并且可以说更具可读性。

 $(function() { $('#button').click(function() { // Create an map of category name to selected filters selectedFilters = $('.car-filters input:checked').get().reduce( function(a, c) { a[c.name] = (a[c.name] || []); a[c.name].push(c.value); return a }, {} ) // filter the list of cars displayed match = 0 unmatchedCars = $('.home-car-info').filter(function() { for (const category in selectedFilters) { // must match at least one in each category if (!selectedFilters[category].includes(this.dataset[category])) { console.log(`"${$(this).text().trim()}" does not match ${category} is in [${selectedFilters[category]}] (${category} is ${this.dataset[category]})`) return true } match++ } }); // do something with unmatchedCars unmatchedCars.hide() if (!match) { console.log("Nothing matches the selected filters") } }) $('#restore').click(function() { $('.home-car-info').show() $('input:checkbox').prop('checked', false) }) });
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <div class="home-car-div"> <div class="home-car-description-div"> <p class="home-car-info" data-year="2018" data-make="Ford" data-model="Escape" data-mileage="10000" data-price="18900"> 2018 Ford Escape </p> <p class="home-car-info" data-year="1998" data-make="Porsche" data-model="911" data-mileage="10000" data-price="72500"> 1998 Porsche 911 </p> </div> </div> <form> <div class="car-filters"> <div class="make-section"> <p >Make</p> <div id="makeSection" data-group="make"> <input type="checkbox" id="iaa" name="make" value="Ford"><label for="iaa">Ford</label> <input type="checkbox" id="iab" name="make" value="Subaru"><label for="iab">Subaru</label> <input type="checkbox" id="iab" name="make" value="Porsche"><label for="iac">Porsche</label> </div> <p >Model</p> <div id="makeSection" data-group="model"> <input type="checkbox" id="iba" name="model" value="T"><label for="iba">T</label> <input type="checkbox" id="ibb" name="model" value="Escape"><label for="ibb">Escape</label> <input type="checkbox" id="ibb" name="model" value="911"><label for="ibc">911</label> </div> </div> </div> <div> <button id="button" type="button">Filter</button> <button id="restore" type="button">Restore</button> </div> </form><br />

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM