首页 > 解决方案 > JQuery Show/Hide multiple elements based on combined multiple data attributes and search field

问题描述

I have some html elements like this:

<div class="items">
    <div class="item" data-opt1="val1" data-opt2="val2,val3">Item 1</div>
    <div class="item" data-opt1="val4" data-opt2="val2,val5">Item 2</div>
    <div class="item" data-opt1="val1" data-opt2="val3,val6">Item 3</div>
    <div class="item" data-opt1="val7" data-opt2="val3,val5">Item 4</div>
</div>

and 2 variables to be used as filters, one array of options and one search string like this:

Example 1

var srcString = "val";

var filters = [
    'opt1' : ['val1'],
    'opt2' : ['val2','val6']
];

In this example item1 and item3 should be visible, item2 and item4 not visible.

Example 2

var srcString = "value";

var filters = [
    'opt1' : ['val1'],
    'opt2' : ['val2','val6']
];

All items shouldn't be visible, because var srcString contain a word that are not present in any of the data attributes.

Example 3

var srcString = "val6";

var filters = [];

Only item3 should be visible.

Example 4

var srcString = "";

var filters = [
    'opt1' : ['val1','val7'],
    'opt2' : ['val5']
];

Only item4 should be visible, because item1 and item3 (even if have opt1=val1) not have val5 in opt2.

Example 5

var srcString = "";

var filters = [
    'opt1' : ['val1','val7']
];

items: 1,3,4 should be visible.

I was able to make all of these filters work one by one, but problems comes when I try to combinate all of them.

Code for search:

$(".item").each(function(){
    var item = $(this);

    if (item.data('opt1').toLowerCase().indexOf(srcVal) >= 0 
        || item.data('opt2').toLowerCase().indexOf(srcVal) >= 0){
        item.removeClass('d-none');
    }else{
        item.addClass('d-none');
    }
});

Code for single filter:

var selectedOptions = filters['opt2'];

$(".item").each(function(){
    var item = $(this);
    let _options = item.data('opt2') + '';
    _options = _options.split(",");
    let found = _options.some(r=> selectedOptions.includes(r));
    if(found==true){
        item.removeClass('d-none');
    }else{
        item.addClass('d-none');
    }
})

Any help is appreciate

标签: javascriptjqueryarraysfiltershow-hide

解决方案


调整现有代码,您可以将第二次检查移动到第一次检查的通过内。

需要进行一些额外的检查,例如检查.opt2存在和具有值,但这些都是简单的检查。

  $(".item").each(function() {
    var item = $(this);

    if (item.data('opt1').toLowerCase().indexOf(srcString) >= 0 ||
      item.data('opt2').toLowerCase().indexOf(srcString) >= 0) {
      item.removeClass('d-none');

      var selectedOptions = filters['opt2'];
      if (selectedOptions != null) {

        let _options = item.data('opt2') + '';
        _options = _options.split(",");
        if (_options.length > 0) {
          let found = _options.some(r => selectedOptions.includes(r));
          if (found == true) {
            item.removeClass('d-none');
          } else {
            item.addClass('d-none');
          }
        }
      }

    } else {
      item.addClass('d-none');
    }
  });

小提琴:https ://jsfiddle.net/7t26n3pj/

注意:这使用提供的 OP 代码,因此与他们的示例不完全匹配,因为缺少检查opt1

您可以if (_available_) continue通过将检查移动到单独的函数中来删除以减少代码缩进,并为通过/不通过返回 true/false - 这也将允许您在以后添加新的过滤器。

function applyFilter(filter) {

  $(".item").each(function() {
    var item = $(this);

    if (passesFilter(item, filter))
      item.removeClass('d-none');
    else
      item.addClass('d-none');
  })
}

function passesFilter(item, filter) {

  if (item.data('opt1').toLowerCase().indexOf(filter.srcString) < 0 &&
    item.data('opt2').toLowerCase().indexOf(filter.srcString) < 0)

    return false;

  var selectedOptions = filter.filters['opt2'];
  if (selectedOptions == null) return true;

  let _options = item.data('opt2') + '';
  _options = _options.split(",");
  if (_options.length === 0) return true;

  let found = _options.some(r => selectedOptions.includes(r));
  return found;
}

// Examples
$("button").click(function() {
  var filter = $(this).data("filter");
  console.log(filter);
  applyFilter(filter);
});
.d-none { display:none; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="items">
  <div class="item" data-opt1="val1" data-opt2="val2,val3">Item 1</div>
  <div class="item" data-opt1="val4" data-opt2="val2,val5">Item 2</div>
  <div class="item" data-opt1="val1" data-opt2="val3,val6">Item 3</div>
  <div class="item" data-opt1="val7" data-opt2="val3,val5">Item 4</div>
</div>

<button type='button' data-filter='{"srcString":"val","filters":{"opt1":["val1"],"opt2":["val2","val6"]}}'>
test 1
</button>
<button type='button' data-filter='{"srcString":"value","filters":{"opt1":["val1"],"opt2":["val2","val6"]}}'>
test 2
</button>
<button type='button' data-filter='{"srcString":"val6","filters":{}'>
test 3
</button>
<button type='button' data-filter='{"srcString":"","filters":{"opt1":["val1", "val7"],"opt2":["val5"]}}'>
test 4
</button>
<button type='button' data-filter='{"srcString":"","filters":{"opt1":["val1", "val7"]}}'>
test 5
</button>


推荐阅读