Demo
Demo

Reputation: 31

Getting index of an element from his parent

I found this code as the answer of a question:

function getNodeIndex(elm){ 
    return [...elm.parentNode.children].indexOf(elm)
}

I made something so when you click on the document, it logs the target of the click; If the target is myClass, I want it logs the index of it. The myClass elements are buttons, that are added when the user clicks on a button.

document.addEventListener("click", function(e) {
    if(e.target.classList.value == "myClass") {
        console.log(getNodeIndex(e.target))
    }
})

But, that's weird: Even if we click on 1st button, 4th button or 35th button, it will always log 2. What's the problem there? Thanks.

Edit:

The full code is here: http://pasted.co/6e55109a And it is executable on http://zombs.io/

Upvotes: 0

Views: 57

Answers (3)

Rob Monhemius
Rob Monhemius

Reputation: 5144

You are adding your eventListener to the document. Then you are checking for the classList. The classList may have another class and break your code. You should use classList.contains('some-class') instead.

I would add the click events directly to the 'some-class'-items you want them to be trigger by. This should work as long as you don't add more items to the DOM later. If you do, make sure to add the eventListener too.

// wait for all the html is loaded
window.addEventListener('load', () => {
  // get all buttons with the .some-class
  const someClassElements = document.querySelectorAll('.some-class');
  // iterate over the 'array like' elements 
  someClassElements.forEach( element => {
    // add a click event to the someClassElements
    element.addEventListener('click', () => {
      // log the nodeIndex
      const nodeIndex = getNodeIndex(element);
      console.log( nodeIndex );
    });
  });
}); // end on load


function getNodeIndex(elm){ 
    return [...elm.parentNode.children].indexOf(elm)
}
div{
  margin-top: 50px;
}
<div>
  <button class='some-class'>some class (0)</button>
  <button class='some-class'>some class (1)</button>
  <button class='some-class'>some class (2)</button>
  <button>no class (3)</button>
  <button class='some-class'>some class (4)</button>
  <button class='some-class'>some class (5)</button>
  <button>no class (6)</button>
  <button class='some-class'>some class (7)</button>
</div>

<div>
  <button>no class (0)</button>
  <button class='some-class'>some class (1)</button>
  <button>no class (2)</button>
  <button class='some-class'>some class (3)</button>
  <button class='some-class'>some class (4)</button>
  <button>no class (5)</button>
  <button class='some-class'>some class (6)</button>
</div>

The actual answer in your situation:

It seems like you want to know the index of the parent div, not the actual element.

use

console.log(getNodeIndex(e.target.parentNode));

instead of

console.log(getNodeIndex(e.target));

PS: You are always getting 2 as result without your html, you may actually always be clicking the third child of the parent element. I verified that this is the case from your code.

PSII: an extra.. In the code you linked you removed a parent node of an element. Later you try to use that element to make some unsuccessful console.log's, which won't work because you just removed the element.

Upvotes: 0

ic3b3rg
ic3b3rg

Reputation: 14927

It's due to the structure of your DOM which probably looks something like

<div>
  <div>Some Text: <button>Button 1</button></div>
  <div>Some Text: <button>Button 2</button></div>
  <div>Some Text: <button>Button 3</button></div>
</div>

Each of those buttons is the second child of its parent, i.e. one of the inner divs

Here's how to modify getNodeIndex to get it to work with DOM in this shape. If this still doesn't work, post your DOM.

function getNodeIndex(elm) { 
  return [...elm.parentNode.parentNode.children].indexOf(elm.parentNode)
}

$('button').on('click', e => {
  console.log(getNodeIndex(e.target))
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
  <div>Some Text: <button>Button 1</button></div>
  <div>Some Text: <button>Button 2</button></div>
  <div>Some Text: <button>Button 3</button></div>
</div>

Upvotes: 1

Adrian Rodriguez
Adrian Rodriguez

Reputation: 1

I don't know if your actual code is exactly the same, but the code you posted has 2 errors, you're missing 2 brackets:

/*
Yours:
document.addEventListener("click", function(e) {
    if(e.target.classList.value == "myClass") {
        console.log(getNodeIndex(e.target)
    }
}
*/

// With the brackets

document.addEventListener("click", function(e) {
    if(e.target.classList.value == "myClass") {
        console.log(getNodeIndex(e.target))
    }
})

I've run your code in jsbin and I had no problem, check the brackets and if you´re still having a problem please post your html

Upvotes: 0

Related Questions