显示与多个选定数据属性匹配的元素

Show elements matching multiple selected data attributes

我正在创建一组过滤器,一旦它们被 selected,相应的 div 应该基于被 selected 的所有属性显示。

我可以让它一次工作一个,但我的问题是试图让它们一起工作。我觉得一般来说可能有更好的方法?

这是我的 select 菜单:

<div class="filters">
 <select class="filter-location">
   <option value="" disabled="" selected="">Location</option>
   <option data-location="Remote">Remote – United States</option>
   <option data-location="Portland, OR">Portland, OR</option>
   <option data-location="Seattle, WA">Seattle, WA</option>
 </select>
 <select class="filter-team">
   <option value="" disabled="" selected="">Team</option>
   <option data-team="Sales">Sales</option>
   <option data-team="Support">Support</option>
   <option data-team="Management">Management</option>
 </select>
 <select class="filter-type">
   <option value="" disabled="" selected="">Type</option>
   <option data-type="Full-Time">Full-Time</option>
   <option data-type="Contract">Contract</option>
 </select>
</div>

这是我的 HTML 标记的简化版本:

<div class="job" data-team="Sales" data-location="Remote" data-type="Full-Time">
  <p>Job Content Here</p>
</div>
<div class="job" data-team="Management" data-location="Portland, OR" data-type="Contract">
  <p>Job Content Here</p>
</div>
<div class="job" data-team="Sales" data-location="Seattle, WA" data-type="Full-Time">
  <p>Job Content Here</p>
</div>

这是我的jQuery,一次显示一个过滤器:

<script type="text/javascript">
  jQuery(document).ready(function($) {
    $('.filters select').on('change', function() {

      var location_value = $(':selected', this).data('location');
      var team_value = $(':selected', this).data('team');
      var type_value = $(':selected', this).data('type');

      $('.job').hide();

      $(".job").each(function( index ) {
        if ($(this).data('location') == location_value) {
          $(this).show();
        }
        if ($(this).data('team') == team_value) {
          $(this).show();
        }
        if ($(this).data('work_type') == type_value) {
          $(this).show();
        }
      });

    });
  }); 
</script>

以下为每个 <select> 创建一个过滤器对象数组,其值如下所示:

[
  {
    "filter": "location",
    "value": "Remote"
  },
  {
    "filter": "team",
    "value": "Sales"
  }
]

然后它使用 Array#every() 来确保每个过滤器都与职位的 data- 属性相匹配,以确定是否显示它。

请注意,我使 <select> 元素更加通用,并为每个元素添加了一个 data-filter 属性,并且只在 <option> 元素上使用了 value

const $sels = $('.filters select'),
      $jobs = $('.job')

$sels.change(function(){
    const filters = $sels.filter(function(){
        return !!this.value
    }).map(function(){
       return {filter: $(this).data('filter'), value : this.value} 
    }).get();
    //console.log('Filters', filters)    
    
    // hide all jobs then filter the ones to show
    const $filterJobs = $jobs.hide().filter(function(){
        const data = $(this).data()
        return filters.every(function(obj){
           return data[obj.filter] === obj.value 
        });
    }).show(); 

    // toggle "no-match" depending on length of filter jobs collection
    $('#no-match').toggle( !$filterJobs.length )

});
.job, #no-match {
  display: none
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="filters">
  <select data-filter="location">
    <option value="">Location</option>
    <option value="Remote">Remote – United States</option>
    <option value="Portland, OR">Portland, OR</option>
    <option value="Seattle, WA">Seattle, WA</option>
  </select>
  <select data-filter="team">
    <option value="">Team</option>
    <option value="Sales">Sales</option>
    <option value="Support">Support</option>
    <option value="Management">Management</option>
  </select>
  <select data-filter="type">
    <option value="">Type</option>
    <option value="Full-Time">Full-Time</option>
    <option value="Contract">Contract</option>
  </select>
</div>
<div id="no-match">
   <h3>No Match</h3>
</div>

<div class="job" data-team="Sales" data-location="Remote" data-type="Full-Time">
  <p>Sales Remote Full Time</p>
</div>
<div class="job" data-team="Management" data-location="Portland, OR" data-type="Contract">
  <p>Management Portland Contract</p>
</div>
<div class="job" data-team="Sales" data-location="Seattle, WA" data-type="Full-Time">
  <p>Sales Seattle Full Time</p>
</div>