php 如何使用多个类通过复选框过滤div

km0tfn4u  于 2023-01-24  发布在  PHP
关注(0)|答案(2)|浏览(127)

我有一个从数据库表中获取产品的产品页面,我使用foreach来拉取每个产品&每个产品显示为一张卡片,并使用类来过滤它们。
问题是复选框过滤器不能正确处理多个值(类),如果我有2个类,过滤器只检测第一类,而不是所有类(过滤器)。
例如,如果我选中"Blue"复选框,我不会看到任何结果,因为JS正在搜索只有一个类("filt-blue")的div,但我需要它显示所有包含"filt-blue"的div以及可能添加的任何其他过滤器。
有关详细信息,请访问**JSFIDDLE**

function change() {
  var checkboxes = document.getElementsByClassName('checkbox');
  var chekboxInputs = Array.from(checkboxes).map(a => a.querySelector('input'));
  var allAreUnselected = chekboxInputs.every(function(elem) {
    return !elem.checked;
  });
  if (allAreUnselected) {
    chekboxInputs.forEach(function(input) {
      Array.from(document.querySelectorAll("." + input.getAttribute("rel"))).forEach(function(item) {
        item.style.display = 'block';
      });
    });
  } else {
    chekboxInputs.forEach(function(input) {
      Array.from(document.querySelectorAll("." + input.getAttribute("rel"))).forEach(function(item) {
        item.style.display = input.checked ? 'block' : 'none';
      });
    });
  }
}
change();
@media(max-width:768px){
   .card{
    width:100% !important;
    margin:12px 6px !important;
    }
  }
  .card {
  text-align:left;
  border-radius:4px;
  margin:24px;
  width:320px;
  min-height:340px;
  transition: all 0.2s;
  border:var(--image-select-border);
}
.cards {
  display: flex;
  flex-wrap: wrap;
  justify-content:center;
}
.card-body {
  flex: 1 1 auto;
  padding:12px;
}
.card-title {
  margin-bottom:16px;
  padding:12px;
}
@media(max-width:768px){
.card-img-top{
  width:240px !important;
}
}
@media(max-width:768px){
.filtbtn{
  width:90% !important;
  margin-left:5% !important;
  float:none !important;
}
}
.filterDiv {
  display: none;
}
.show {
  display: block;
}
@media(max-width:768px){
#opts{
  margin-left:5% !important;
}
}
.optsel{
  border-bottom:2px solid #0d6efd;
  border-top: none;
  border-left: none;
  border-right: none;
}
.sidebar {
  height:100%;
  width:0;
  position:fixed;
  z-index:1;
  top:76px;
  right:0;
  background-color:#111;
  overflow-x:hidden;
  transition: 0.5s;
  padding-top: 60px;
}
.sidebar a {
  padding:8px 12px;
  text-decoration: none;
  font-size:16px;
  color: #818181;
  display: block;
  transition: 0.3s;
}
.sidebar .closebtn {
  position: absolute;
  top: 0;
  margin-right:12px;
  font-size:18px;
  color:#222 !important;
  background-color:#fff;
  width:100%;
}
@media(max-width:768px){
  .closebtn{
    top:4px !important;
  }
}
.openbtn {
  font-size: 20px;
  cursor: pointer;
  background-color: #111;
  color: white;
  padding: 10px 15px;
  border: none;
}
.openbtn:hover {
  background-color: #444;
}
#main {
  transition: margin-right .5s; /* If you want a transition effect */
  padding: 20px;
}
/* On smaller screens, where height is less than 450px, change the style of the sidenav (less padding and a smaller font size) */
@media screen and (max-height: 450px) {
  .sidebar {padding-top: 15px;}
  .sidebar a {font-size: 22px;}
}
.optbtn{
  background-color:#fff;
  color: #222;
  cursor: pointer;
  padding:14px;
  width: 100%;
  border: none;
  text-align: left;
  outline: none;
  font-size: 16px;
  transition: 0.4s;
}
.accordion {
  background-color:#111;
  color: #fff !important;
  cursor: pointer;
  padding: 18px;
  width: 100%;
  border: none;
  text-align: left;
  outline: none;
  font-size: 15px;
  transition: 0.4s;
}
.notaccordion {
  background-color:#111;
  color: #fff !important;
  cursor: pointer;
  padding: 18px;
  width: 100%;
  border: none;
  text-align: center;
  outline: none;
  font-size:18px;
  transition: 0.4s;
  font-weight:bolder;
}
.active, .accordion:hover {
  opacity:0.9;
}
.accordion:after {
  content: '\002B';
  color: #777;
  font-weight: bold;
  float: right;
  margin-left: 5px;
}
.active:after {
  content: "\2212";
}
.filterpanel {
  padding:0 18px;
  background-color:#fff;
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.2s ease-out;
}
.checkbox{
  color:#222 !important;
  padding:12px 12px;
}
.checkbox-button {
  cursor: pointer;
}
.checkbox span{
  margin-left:12px;
}
.checkbox input[type=checkbox] {
    box-sizing: border-box;
    padding: 0;
}
.checkbox input {
    font-size: 1rem;
    line-height: 1.5;
    padding: 11px 23px;
    border: 1px solid black;
    border-radius: 0;
    outline: 0;
    background-color: transparent;
}
.checkbox-button__input {
    opacity: 0;
    position: absolute;
}
.checkbox-button__control {
    position: relative;
    display: inline-block;
    width: 20px;
    height: 20px;
    vertical-align: middle;
    background-color: inherit;
    color: #017b5f;
    border: 2px solid #666;
}
.checkbox-button__input:checked+.checkbox-button__control:after {
    content: "";
    display: block;
    position: absolute;
    top: 2px;
    left: 2px;
    width: 12px;
    height: 12px;
    background-color:#0d6efd;
}
.checkbox-button__input:checked+.checkbox-button__control {
    border-color:black;
    border:2px solid black;
}
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous" id="bootstrap-css">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.0/css/all.css" integrity="sha384-lZN37f5QGtY3VHgisS14W3ExzMWZxybE1SJSEsQp9S+oqd12jhcu+A56Ebc1zFSJ" crossorigin="anonymous">



<div class="filter">
  <div class="checkbox">
    <label class="checkbox-button">
      <input type="checkbox" class="checkbox-button__input" id="choice1-1" name="choice1" onchange="change()" rel="filt-blue">
      <span class="checkbox-button__control"></span>
    </label>
    <span><b>blue</b></span>
  </div>
</div>
<div class="filter">
  <div class="checkbox">
    <label class="checkbox-button">
      <input type="checkbox" class="checkbox-button__input" id="choice1-2" name="choice1" onchange="change()" rel="filt-red">
      <span class="checkbox-button__control"></span>
    </label>
    <span><b>red</b></span>
  </div>
</div>

<hr>

<div class="filter">
  <div class="checkbox">
    <label class="checkbox-button">
      <input type="checkbox" class="checkbox-button__input" id="choice1-1a" name="choice2" onchange="change()" rel="filt-long">
      <span class="checkbox-button__control"></span>
    </label>
    <span><b>long</b></span>
  </div>
</div>
<div class="filter">
  <div class="checkbox">
    <label class="checkbox-button">
      <input type="checkbox" class="checkbox-button__input" id="choice1-2a" name="choice2" onchange="change()" rel="filt-short">
      <span class="checkbox-button__control"></span>
    </label>
    <span><b>short</b></span>
  </div>
</div>



<div class="cards">

  <div class="card filt-blue filt-long">
    <h6 class="card-title"><b><?php echo $fetch['title'];?></b></h6>
    <center><img src="/images/products/<?php echo $fetch['Img'];?>" class="card-img-top" style="width:160px;margin:0 auto;"></center>
    <div class="card-body">
      <small><?php echo $fetch['detail'];?></small>
      <h6><b>Starting from - &pound;<?php echo $fetch['SFprice'];?></b></h6>
    </div>
  </div>

<div class="card filt-blue filt-short">
    <h6 class="card-title"><b><?php echo $fetch['title'];?></b></h6>
    <center><img src="/images/products/<?php echo $fetch['Img'];?>" class="card-img-top" style="width:160px;margin:0 auto;"></center>
    <div class="card-body">
      <small><?php echo $fetch['detail'];?></small>
      <h6><b>Starting from - &pound;<?php echo $fetch['SFprice'];?></b></h6>
    </div>
  </div>
  
</div>



<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
j5fpnvbx

j5fpnvbx1#

这段代码可以帮助你的过滤器考虑到多个类别。有几种过滤方式。例如,如果你有“long and blue”,你想只显示long and blue吗?或者你也想显示一个“Red Long”。这段代码考虑到了多个过滤器类别,但是是以逻辑OR的方式而不是AND逻辑。

<body>

<label>Blue</label>
<input type="checkbox" name="filter-blue" onchange="change()">

<label>Red</label>
<input type="checkbox" name="filter-red" onchange="change()">

<label>Long</label>
<input type="checkbox" name="filter-long" onchange="change()">

<label>Short</label>
<input type="checkbox" name="filter-short" onchange="change()">

<div class="cards">
    
    <p class="filter-blue">Blue Jeans</p>
    <p class="filter-blue">Blue Cups</p>
    <p class="filter-red">Red Shirt</p>
    <p class="filter-red">Red Shirt</p>
    <p class="filter-red filter-long">Long Red Shirt</p>
    <p class="filter-red filter-short">Short Red Shirt</p>
    <p class="filter-blue filter-long">Long Blue Shirt</p>
    <p class="filter-blue filter-short">Short Blue Shirt</p>

</div>

<script type="text/javascript">
    
function change() {

    // Step 1 - Get checked filters

    let checkboxes = document.querySelectorAll('input[type="checkbox"]'),
        filtered = [];

    checkboxes.forEach(checkbox => {
        if (checkbox.checked) {
            filtered.push(checkbox.name);
        }
    });

    // Step 2 - Show cards based on the filters
    let cards = document.querySelectorAll('.cards p');

    cards.forEach(card => {
        if (
            filtered.length === 0 || // If no filter is checked then show everything
            filtered.some(r => card.classList.contains(r)) // If the filter matches the cards class. Filter it.
        ) {
            card.style.display = 'block';
        } else {
            card.style.display = 'none';
        }
    });
}

</script>

</body>
um6iljoc

um6iljoc2#

为什么当前代码不起作用?

代码迭代每个input,找到所有与input匹配的卡片,第一个inputblue,代码迭代所有卡片,正确显示那些与blue匹配的卡片,然后继续下一次迭代。red复选框。没有匹配的牌,所以它们都立即隐藏。所以任何匹配的牌实际上都会显示,然后立即隐藏。

好吧,我们该如何解决它?

我的方法是:

  • 因为我们需要评估每张卡片的所有复选框,所以颠倒迭代的顺序--对于每张卡片,迭代每个复选框(而不是像你那样反过来);
  • 评估每个复选框:如果选中 * 并且 * 当前卡具有该属性,则将其标记为匹配,并继续选中其他复选框;
  • 但是如果这个复选框被选中了,而当前的卡片没有这个属性,就把它标记为不匹配,现在我们必须立即退出,这样以后的匹配就不会覆盖这个失败;
  • 在我们检查完所有的输入(或者在失败时退出)之后,根据我们匹配的最终状态显示或隐藏卡片;
function change() {
    var checkboxes = document.getElementsByClassName('checkbox');
    var chekboxInputs = Array.from(checkboxes).map(a => a.querySelector('input'));
    var allAreUnselected = chekboxInputs.every(function(elem) {
        return !elem.checked;
    });

    if (allAreUnselected) {
        chekboxInputs.forEach(function(input) {
            Array.from(document.querySelectorAll("." + input.getAttribute("rel"))).forEach(function(item) {
                item.style.display = 'block';
            });
        });

    } else {
        Array.from(document.querySelectorAll(".card")).forEach(function(card) {
            // console.log('Start card: ', card);
            let match = false;

            for (const input of chekboxInputs) {
                let attribute = input.getAttribute("rel");
                // console.log('processing input with rel:', attribute);

                if (input.checked && card.classList.contains(attribute)) {
                    // console.log('input is checked and card matches');
                    match = true;
                    
                } else if (input.checked && ! card.classList.contains(attribute)) {
                    // console.log('input is checked and card does not match');
                    match = false;
                    break;
                }
            }

            // console.log('done checking inputs, match is:', match);
            card.style.display = match ? 'block' : 'none';
        });
    }
}
change();
.card {
  border: 1px solid black;
}
<div class="checkbox">
    <input type="checkbox" name="choice1" onchange="change()" rel="filt-blue">
    <span><b>blue</b></span>
</div>

<div class="checkbox">
    <input type="checkbox" name="choice1" onchange="change()" rel="filt-red">
    <span><b>red</b></span>
</div>

<div class="checkbox">
    <input type="checkbox" name="choice2" onchange="change()" rel="filt-long">
    <span><b>long</b></span>
</div>

<div class="checkbox">
    <input type="checkbox" name="choice2" onchange="change()" rel="filt-short">
    <span><b>short</b></span>
</div>

<br><br>

<div class="cards">
    <div class="card filt-blue filt-long">
        <b>Blue Long</b>
    </div>

    <div class="card filt-blue filt-short">
        <b>Blue Short</b>
    </div>
</div>
注解
  • 分离HTML和JS通常被认为是一种好的做法。在这里,这意味着删除HTML中的内联onchange="change()",并将其替换为JS中的事件处理程序:
let checkbox = document.querySelector("input[name=checkbox]");
checkbox.addEventListener('change', change);
  • 如果你能创建一个minimal, complete, and verifiable example的问题,你会让别人更容易帮助你。在这种情况下,我花在这个问题上的大部分时间都在评估我可以剥离什么-很多HTML和大多数CSS类是不相关的。PHP显然不起作用,而且所有的CSS都不重要。Bootstrap、JQuery CSS或JS引用都不是必需的。当你去掉所有与问题无关的东西时,理解、调试和工作就容易多了。

相关问题