2016-04-22 39 views
1

JSFiddle此問題。getElementsByClassName顯示正確的長度,但不對第三個(最後一個)結果執行代碼

我有一個函數,當您更改下拉列表的值時執行。它選擇所有具有與select選項的值相對應的類名稱的元素。 (即「Ralph」選擇所有具有類別名稱「Ralph」的div元素)。

從那裏,我已經試圖遍歷類數組的東西(我不太好,編程詞彙)。我認爲它運作良好。然後我意識到,它會不是隱藏第三個「丹」元素。

從select下拉菜單中選擇另一個值後,它會隱藏它,然後再次選擇「Dan」。

控制檯中沒有錯誤,我可以看到。我試過以下內容:

  1. 將+1添加到IF語句的x.length中,試圖強制它再次執行它。

  2. 設置i = -1(愚蠢,我知道。擾流板,它沒有工作)。

在控制檯中,您會注意到我記錄了var x(包含類名稱)的初始長度。它正確地確定有3個「丹」元素。我很困惑,爲什麼它沒有隱藏最後一個。

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> 
+1

'getElementsByClassName'返回[實時的HTMLCollection](https://developer.mozilla.org/en/docs/Web/API/ HTMLCollection),這意味着它將隨着您更改DOM而發生變化。 – freefaller

+0

是的!謝謝。所以我應該把類名「數組」放入一個真正的數組中,然後遍歷它? – perkface

+0

這是有道理的,是的 – freefaller

回答

2

正如我在我的評論說... getElementsByClassName返回Live HTMLCollection這意味着它會改變你改變DOM

你最好的選擇是在處理它們之前將對象複製到數組中。事情是這樣的......

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"); 
    } 
} 

另一種選擇可能是要經過反向的元素...或創建一個while循環,看起來在數組中的第一項,直到沒有更多的項目。像這樣...

function filterName(n) { 
    var x = document.getElementsByClassName(n); 
    while (x.length > 0) { 
     x[0].setAttribute("class", "hidden"); 
    } 
} 
+1

快速,正確,比我目前試圖寫的更簡單的解決方案。謝謝! (我結束了第二次,像魅力一樣)。 – perkface

+1

不客氣 - 與你的其他項目祝好運:-) – freefaller

1

這是另一種使用一些不同API的解決方案。來源中對解釋和參考文獻進行了評論。

FIDDLE

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>

參考

  1. querySelector
  2. EventTarget
  3. querySelectorAll
  4. Converting a NodeList to an Array
  5. classList
相關問題