0

I'm working on a project where I have to filter some elements in a page. I could manage to do it, but I also have to change the width of the elements if they are filtered or not. For example, every element has a width of 100px, but I want every third having a width of 300px.

Each element showing has a class called show. What I did was to add the style of 300px on the .show. But when I filter it the width stays on the same element and not on the third .show.

This is my code at the moment:

filterSelection("all");

function filterSelection(c) {
  var x, i;
  x = document.getElementsByClassName("filterDiv");
  if (c == "all") c = "";
  for (i = 0; i < x.length; i++) {
    w3RemoveClass(x[i], "show");
    if (x[i].className.indexOf(c) > -1) w3AddClass(x[i], "show");
  }
}

function w3AddClass(element, name) {
  var i, arr1, arr2;
  arr1 = element.className.split(" ");
  arr2 = name.split(" ");
  for (i = 0; i < arr2.length; i++) {
    if (arr1.indexOf(arr2[i]) == -1) {
      element.className += " " + arr2[i];
    }
  }
}

function w3RemoveClass(element, name) {
  var i, arr1, arr2;
  arr1 = element.className.split(" ");
  arr2 = name.split(" ");
  for (i = 0; i < arr2.length; i++) {
    while (arr1.indexOf(arr2[i]) > -1) {
      arr1.splice(arr1.indexOf(arr2[i]), 1);
    }
  }
  element.className = arr1.join(" ");
}
.filterDiv {
      float: left;
      background-color: #2196f3;
      color: #ffffff;
      width: 100px;
      line-height: 100px;
      text-align: center;
      margin: 2px;
      display: none;
    }
    
    .show {
      display: block;
    }
    
    .show:nth-child(3n + 0) {
      width: 300px;
    }
<body>
  <h2>Filter DIV Elements</h2>

  <div id="myBtnContainer">
    <button class="btn active" onclick="filterSelection('all')">Show all</button>
    <button class="btn" onclick="filterSelection('cars')">Cars</button>
    <button class="btn" onclick="filterSelection('fruits')">Fruits</button>
    <button class="btn" onclick="filterSelection('colors')">Colors</button>
  </div>

  <div class="container">
    <div class="filterDiv cars">BMW</div>
    <div class="filterDiv colors fruits">Orange</div>
    <div class="filterDiv cars">Volvo</div>
    <div class="filterDiv colors">Red</div>
    <div class="filterDiv colors">Blue</div>
    <div class="filterDiv fruits">Melon</div>
    <div class="filterDiv fruits animals">Kiwi</div>
    <div class="filterDiv fruits">Banana</div>
    <div class="filterDiv fruits">Lemon</div>
  </div>

</body>

Does someone have a solution to fix that?

Thanks!

Manish
  • 4,692
  • 3
  • 29
  • 41
  • 1
    Possible duplicate of [How to get nth-child selector to skip hidden divs](https://stackoverflow.com/questions/32355054/how-to-get-nth-child-selector-to-skip-hidden-divs) – Manish Oct 04 '19 at 09:27

3 Answers3

0

I think the reason why the items are not displayed like you want is that you do not remove the items from the DOM but rather hide them with css. this does not affect the .show:nth-child(3n + 0) selector.

What I would do is to tell CSS specificly how the items inside "container" should look like. This can be done for example using a grid.

If you do not want to use a grid you could also remove the elements that should not be displayed from the DOM using javascript. This is not the best solution in my opinion though.

Janis Jansen
  • 996
  • 1
  • 16
  • 36
  • Thank you for your answer, but I'm using flexboxes in the real stuff, is it compatible with css grids? –  Oct 04 '19 at 11:47
0

What I understand is that, you want each element that is filtered to have a width of 300px, a solution to that could be: write a style:

.filtered {
width:300px;
}

and then use

$("[your-object]").toggleClass("filtered");

to apply the effect.

Salman Malik
  • 923
  • 6
  • 24
  • Thank you for your answer, this could work yeah, but your solution is jQuery right? I can not use it in this project... –  Oct 04 '19 at 11:19
0

A friend of mine helped me for a solution, it's working, so I'm just posting it for people looking for one:

CSS:

.filterDiv {
    float: left;
    background-color: #2196f3;
    color: #ffffff;
    width: 100px;
    line-height: 100px;
    text-align: center;
    margin: 2px;
    display: none;
}

.show {
    display: block;
}

.item1 {
    width: 300px;
}

.item2 {
    width: 150px;
}

JS:

filterSelection("all");
var count = 0;
function filterSelection(c) {
    clean();
    var x, i;
    x = document.getElementsByClassName("filterDiv");
    if (c == "all") c = "";
    for (i = 0; i < x.length; i++) {
        w3RemoveClass(x[i], "show");
        if (x[i].className.indexOf(c) > -1) w3AddClass(x[i], "show");
    }
}
function clean() {
    count = 0;
    document.querySelectorAll(".filterDiv").forEach(it => {
        it.classList.forEach(className => {
            className.startsWith("item") && it.classList.remove(className);
        });
    });
}
function w3AddClass(element, name) {
    var i, arr1, arr2;
    arr1 = element.className.split(" ");
    arr2 = name.split(" ");

    for (i = 0; i < arr2.length; i++) {
        if (arr1.indexOf(arr2[i]) == -1) {
            element.className += " " + arr2[i];
            element.classList.add(getNext());
        }
    }
}

function getNext() {
    if (!count) {
        count = 0;
    }

    if (count >= 6) {
        count = 1;
    } else {
        count += 1;
    }

    return "item" + count;
}

function w3RemoveClass(element, name) {
    var i, arr1, arr2;
    arr1 = element.className.split(" ");
    arr2 = name.split(" ");
    for (i = 0; i < arr2.length; i++) {
        while (arr1.indexOf(arr2[i]) > -1) {
            arr1.splice(arr1.indexOf(arr2[i]), 1);
        }
    }
    element.className = arr1.join(" ");
}

But thank you for your answers!