8

Follow up to my previous question - I want to use a button to show / hide multiple elements with the same class name using JS, yet it appears that I can only change the first element with a certain class name, and all further elements with the same class on the page are ignored.

How do I fix this?

	function designInfo() {
		document.getElementsByClassName("design")[0].style.display = "block";
		document.getElementsByClassName("it")[0].style.display = "none";
		document.getElementsByClassName("other")[0].style.display = "none";
	}

	function itInfo() {
		document.getElementsByClassName("design")[0].style.display = "none";
		document.getElementsByClassName("it")[0].style.display = "block";
		document.getElementsByClassName("other")[0].style.display = "none";
	}
	
	function allInfo() {
		document.getElementsByClassName("design")[0].style.display = "block";
		document.getElementsByClassName("it")[0].style.display = "block";
		document.getElementsByClassName("other")[0].style.display = "block";
	}
    .it {}
    .design {}
    .other {}

    .indent {
      margin: .5em 1em .5em 1em;
    }
    <button onclick="designInfo()">show design stuff</button>
    <button onclick="itInfo()">show IT stuff</button>
    <button onclick="allInfo()">show all</button>

    <div class="indent">

       <div class="it">• boring IT stuff</div>
       <div class="design">• cool design stuff</div>
       <div class="it">• it stuff and things</div>
       <div class="design">• design stuff</div>
       <div class="it">• it stuff and more</div>
       <div class="other">• more it stuff</div>
       <div class="other">• it stuff</div>
  
    </div>

10
  • Select all elements -> for each -> do stuff. Commented Feb 23, 2017 at 12:49
  • Select all elements? I thought that's what: getElementsByClassName would do, but I guess it doesn't... Commented Feb 23, 2017 at 12:51
  • Using [0] after your selection will get the first node and only the first node. Commented Feb 23, 2017 at 12:51
  • "Select all elements" == document.getElementsByClassName. Commented Feb 23, 2017 at 12:52
  • 1
    Or, do it properly, and don’t manipulate style values directly, but set a class only (separation of concerns). And if you make use of the descendant selector, you only need to set it once on a common ancestor element, instead of for each individual element. Commented Feb 23, 2017 at 12:53

6 Answers 6

14

You need to use a for-loop over all items you get from document.getElementsByClassName() method as in following snippet:

function setDisplay(className, displayValue) {
  var items = document.getElementsByClassName(className);
  for (var i=0; i < items.length; i++) {
    items[i].style.display = displayValue;
  }
}

function designInfo() {
  setDisplay("design", "block");
  setDisplay("it", "none");
  setDisplay("other", "none");
}

function itInfo() {
  setDisplay("design", "none");
  setDisplay("it", "block");
  setDisplay("other", "none");
}

function allInfo() {
  setDisplay("design", "block");
  setDisplay("it", "block");
  setDisplay("other", "block");
}
.it {}
.design {}
.other {}

.indent {
  margin: .5em 1em .5em 1em;
}
<button onclick="designInfo()">show design stuff</button>
<button onclick="itInfo()">show IT stuff</button>
<button onclick="allInfo()">show all</button>

<div class="indent">

   <div class="it">• boring IT stuff</div>
   <div class="design">• cool design stuff</div>
   <div class="it">• it stuff and things</div>
   <div class="design">• design stuff</div>
   <div class="it">• it stuff and more</div>
   <div class="other">• more it stuff</div>
   <div class="other">• it stuff</div>

</div>


Update Also, it could be written with less code as below:

function filter(designDisp, itDisp, otherDisp) {
  setDisplay("design", designDisp);
  setDisplay("it", itDisp);
  setDisplay("other", otherDisp);
}

function setDisplay(className, displayValue) {
  var items = document.getElementsByClassName(className);
  for (var i=0; i < items.length; i++) {
    items[i].style.display = (displayValue? "block" : "none");
  }
}
.it {}
.design {}
.other {}

.indent {
  margin: .5em 1em .5em 1em;
}
<button onclick="filter(1,0,0)">show design stuff</button>
<button onclick="filter(0,1,0)">show IT stuff</button>
<button onclick="filter(1,1,1)">show all</button>

<div class="indent">

   <div class="it">• boring IT stuff</div>
   <div class="design">• cool design stuff</div>
   <div class="it">• it stuff and things</div>
   <div class="design">• design stuff</div>
   <div class="it">• it stuff and more</div>
   <div class="other">• more it stuff</div>
   <div class="other">• it stuff</div>

</div>

Sign up to request clarification or add additional context in comments.

Comments

4

It would be best to do this with classes that show/hide the element. Your problem is you are using the first index [0] of the matched array. You need to loop through each element in the array to manipulate the element.

Something like this should do the trick:

let els = document.querySelectorAll('.myclass');

els.forEach(function(el) {
  el.classList.add('hidden');
});

You can do the same with el.classList.remove(className); to remove a class

Note: forEach is an ECMAScript 5 function

Comments

0

You're half way there:

Use this function and pass through the class name and either 'block' or 'none'

function toggle(className, state){
    elementArray = document.getElementsByClassName(className);

    for(var i = 0; i < elementArray.length; i++){
        elementArray[i].style.display = state;
    }
}

Comments

0

getElementsByClassName return an array of elements. You have to iterate them and update their style one by one

var elements = {
  design: document.getElementsByClassName("design"),
  it: document.getElementsByClassName("it"),
  other: document.getElementsByClassName("other")
};

function toggle(type) {
  Object.keys(elements).forEach(function(key) {
    var els = elements[key];
    var state = "none";
    if (key === type) state = "block";
    for (var i = 0; i < els.length; i++) {
      els[i].style.display = state;
    }
  });
}
.indent {
  margin: .5em 1em .5em 1em;
}
<button onclick="toggle('design')">show design stuff</button>
<button onclick="toggle('it')">show IT stuff</button>
<button onclick="toggle('other')">show all</button>

<div class="indent">
  <div class="it">• boring IT stuff</div>
  <div class="design">• cool design stuff</div>
  <div class="it">• it stuff and things</div>
  <div class="design">• design stuff</div>
  <div class="it">• it stuff and more</div>
  <div class="other">• more it stuff</div>
  <div class="other">• it stuff</div>
</div>

1 Comment

@escapetomars Wait a sec I will try to make it better
0

Easy solution, made together with jQuery. I've provided just one function, which accepts an argument, which is the name of the elements you want to leave in the list.

var elems = $('.indent').children('div');

function filter(v) {
  elems.filter(function() {
    $(this).show();
    if (!$(this).hasClass(v) && v) {
      $(this).hide();
    }
  });
}
.indent {
  margin: .5em 1em .5em 1em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button onclick="filter('design')">show design stuff</button>
<button onclick="filter('it')">show IT stuff</button>
<button onclick="filter()">show all</button>

<div class="indent">

  <div class="it">• boring IT stuff</div>
  <div class="design">• cool design stuff</div>
  <div class="it">• it stuff and things</div>
  <div class="design">• design stuff</div>
  <div class="it">• it stuff and more</div>
  <div class="other">• more it stuff</div>
  <div class="other">• it stuff</div>

</div>

Comments

0
var X = document.querySelectorAll(".className");

for (var i = 0; i < X.length; i++) {

    X[i].style.cssProperty = someNumber + "unitType";

}

Example: X[i].style.width = 100 + "%";

If you want it to apply random integers:

var X = document.querySelectorAll(".className");

for (var i = 0; i < X.length; i++) {

    var rand = Math.floor(Math.random() * someNumber);

    X[i].style.cssProperty = rand + "unitType";

}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.