jQuery的多个复选框过滤多个(超过3个)类别

时间:2018-12-03 21:50:40

标签: javascript jquery checkbox filtering

我必须创建一个列出19门课程的页面。我想为其添加过滤功能,以允许访问者按不同特征(作业功能,日期,持续时间,位置,产品等)过滤课程。

我遇到了这个previous question on StackOverflow,它几​​乎可以解决我的问题。但是,该解决方案只有3套复选框,而我需要8套。

我在JSFiddle上有一些代码,可以过滤前三个类别,但超出的范围则无法过滤。

var byProperty = [],
  byColor = [],
  byLocation = [];

$("input[name=cat1]").on("change", function() {
  if (this.checked) byProperty.push("[data-category~='" + $(this).attr("value") + "']");
  else removeA(byProperty, "[data-category~='" + $(this).attr("value") + "']");
});

$("input[name=cat2]").on("change", function() {
  if (this.checked) byColor.push("[data-category~='" + $(this).attr("value") + "']");
  else removeA(byColor, "[data-category~='" + $(this).attr("value") + "']");
});

$("input[name=cat3]").on("change", function() {
  if (this.checked) byLocation.push("[data-category~='" + $(this).attr("value") + "']");
  else removeA(byLocation, "[data-category~='" + $(this).attr("value") + "']");
});

$("input").on("change", function() {
  var str = "Include items \n";
  var selector = '',
    cselector = '',
    nselector = '';

  var $lis = $('.courses > div'),
    $checked = $('input:checked');

  if ($checked.length) {

    if (byProperty.length) {
      if (str == "Include items \n") {
        str += "    " + "with (" + byProperty.join(',') + ")\n";
        $($('input[name=cat1]:checked')).each(function(index, byProperty) {
          if (selector === '') {
            selector += "[data-category~='" + byProperty.id + "']";
          } else {
            selector += ",[data-category~='" + byProperty.id + "']";
          }
        });
      } else {
        str += "    AND " + "with (" + byProperty.join(' OR ') + ")\n";
        $($('input[name=cat2]:checked')).each(function(index, byProperty) {
          selector += "[data-category~='" + byProperty.id + "']";
        });
      }
    }

    if (byColor.length) {
      if (str == "Include items \n") {
        str += "    " + "with (" + byColor.join(' OR ') + ")\n";
        $($('input[name=cat2]:checked')).each(function(index, byColor) {
          if (selector === '') {
            selector += "[data-category~='" + byColor.id + "']";
          } else {
            selector += ",[data-category~='" + byColor.id + "']";
          }
        });
      } else {
        str += "    AND " + "with (" + byColor.join(' OR ') + ")\n";
        $($('input[name=cat2]:checked')).each(function(index, byColor) {
          if (cselector === '') {
            cselector += "[data-category~='" + byColor.id + "']";
          } else {
            cselector += ",[data-category~='" + byColor.id + "']";
          }
        });
      }
    }

    if (byLocation.length) {
      if (str == "Include items \n") {
        str += "    " + "with (" + byLocation.join(' OR ') + ")\n";
        $($('input[name=cat3]:checked')).each(function(index, byLocation) {
          if (selector === '') {
            selector += "[data-category~='" + byLocation.id + "']";
          } else {
            selector += ",[data-category~='" + byLocation.id + "']";
          }
        });
      } else {
        str += "    AND " + "with (" + byLocation.join(' OR ') + ")\n";
        $($('input[name=cat3]:checked')).each(function(index, byLocation) {
          if (nselector === '') {
            nselector += "[data-category~='" + byLocation.id + "']";
          } else {
            nselector += ",[data-category~='" + byLocation.id + "']";
          }
        });
      }
    }

    $lis.hide();
    console.log(selector);
    console.log(cselector);
    console.log(nselector);

    if (cselector === '' && nselector === '') {
      $('.courses > div').filter(selector).show();
    } else if (cselector === '') {
      $('.courses > div').filter(selector).filter(nselector).show();
    } else if (nselector === '') {
      $('.courses > div').filter(selector).filter(cselector).show();
    } else {
      $('.courses > div').filter(selector).filter(cselector).filter(nselector).show();
    }

  } else {
    $lis.show();
  }

  $("#result").html(str);

});

function removeA(arr) {
  var what, a = arguments,
    L = a.length,
    ax;
  while (L > 1 && arr.length) {
    what = a[--L];
    while ((ax = arr.indexOf(what)) !== -1) {
      arr.splice(ax, 1);
    }
  }
  return arr;
}
body {
  font-family: 'Arial';
  color: #646464;
}

.filters-wrap {
  float: left;
  width: 20%;
  margin: 0 5% 0 0;
  padding: 0;
  position: relative;
}

.filters {
  float: left;
  width: 50%;
}

.filters div {
  float: left;
  width: 90%;
  height: 68px;
  line-height: 68px;
  padding: 0 5%;
  background: #eee;
  margin: 0 0 1px;
  position: relative;
}
<div class="filters-wrap">

  <h3>Category 1</h3>
  <form>
    <label><input type="checkbox" name="cat1" value="1-a" id="1-a" />1-A</label><br>
    <label><input type="checkbox" name="cat1" value="1-b" id="1-b" />1-B</label><br>
    <label><input type="checkbox" name="cat1" value="1-c" id="1-c" />1-C</label><br>
  </form>
  <h3>Category 2</h3>
  <form>
    <label><input type="checkbox" name="cat2" value="2-a" id="2-a" />2-A</label><br>
    <label><input type="checkbox" name="cat2" value="2-b" id="2-b" />2-B</label><br>
    <label><input type="checkbox" name="cat2" value="2-c" id="2-c" />2-C</label><br>
  </form>
  <h3>Category 3</h3>
  <form>
    <label><input type="checkbox" name="cat3" value="3-a" id="3-a" />3-A</label><br>
    <label><input type="checkbox" name="cat3" value="3-b" id="3-b" />3-B</label><br>
    <label><input type="checkbox" name="cat3" value="3-c" id="3-c" />3-C</label><br>
  </form>
  <h3>Category 4</h3>
  <form>
    <label><input type="checkbox" name="cat4" value="4-a" id="4-a" />4-A</label><br>
    <label><input type="checkbox" name="cat4" value="4-b" id="4-b" />4-B</label><br>
    <label><input type="checkbox" name="cat4" value="4-c" id="4-c" />4-C</label><br>
  </form>
  <h3>Category 5</h3>
  <form>
    <label><input type="checkbox" name="cat5" value="5-a" id="5-a" />5-A</label><br>
    <label><input type="checkbox" name="cat5" value="5-b" id="5-b" />5-B</label><br>
    <label><input type="checkbox" name="cat5" value="5-c" id="5-c" />5-C</label><br>
  </form>
  <h3>Category 6</h3>
  <form>
    <label><input type="checkbox" name="cat6" value="6-a" id="6-a" />6-A</label><br>
    <label><input type="checkbox" name="cat6" value="6-b" id="6-b" />6-B</label><br>
    <label><input type="checkbox" name="cat6" value="6-c" id="6-c" />6-C</label><br>
  </form>
  <h3>Category 7</h3>
  <form>
    <label><input type="checkbox" name="cat7" value="7-a" id="7-a" />7-A</label><br>
    <label><input type="checkbox" name="cat7" value="7-b" id="7-b" />7-A</label><br>
    <label><input type="checkbox" name="cat7" value="7-c" id="7-c" />7-A</label><br>
  </form>
  <h3>Category 8</h3>
  <form>
    <label><input type="checkbox" name="cat8" value="8-a" id="8-a" />8-A</label><br>
    <label><input type="checkbox" name="cat8" value="8-b" id="8-b" />8-B</label><br>
    <label><input type="checkbox" name="cat8" value="8-c" id="8-c" />8-C</label><br>
  </form>
</div>

<div class="courses">
  <div class="course" data-id="course01" data-category="1-a 2-b 4-c">Course 1 [cat 1A, 2B, 4C]</div>
  <div class="course" data-id="course02" data-category="3-c 6-b 7-c 8-a">Course 2 [cat 3C, 6BB, 7C, 8A]</div>
  <div class="course" data-id="course03" data-category="3-a 6-b 8-c">Course 3 [cat 3A, 6B, 8C]</div>
  <div class="course" data-id="course04" data-category="5-c 6-b">Course 4 [cat 5C, 6B]</div>
</div>

如何编辑包含其余类别(4-8)的代码?

谢谢!

1 个答案:

答案 0 :(得分:0)

也许我错过了一些重要的事情,但是除了对眼前的情况过于具体之外,原始代码有点太复杂了,并不必要地重复了代码(例如,它为每个类别和选择器定义了一个特定的数组)...这让我写了些不同的东西。

可以通过简化数组来简化整个过程,使它们更通用,因为可以使用数组数组来保存类别值,而不是使用单独变量中的数组。这样,如果要在过滤中添加/删除类别,则只需指定新的类别数,而不是为每个类别添加/删除数十行代码。

此外,如果您没有创建选择器(可能会很庞大),而只是更改了一点HTML并使用了不同的数据属性(每个类别有一个数据属性,而不是一个大数据属性)包含所有这些)。 注意:在编写答案时要考虑一下,此步骤可以是可选的。


这是我所做的更改的列表:

  1. 将复选框的值修改为仅包含字母,而不包含数字字母。这只是为了简化并遵循以下步骤。
  2. 将大数据类别细分为较小的数据类别(每个类别一个,并且仅在需要时)。这样做是为了“标准化”数据。
  3. 在样式...中添加了类.hidden,隐藏了添加元素的元素。

有了这些更改,(注释的)代码如下所示:

// constant: number of categories (this could be calculated if properly designed)
const NUM_CATEGORIES = 8;

// every time an option is clicked 
$("input[type='checkbox']").on("click", function() {

  // generate an array with the checked options per category
  let selected = new Array(NUM_CATEGORIES);
  // for each category
  for (let x = 0; x < NUM_CATEGORIES; x++) {
    // generate an array
    selected[x] = [];
    // populate it with the values of the checked options
    $("input[name=cat" + (x+1) + "]:checked").each(function() { 
      selected[x].push($(this).val());
    });
  }
  
  // for each course
  $(".course").each(function() {
    // by default it is going to be displayed
    let show = true;
    
    // we check all the categories
    for (let x = 0; x < NUM_CATEGORIES; x++) {
      // if they have a checked value
      if (selected[x].length) {
        // if the course has a value for that category
        if (this.dataset["cat-" + (x+1)]) {
          // convert the value into an array (in case there are multiple)
          var catValues = this.dataset["cat-" + (x+1)].split(",");
          // check if any of the values of the array is a selected category
          show = catValues.some(val => selected[x].indexOf(val) >= 0);
          // if not, hide and no need to keep checking
          if (!show) break;
        } 
        // if the course does not have a value for that checked category
        else {
          // hide and no need to keep checking
          show = false;
          break;
        }
      }
    }
    
    // hide or show depending on if it has fulfilled the condition
    $(this).toggleClass("hidden", !show);
  });
});
body {
  font-family: 'Arial';
  color: #646464;
}

.filters-wrap {
  float: left;
  width: 20%;
  margin: 0 5% 0 0;
  padding: 0;
  position: relative;
}

.filters {
  float: left;
  width: 50%;
}

.filters div {
  float: left;
  width: 90%;
  height: 68px;
  line-height: 68px;
  padding: 0 5%;
  background: #eee;
  margin: 0 0 1px;
  position: relative;
}

.courses {
  position: fixed;
  right: 10px;
  top: 50px;
}

.course.hidden {
  display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="filters-wrap">

  <h3>Category 1</h3>
  <form>
    <label><input type="checkbox" name="cat1" value="a" id="1-a" />1-A</label><br>
    <label><input type="checkbox" name="cat1" value="b" id="1-b" />1-B</label><br>
    <label><input type="checkbox" name="cat1" value="c" id="1-c" />1-C</label><br>
  </form>
  <h3>Category 2</h3>
  <form>
    <label><input type="checkbox" name="cat2" value="a" id="2-a" />2-A</label><br>
    <label><input type="checkbox" name="cat2" value="b" id="2-b" />2-B</label><br>
    <label><input type="checkbox" name="cat2" value="c" id="2-c" />2-C</label><br>
  </form>
  <h3>Category 3</h3>
  <form>
    <label><input type="checkbox" name="cat3" value="a" id="3-a" />3-A</label><br>
    <label><input type="checkbox" name="cat3" value="b" id="3-b" />3-B</label><br>
    <label><input type="checkbox" name="cat3" value="c" id="3-c" />3-C</label><br>
  </form>
  <h3>Category 4</h3>
  <form>
    <label><input type="checkbox" name="cat4" value="a" id="4-a" />4-A</label><br>
    <label><input type="checkbox" name="cat4" value="b" id="4-b" />4-B</label><br>
    <label><input type="checkbox" name="cat4" value="c" id="4-c" />4-C</label><br>
  </form>
  <h3>Category 5</h3>
  <form>
    <label><input type="checkbox" name="cat5" value="a" id="5-a" />5-A</label><br>
    <label><input type="checkbox" name="cat5" value="b" id="5-b" />5-B</label><br>
    <label><input type="checkbox" name="cat5" value="c" id="5-c" />5-C</label><br>
  </form>
  <h3>Category 6</h3>
  <form>
    <label><input type="checkbox" name="cat6" value="a" id="6-a" />6-A</label><br>
    <label><input type="checkbox" name="cat6" value="b" id="6-b" />6-B</label><br>
    <label><input type="checkbox" name="cat6" value="c" id="6-c" />6-C</label><br>
  </form>
  <h3>Category 7</h3>
  <form>
    <label><input type="checkbox" name="cat7" value="a" id="7-a" />7-A</label><br>
    <label><input type="checkbox" name="cat7" value="b" id="7-b" />7-A</label><br>
    <label><input type="checkbox" name="cat7" value="c" id="7-c" />7-A</label><br>
  </form>
  <h3>Category 8</h3>
  <form>
    <label><input type="checkbox" name="cat8" value="a" id="8-a" />8-A</label><br>
    <label><input type="checkbox" name="cat8" value="b" id="8-b" />8-B</label><br>
    <label><input type="checkbox" name="cat8" value="c" id="8-c" />8-C</label><br>
  </form>
</div>

<div class="courses">
  <div class="course" data-id="course01" data-cat-1="a" data-cat-2="b" data-cat-4="c">Course 1 [cat 1A, 2B, 4C]</div>
  <div class="course" data-id="course02" data-cat-3="c" data-cat-6="b,c" data-cat-7="c" data-cat-8="a">Course 2 [cat 3C, 6BC, 7C, 8A]</div>
  <div class="course" data-id="course03" data-cat-3="a" data-cat-6="b" data-cat-8="c">Course 3 [cat 3A, 6B, 8C]</div>
  <div class="course" data-id="course04" data-cat-5="c" data-cat-6="b">Course 4 [cat 5C, 6B]</div>
</div>