简体   繁体   中英

How to get the index of an element in a HTML collection when that element is clicked, using javascript

I have five buttons in my HTML file.

Seeing as they are five, I would like to be able to print the index of the specific button that has been clicked in the HTML collection. ie on tapping btn 4 I should see 3 printed. I tried putting together some javascript lines that I thought would do it but in vain. The JS code is:

 if (document.readyState == 'loading') { document.addEventListener('DOMContentLoaded',execute); }else{ execute() } function execute() { var btns = document.getElementsByClassName('item'); for (var i = 0; i < btns.length; i++) { btns[i].addEventListener('click',btnClicked); } } function btnClicked(event,btns) { var btn = event.currentTarget; var btnIndex = btns.indexOf(btn) console.log(btnIndex) }
 <body> <div class="btn-items"> <button class="item">btn 1 </button> <button class="item">btn 2 </button> <button class="item">btn 3</button> <button class="item">btn 4</button> <button class="item">btn 5</button> </div> </body>

What is the way to go?

You could give every button a custom attribute by using the setAttribute function on the HTML element. Then you just need to retrieve the value of this attribute by using the getAttribute function. See code example below:

 var btns = document.getElementsByClassName('item') for (var i = 0; i < btns.length; i++) { btns[i].addEventListener('click', btnClicked) btns[i].setAttribute('data-index', i) } function btnClicked(event) { var btn = event.currentTarget; console.log(btn.getAttribute('data-index')) }
 <div class="btn-items"> <button class="item">btn 1 </button> <button class="item">btn 2 </button> <button class="item">btn 3</button> <button class="item">btn 4</button> <button class="item">btn 5</button> </div>

document.getElementsByClassName() returns a node list that doesn't have indexOf() function. (see this question)

You can just pass i as parameter to btnClicked() .

var btns;
if (document.readyState == 'loading') {
        document.addEventListener('DOMContentLoaded',execute);
    }else{
        execute()
    }
    function execute() {
        btns = document.getElementsByClassName('item');
        for (let i = 0; i < btns.length; i++) {
            btns[i].addEventListener('click',(e)=> btnClicked(e,i));
        }       
    }
    function btnClicked(event,i) {
        
        console.log(i)
    }

You can get the desired output with this solution

function execute() {
    var btns = document.querySelectorAll('.item');
    btns.forEach(btnClicked);
  
}
function btnClicked(btn,index) {
    btn.addEventListener('click',()=>{
       console.log(index)
    });
}

This is a cleaner way of achieving that.

why not use

 if (document.readyState == 'loading') { document.addEventListener('DOMContentLoaded',execute); }else{ execute(); } function execute() { const btns = document.getElementsByClassName('item'); for(let i = 0; i < btns.length; i++){ btns[i].addEventListener('click',function(){ console.log('button index: '+i); }); } }
 <,DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width. initial-scale=1.0"> <title>Document</title> </head> <body> <button class="item">button 1</button> <button class="item">button 2</button> <button class="item">button 3</button> <script src="script.js"></script> </body> </html>

Often when you want to apply the same event to multiple elements, try and use event delegation.

Basically what you do is listen for the event on the parent btn-items , this works because Browser bubble events up.

Below is an example, notice because you listen for all clicks on the parent, if you click on the gap between buttons you will get -1 , in a real example you will likely want to handle this.

But the advantage with this approach, there is a single event listener, and a single event callback. And a really nice advantage is that if you later dynamically add .item , it will automatically work for these too.

 const btns = document.querySelector('.btn-items'); btns.addEventListener('click', e => { console.log([...btns.children]. indexOf(e.target)); });
 <div class="btn-items"> <button class="item">btn 1 </button> <button class="item">btn 2 </button> <button class="item">btn 3</button> <button class="item">btn 4</button> <button class="item">btn 5</button> </div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM