JQuery 根据组合的多个数据属性和搜索字段显示/隐藏多个元素

Posted

技术标签:

【中文标题】JQuery 根据组合的多个数据属性和搜索字段显示/隐藏多个元素【英文标题】:JQuery Show/Hide multiple elements based on combined multiple data attributes and search field 【发布时间】:2021-10-13 19:15:44 【问题描述】:

我有一些像这样的 html 元素:

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

和 2 个用作过滤器的变量、一个选项数组和一个搜索字符串,如下所示:

示例 1

var srcString = "val";

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

在这个例子中 item1 和 item3 应该是可见的,item2 和 item4 是不可见的。

示例 2

var srcString = "value";

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

所有项目都不应该是可见的,因为 var srcString 包含的词在任何数据属性中都不存在。

示例 3

var srcString = "val6";

var filters = [];

只有 item3 应该是可见的。

示例 4

var srcString = "";

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

只有 item4 应该是可见的,因为 item1 和 item3(即使有 opt1=val1)在 opt2 中没有 val5。

示例 5

var srcString = "";

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

items: 1,3,4 应该是可见的。

我能够让所有这些过滤器一个一个地工作,但是当我尝试组合所有这些过滤器时就会出现问题。

搜索代码:

$(".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');
    
);

单个过滤器的代码:

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');
    
)

感谢您的帮助

【问题讨论】:

我能够让所有这些过滤器一个一个地工作,但是当我尝试组合所有这些过滤器时会出现问题。 - 请包括这个尝试,它可能会更新您的尝试比从头开始更容易。 您可以将第二个的内容(不是每个本身,anon-func)放在第一个的 if 中。 你能举个例子吗?我不明白你的意思.. 我希望代码能够适应,即使我将来必须添加更多属性来过滤.. if/else 是最好的方法? @freedomn-m 我明白你的意思.. 但我的第二个每个循环都基于单个静态数组“selectedOptions”。要组合它们,我需要使用我的数组“过滤器”,其中 opt2 索引可以存在或不存在... 根据您的代码,您的场景“1”也应该显示 Item2,因为您使用了 .some(又名“any”)并且“val2”匹配“val2” 【参考方案1】:

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

需要进行一些额外的检查,例如检查 .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>

【讨论】:

非常感谢您的帮助,但有些东西在方面不起作用。在测试 1 中,项目 2 不应该是可见的,因为过滤器 opt1 的选定值只有 val1,并且 item2 有 opt1=val4,即使 opt2 匹配......这就像 sql 中的 OR,可能我需要类似 AND 如前所述,它使用您的原始代码,该代码也选择了 item2 - 这是 _options.some(r =&gt; selectedOptions.includes(r)) 行,它指出至少需要匹配一个,而不是全部。您可能想将.some 更改为.every 是的,每个属性我至少需要一个(如果选择的话)。用 .every 改变 .some 不是解决方案

以上是关于JQuery 根据组合的多个数据属性和搜索字段显示/隐藏多个元素的主要内容,如果未能解决你的问题,请参考以下文章

根据选择值显示隐藏多个 div

快速组合多个搜索字段

使用单个搜索框组合文本框和下拉字段的 JQuery 搜索

如何在数据库字段中存储多个图像参考

在组合框中显示多个字段

jQuery Chosen:在同一页面上显示多个选择字段