-1

I'm using javascript to filter a bunch of divs on a page. I'm using this code to do the filtering and it's working well. I'm also using nth-child in css to create a responsive grid that removes the outer borders to make the appearance less blocky. However, the nth-child isn't recalculating when objects are filtered, so there are missing borders in the middle of the grid and extra borders on the edges, unless all divs are shown.

Does anyone have any suggestions on how to reapply/reload the css after one of the filter buttons is clicked?

filterSelection("all")
function filterSelection(c) {
  var x, i;
  x = document.getElementsByClassName("filterDiv");
  if (c == "all") c = "";
  // Add the "show" class (display:block) to the filtered elements, and remove the "show" class from the elements that are not selected
  for (i = 0; i < x.length; i++) {
    w3RemoveClass(x[i], "show");
    if (x[i].className.indexOf(c) > -1) w3AddClass(x[i], "show");
  }
}

// Show filtered elements
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];
    }
  }
}

// Hide elements that are not selected
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(" ");
}

// Add active class to the current control button (highlight it)
var btnContainer = document.getElementById("myBtnContainer");
var btns = btnContainer.getElementsByClassName("btn");
for (var i = 0; i < btns.length; i++) {
  btns[i].addEventListener("click", function() {
    var current = document.getElementsByClassName("active");
    current[0].className = current[0].className.replace(" active", "");
    this.className += " active";
  });
}

and the CSS

.filterDiv {
    border-top: none;
    height:215px;
    border: 1px #ddd solid;

}


.filterDiv:nth-child(4n+0) {
    border-right:none; 
}

.filterDiv:first-child {
    border-left:none; 
}
Seth
  • 1
  • 1

1 Answers1

0

I've read the code from w3schools which you provided. I'm guessing your problem is this concept that :nth-child doesn't exclude display: none children.

In other words, :nth-child( 2 ) in the below example is .second. regardless of it's display value:

<div class="container">

    <div class="first"></div>
    <div class="second"></div>
    <div class="third"></div>

</div>

so, if you make your .first item hidden, it doesn't make your .second item to be :first-child; it's still :nth-child( 2 ).

I hope this could clarify somethings for you.

mrReiha
  • 908
  • 6
  • 24
  • Hmm, yes, thanks. I found a post about using [jquery to detach](https://stackoverflow.com/questions/32355054/how-to-get-nth-child-selector-to-skip-hidden-divs/32372800) the hidden objects, and that works...sort of. There is crossover in the elements, ie one object can be in multiple categories, so when I detach I'm dropping items that should be displayed. In the W3schools example, I drop Mustangs from Cars because it's detached when I drop Animals – Seth Dec 12 '18 at 19:51