Abhishek Tripathi
Abhishek Tripathi

Reputation: 1381

document.getElementsByClassName() not working properly?

I am finding all the nodes using evaluate() on particular xpath and then I am adding class to highlight those nodes but when i try to remove those classes to unhighlight those nodes its unhighlighting half only. Even the loop runs only half time.

i have made a fiddle to show. Can anybody tell me why is it unhighlighting only half ? HTML part :

<div id="div1">abcdefghi</div>
<div id="div4">abcdefghi</div>
<div id="div2">abcdefghi</div>
<div id="div3">abcdefghi</div>

JS part :

(function xpathTest()
{
  var nodesSnapshot = document.evaluate("//div", document, null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
 for ( var i=0 ; i < nodesSnapshot.snapshotLength; i++ )
 {
   nodesSnapshot.snapshotItem(i).classList.add('highlight_csspath_chosen');
 }
 var ele = document.getElementsByClassName("highlight_csspath_chosen");
 for(i=0;i<ele.length;i++)
 {
  alert(i);
  ele[i].classList.remove("highlight_csspath_chosen");
 }
 })();

CSS part :

.highlight_csspath_chosen{
background-color: #ff8533 !important;
outline: 1px solid #5166bb !important;
}

Upvotes: 0

Views: 668

Answers (2)

Himanshu Tanwar
Himanshu Tanwar

Reputation: 906

The ele variable is keeping reference of the DOM elements with class highlight_csspath_chosen. So as the loop progresses the length of ele also decreases.

For example,

length of ele is 4 at starting, and i=0

when you remove class from the 1st element, the length becomes 3 and i becomes 1 for next iteration, hence it refers to the 3rd element of the initial array

initial array = [A, B, C, D] and i = 0

class from A is removed,

array is updated to [B, C, D] // since only these elements now contain the class

i is now = 1 , i.e [C] //skipping [B]

therefore in every iteration 1 element is being skipped, hence half of the elements get updated.

check the solution in the fiddle

http://jsfiddle.net/Lrb8j22p/52/

var ele = document.getElementsByClassName("highlight_csspath_chosen"); 
ele = Array.prototype.slice.call(ele,0);

I have converted the ele into an array so that is doesn't refer to the DOM

Upvotes: 1

lobo
lobo

Reputation: 164

Javascript document.getElementsByClassName returns a live collection, which means that changes in the DOM are reflected in the collection. So for each iteration, the size of list decreases by 1, so ele.length is not constant. So the loop iterates twice instead of 4 times. You can replace it with a for-each loop.

for(var element : ele){
   ele.classList.remove("highlight_csspath_chosen");
}

For more information about live collection refer to Live Collection

Upvotes: 1

Related Questions