Reputation: 113
JSFiddle for this issue.
I've got a function that executes when you change the value of the dropdown. It selects all elements with the class name that corresponds with the value of the select option. (i.e. "Ralph" selects all div elements with the classname "Ralph").
From there, I've attemtped to iterate through the class array things (I'm not too great with programming vocabulary). I thought it was working great. Then I realized, that it will not hide the third "Dan" element.
It does hide it after I select another value from the select drop down, and then select "Dan" again.
There is no error in the console that I can see. I've tried the following:
Adding +1 to the x.length of the IF statement to try and force it to do it again.
Setting i = -1 (stupid, I know. Spoiler, it didn't work).
In the console, you'll note that I log the initial length of the var x (which holds the class names). It is correctly identifying that there are 3 "Dan" elements. I'm stumped as to why it's not hiding the last one.
JS:
var x;
function filterName(n) {
x = document.getElementsByClassName(n);
console.log(x.length);
for (i = 0; i < x.length; i++) {
x[i].setAttribute("class", "hidden");
}
}
HTML:
<div class="container">
<div class="names col-sm-12">
<form name="filterDB" action="POST">
<select id="filterName" name="filterName">
<option value="" disabled="" selected="">Filter by Employee: </option>
<option id="Ralph" name="name" value="Ralph">Ralph</option>
<option id="Dan" name="name" value="Dan">Dan</option>
<option id="Brady" name="name" value="Brady">Brady</option>
<option id="Abby" name="name" value="Abby">Abby</option>
</select>
</form>
</div>
<div class="col-md-2 col-md-offset-1">
<h4 class="titles">Monday</h4>
<hr>
<div class="Ralph">Name: Ralph<hr></div>
</div>
<div class="col-md-2">
<h4 class="titles">Tuesday</h4>
<hr>
<div class="Dan">Name: Dan<hr></div>
<div class="Dan">Name: Dan<hr></div>
</div>
<div class="col-md-2">
<h4 class="titles">Wednesday</h4>
<hr>
<div class="Brady">Name: Brady<hr></div>
</div>
<div class="col-md-2">
<h4 class="titles">Thursday</h4>
<hr>
<div class="Abby">Name: Abby<hr></div>
</div>
<div class="col-md-2">
<h4 class="titles">Friday</h4>
<hr>
<div class="Dan">Name: Dan<hr></div>
</div>
<div class="clearfix"></div>
</div>
Upvotes: 1
Views: 472
Reputation: 43880
Here's another way to a solution utilizing some different APIs. The explanations and references are commented in the source.
SNIPPET
/* Footnotes at the end */
// Alt. var filter = document.querySelector('#filterName');¹
var filter = document.getElementById('filterName');
/* Use the Event Object to in order to determine event.target²
|| (the element that was clicked)
|| Event Object----------------------------⇲ */
filter.addEventListener("change", function(event) {
// Save event.target's value in the variable 'employee'
var employee = event.target.value;
// Call filterName and pass in 'employee'
filterName(employee);
}, false);
function filterName(name) {
// Alt. nodeNames = document.querySelectorAll('.' + name);³
var nameNodes = document.getElementsByClassName(name);
// Convert nodeNames to an array⁴
var nameArray = Array.prototype.slice.call(nameNodes);
console.log(nameArray.length);
/* Iterate through nameArray and on each iteration
|| use `classList.add`⁵ to add the .hidden class. */
for (var i = 0; i < nameArray.length; i++) {
nameArray[i].classList.add("hidden");
}
}
/* ¹ https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector
|| ² https://developer.mozilla.org/en-US/docs/Web/API/EventTarget
|| ³ https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll
|| ⁴ https://developer.mozilla.org/en-US/docs/Web/API/NodeList#Converting_a_NodeList_to_an_Array
|| ⁵ https://developer.mozilla.org/en-US/docs/Web/API/Element/classList */
.hidden {
display: none;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
<div class="container">
<div class="names col-sm-12">
<form name="filterDB" action="POST">
<select id="filterName" name="filterName">
<option value="" disabled="" selected="">Filter by Employee:</option>
<option id="Ralph" name="name" value="Ralph">Ralph</option>
<option id="Dan" name="name" value="Dan">Dan</option>
<option id="Brady" name="name" value="Brady">Brady</option>
<option id="Abby" name="name" value="Abby">Abby</option>
</select>
</form>
</div>
<div class="col-md-2 col-md-offset-1">
<h4 class="titles">Monday</h4>
<hr>
<div class="Ralph">Name: Ralph
<hr>
</div>
</div>
<div class="col-md-2">
<h4 class="titles">Tuesday</h4>
<hr>
<div class="Dan">Name: Dan
<hr>
</div>
<div class="Dan">Name: Dan
<hr>
</div>
</div>
<div class="col-md-2">
<h4 class="titles">Wednesday</h4>
<hr>
<div class="Brady">Name: Brady
<hr>
</div>
</div>
<div class="col-md-2">
<h4 class="titles">Thursday</h4>
<hr>
<div class="Abby">Name: Abby
<hr>
</div>
</div>
<div class="col-md-2">
<h4 class="titles">Friday</h4>
<hr>
<div class="Dan">Name: Dan
<hr>
</div>
</div>
<div class="clearfix"></div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
REFERENCES
Upvotes: 1
Reputation: 19953
As I said in my comment... getElementsByClassName
returns a Live HTMLCollection meaning that it will change as you change the DOM
Your best option would be to copy the objects into an array before you process them. Something like this...
function filterName(n) {
var x = document.getElementsByClassName(n);
var objs = [];
for (i = 0; i < x.length; i++) {
objs.push(x[i]);
}
for (i = 0; i < objs.length; i++) {
objs[i].setAttribute("class", "hidden");
}
}
Another option could be to go through the elements in reverse... or create a while loop that looks at the first item in the array until there are no more items. Something like this...
function filterName(n) {
var x = document.getElementsByClassName(n);
while (x.length > 0) {
x[0].setAttribute("class", "hidden");
}
}
Upvotes: 2