0

I have the below code on a page on a shopify website, but the buttons wont change color when active. Seems to work fine when I try it on bootply but wont work withen shopify. The error I see in the console is Uncaught TypeError: "Cannot read property 'getElementsByClassName' of null""

<script>
  filterSelection("all")
  function filterSelection(c) {
    var x, i;
    x = document.getElementsByClassName("column");
    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(" ");
  }


  // Add active class to the current 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";
    });
  }
</script>
Medet Tleukabiluly
  • 11,662
  • 3
  • 34
  • 69
vermit25
  • 13
  • 5
  • 1
    probably `var btns = btnContainer.getElementsByClassName("btn");` is causing error. Check if `btnContainer` has value – Nidhin Joseph Aug 26 '19 at 02:12
  • modern day browsers have classList.add/remove() – epascarello Aug 26 '19 at 02:15
  • @NidhinJoseph How would I check if btnContainer has a value? – vermit25 Aug 26 '19 at 02:30
  • a simple if condition would do `if(btnContainer ) {var btns = btnContainer.getElementsByClassName("btn");}` – Nidhin Joseph Aug 26 '19 at 02:36
  • `document.addEventListener("DOMContentLoaded", function() { // Place class assigning code here });` - Its better to wait for DOM to completely load all elements - And then do manipulations over that – Nareen Babu Aug 26 '19 at 04:40
  • 1
    @user2932057 That's it! Thanks a lot. I would like to mark your answer as the correct one. Would you happen to also know why the "all" filter does not work while the others work fine? Actually on page load the "all" button shows nothing, but if I go another button and come back to the "all" button it then shows correctly – vermit25 Aug 26 '19 at 04:56
  • @vermit25 - Place filter selection function call also inside DOM Load – Nareen Babu Aug 26 '19 at 05:10

1 Answers1

1

Better to wait for DOM to completely load all elements - do manipulations after that

document.addEventListener("DOMContentLoaded", function() {  
// Place class assigning code here 
 // Add active class to the current 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";
});
}
// Place filter selection also inside DOM Load
filterSelection("all");
});  
Nareen Babu
  • 443
  • 1
  • 5
  • 13