jayngs
jayngs

Reputation: 33

Product filter - Show results based on multiple checkboxes selected/deselected

I'm building a product filter to narrow down monitor choices based on specs such as resolution, response time, brand etc.

I have created divs for each result, the specs are classes.

Each checkbox has a value attribute. When checked this attribute is stored in the map object. This is so that when I deselect a checkbox, it is removed from the map object and visa versa.

The results of the map object are joined together with "." between and then stored in variable assignedTo, this is being logged so you can see which have been selected.

My problem now is how do I show all the divs that contain the classes stored in assignedTo?

I've tried using document.querySelectorAll and then looping through that by displaying block but there are two issues:

  1. I get an "Uncaught SyntaxError: Failed to execute 'querySelectorAll' on 'Document': '...' is not a valid selector"
  2. If I am successful in looping through and displaying each result, if I uncheck a box, how do I get that result to disappear?

$(document).ready(function() {
  $(':checkbox[type="checkbox"]').on('change', function() {
    var assignedTo = $(':checkbox[type="checkbox"]:checked').map(function() {
        return $(this).attr('value');
      })
      .get().join(".");
    console.log(assignedTo);
    document.querySelectorAll("div.result." + assignedTo).forEach(div => div.style.display = "block")
  });
});
.result {
  width: 100%;
  border: 1px solid black;
  padding: 20px;
  line-height: 20px;
  text-align: left;
  margin: 10px;
  float: left;
  font-size: 11px;
  color: #000;
  font-family: sans-serif;
  display: none;
}

div.results {
  width: 70%;
  display: inline;
  float: left;
  position: relative;
  padding-right: 10%;
}

div#filters {
  width: 20%;
  display: inline;
  float: left;
  position: relative;
}

.btn {
  background-color: #0077ce;
  color: #fff;
  font-weight: bold;
  border-radius: 10px;
  padding: 10px;
  display: inline-block;
  position: relative;
  float: right;
}

.btn:hover {
  cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>

<head>
  <title>Test</title>
</head>

<body>
  <h1>Find your monitor</h1>
  <div id="filters">
    <h3>Recommended For</h3>
    <ul class="recommended">
      <li>
        <input type="checkbox" value="home" id="filter-home" />
        <label for="filter-home">Home</label>
      </li>
      <li>
        <input type="checkbox" value="office" id="filter-office" />
        <label for="filter-office">Office</label>
      </li>
      <li>
        <input type="checkbox" value="gaming" id="filter-gaming" />
        <label for="filter-gaming">Gaming</label>
      </li>
    </ul>
    <h3>Size</h3>
    <ul class="-monitor-size">
      <li>
        <input type="checkbox" value="24inch" id="filter-24inch" />
        <label for="filter-24inch">24inch</label>
      </li>
      <li>
        <input type="checkbox" value="32inch" id="filter-32inch" />
        <label for="filter-32inch">32inch</label>
      </li>
      <li>
        <input type="checkbox" value="40inch" id="filter-40inch" />
        <label for="filter-40inch">40inch</label>
      </li>
    </ul>
    <h3>Resolution</h3>
    <ul class="monitor-resolution">
      <li>
        <input type="checkbox" value="1080p" id="filter-1080p" />
        <label for="filter-1080p">1080p</label>
      </li>
      <li>
        <input type="checkbox" value="4K" id="filter-4K" />
        <label for="filter-4K">4K</label>
      </li>
      <li>
        <input type="checkbox" value="5K" id="filter-5K" />
        <label for="filter-5K">5K</label>
      </li>
    </ul>
    <h3>Response Time</h3>
    <ul class="monitor-responsetime">
      <li>
        <input type="checkbox" value="1ms" id="filter-1ms" />
        <label for="filter-1ms">1ms</label>
      </li>
      <li>
        <input type="checkbox" value="5ms" id="filter-5ms" />
        <label for="filter-5ms">5ms</label>
      </li>
      <li>
        <input type="checkbox" value="10ms" id="filter-10ms" />
        <label for="filter-10ms">10ms</label>
      </li>

    </ul>
    <h3>Brand</h3>
    <ul class="monitor-brand">
      <li>
        <input type="checkbox" value="branda" id="filter-branda" />
        <label for="filter-branda">Brand A</label>
      </li>
      <li>
        <input type="checkbox" value="brandb" id="filter-brandb" />
        <label for="filter-brandb">Brand B</label>
      </li>
      <li>
        <input type="checkbox" value="brandc" id="filter-brandc" />
        <label for="filter-brandc">Brand C</label>
      </li>
      <li>
        <input type="checkbox" class="brandd" id="filter-brandd" />
        <label for="filter-brandd">Brand D</label>
      </li>
      <li>
        <input type="checkbox" value="brande" id="filter-brande" />
        <label for="filter-brande">Brand E</label>
      </li>
      <li>
        <input type="checkbox" value="brandf" id="filter-brandf" />
        <label for="filter-brandf">Brand F</label>
      </li>

    </ul>
  </div>
  <div class="results">
    <div class="result gaming monitor 32inch 4K 5ms branda">32inch 4K Monitor - Brand A <span class="btn">Order</span></div>
    <div class="result gaming monitor 32inch 4K 5ms branda">32inch 4K Monitor - Brand A <span class="btn">Order</span></div>
    <div class="result gaming monitor 32inch 5K 1ms brandb">32inch 5K Monitor - Brand B<span class="btn">Order</span></div>
    <div class="result gaming monitor 40inch 5K 1ms brandc">40inch 5K Monitor - Brand C<span class="btn">Order</span></div>
    <div class="result office monitor 24inch 1080p 10ms brandd">24inch 1080p Monitor - Brand D<span class="btn">Order</span></div>
    <div class="result home monitor 24inch 4K 5ms brandd">24inch 4K Monitor - Brand D <span class="btn">Order</span></div>


    <div class="result gaming monitor 32inch 5K 1ms brande">32inch 5K Monitor - Brand E<span class="btn">Order</span></div>
    <div class="result gaming monitor 40inch 5K 1ms brande">40inch 5K Monitor - Brand E<span class="btn">Order</span></div>
    <div class="result office monitor 24inch 1080p 10ms brande">24inch 1080p Monitor - Brand E<span class="btn">Order</span></div>
    <div class="result home monitor 24inch 4K 5ms brandf">24inch 4K Monitor - Brand F <span class="btn">Order</span></div>
    <div class="result home monitor 24inch 4K 5ms brandf">24inch 4K Monitor - Brand F <span class="btn">Order</span></div>
  </div>
</body>

</html>

Upvotes: 3

Views: 463

Answers (1)

vqf
vqf

Reputation: 2628

  1. querySelector has problems with selectors that start with a number. You can use the selectors if you escape the first number, in the code below r.replace(/^(\d)/, '\\3' + '$1 ').
  2. Since you are cycling through the selectors, you can just hide all the elements before showing the results. In the code below, document.querySelectorAll('div.result').forEach(div => div.style.display = "none"); just before the cycle.

I have also added a condition in case nothing is selected. In your code, it led to an error.

$(document).ready(function() {
  $(':checkbox[type="checkbox"]').on('change', function() {
    var assignedTo = $(':checkbox[type="checkbox"]:checked').map(function() {
    let r = $(this).attr('value');
    r = r.replace(/^(\d)/, '\\3' + '$1 ');
        return r;
      })
      .get().join(".");
    console.log(assignedTo);
    document.querySelectorAll('div.result').forEach(div => div.style.display = "none");
    if (assignedTo !== ""){
    document.querySelectorAll("div.result." + assignedTo).forEach(div => div.style.display = "block");
    }
  });
});
.result {
  width: 100%;
  border: 1px solid black;
  padding: 20px;
  line-height: 20px;
  text-align: left;
  margin: 10px;
  float: left;
  font-size: 11px;
  color: #000;
  font-family: sans-serif;
  display: none;
}

div.results {
  width: 70%;
  display: inline;
  float: left;
  position: relative;
  padding-right: 10%;
}

div#filters {
  width: 20%;
  display: inline;
  float: left;
  position: relative;
}

.btn {
  background-color: #0077ce;
  color: #fff;
  font-weight: bold;
  border-radius: 10px;
  padding: 10px;
  display: inline-block;
  position: relative;
  float: right;
}

.btn:hover {
  cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>

<head>
  <title>Test</title>
</head>

<body>
  <h1>Find your monitor</h1>
  <div id="filters">
    <h3>Recommended For</h3>
    <ul class="recommended">
      <li>
        <input type="checkbox" value="home" id="filter-home" />
        <label for="filter-home">Home</label>
      </li>
      <li>
        <input type="checkbox" value="office" id="filter-office" />
        <label for="filter-office">Office</label>
      </li>
      <li>
        <input type="checkbox" value="gaming" id="filter-gaming" />
        <label for="filter-gaming">Gaming</label>
      </li>
    </ul>
    <h3>Size</h3>
    <ul class="-monitor-size">
      <li>
        <input type="checkbox" value="24inch" id="filter-24inch" />
        <label for="filter-24inch">24inch</label>
      </li>
      <li>
        <input type="checkbox" value="32inch" id="filter-32inch" />
        <label for="filter-32inch">32inch</label>
      </li>
      <li>
        <input type="checkbox" value="40inch" id="filter-40inch" />
        <label for="filter-40inch">40inch</label>
      </li>
    </ul>
    <h3>Resolution</h3>
    <ul class="monitor-resolution">
      <li>
        <input type="checkbox" value="1080p" id="filter-1080p" />
        <label for="filter-1080p">1080p</label>
      </li>
      <li>
        <input type="checkbox" value="4K" id="filter-4K" />
        <label for="filter-4K">4K</label>
      </li>
      <li>
        <input type="checkbox" value="5K" id="filter-5K" />
        <label for="filter-5K">5K</label>
      </li>
    </ul>
    <h3>Response Time</h3>
    <ul class="monitor-responsetime">
      <li>
        <input type="checkbox" value="1ms" id="filter-1ms" />
        <label for="filter-1ms">1ms</label>
      </li>
      <li>
        <input type="checkbox" value="5ms" id="filter-5ms" />
        <label for="filter-5ms">5ms</label>
      </li>
      <li>
        <input type="checkbox" value="10ms" id="filter-10ms" />
        <label for="filter-10ms">10ms</label>
      </li>

    </ul>
    <h3>Brand</h3>
    <ul class="monitor-brand">
      <li>
        <input type="checkbox" value="branda" id="filter-branda" />
        <label for="filter-branda">Brand A</label>
      </li>
      <li>
        <input type="checkbox" value="brandb" id="filter-brandb" />
        <label for="filter-brandb">Brand B</label>
      </li>
      <li>
        <input type="checkbox" value="brandc" id="filter-brandc" />
        <label for="filter-brandc">Brand C</label>
      </li>
      <li>
        <input type="checkbox" class="brandd" id="filter-brandd" />
        <label for="filter-brandd">Brand D</label>
      </li>
      <li>
        <input type="checkbox" value="brande" id="filter-brande" />
        <label for="filter-brande">Brand E</label>
      </li>
      <li>
        <input type="checkbox" value="brandf" id="filter-brandf" />
        <label for="filter-brandf">Brand F</label>
      </li>

    </ul>
  </div>
  <div class="results">
    <div class="result gaming monitor 32inch 4K 5ms branda">32inch 4K Monitor - Brand A <span class="btn">Order</span></div>
    <div class="result gaming monitor 32inch 4K 5ms branda">32inch 4K Monitor - Brand A <span class="btn">Order</span></div>
    <div class="result gaming monitor 32inch 5K 1ms brandb">32inch 5K Monitor - Brand B<span class="btn">Order</span></div>
    <div class="result gaming monitor 40inch 5K 1ms brandc">40inch 5K Monitor - Brand C<span class="btn">Order</span></div>
    <div class="result office monitor 24inch 1080p 10ms brandd">24inch 1080p Monitor - Brand D<span class="btn">Order</span></div>
    <div class="result home monitor 24inch 4K 5ms brandd">24inch 4K Monitor - Brand D <span class="btn">Order</span></div>


    <div class="result gaming monitor 32inch 5K 1ms brande">32inch 5K Monitor - Brand E<span class="btn">Order</span></div>
    <div class="result gaming monitor 40inch 5K 1ms brande">40inch 5K Monitor - Brand E<span class="btn">Order</span></div>
    <div class="result office monitor 24inch 1080p 10ms brande">24inch 1080p Monitor - Brand E<span class="btn">Order</span></div>
    <div class="result home monitor 24inch 4K 5ms brandf">24inch 4K Monitor - Brand F <span class="btn">Order</span></div>
    <div class="result home monitor 24inch 4K 5ms brandf">24inch 4K Monitor - Brand F <span class="btn">Order</span></div>
  </div>
</body>

</html>

Upvotes: 1

Related Questions