skip to Main Content

I have a grid with an unknown number of rows and a variable number of columns. I set the number of columns by declaring a constant.* I detect a key combo to move focus from an element in the grid whose position is unknown; it could be any of the grid’s child elements (images in this case). The idea is to move focus to the image either directly above or below.

To do this, I need to get the nth sibling element, either previous or next, from the focused element, where n is the number of columns.

I can’t use parentNode.querySelector(':nth-child(…)') since I don’t know the relationship of the focused element to the starting index (:first-child).

*Since this is a web component, the constant is set by declaring an attribute on the component.

Is there a JavaScript method to handle such cases?

2

Answers


  1. You can count children of parent until you find the original node. That’s how you can find nth position.

    function getNthPosition(node) {
    
      const parent = node.parentElement;
    
      
      // var nodes = parent.querySelectorAll(":scope > *");
      var nodes = parent.children;
      for (var i = 0; i < nodes.length; i++) {
    
        if (nodes[i] === node) {
          return i + 1
        }
      }
      return -1;
    }
    
    document.querySelectorAll("button").forEach(function(button) {
      button.addEventListener('click', function() {
        console.log("position", getNthPosition(button))
      })
    })
    <div class="parent">
      <button>click</button>
      <button>click</button>
      <button>click</button>
      <button>click</button>
    </div>
    Login or Signup to reply.
  2. No, there is no DOM method that does this directly. However, you can

    • iterate .previous|next(Element)Sibling for the given number of times:
      function getNthElementSibling(el, n) {
        while (el && n > 0) {
          el = el.nextElementSibling;
          n--;
        }
        while (el && n < 0) {
          el = el.previousElementSibling;
          n++;
        }
        return el;
      }
      

      (Use .nextSibling and .previousSibling if you want to take non-element nodes into account)

    • look up the element’s index in its parent’s child (element) nodes (see Finding DOM node index, JavaScript DOM: Find Element Index In Container) and then return the respective child after index arithmetic:
      function getNthElementSibling(el, n) {
        const siblings = Array.from(el.parentNode.children);
        return siblings[siblings.indexOf(el) + n];
      }
      

      (Use .childNodes if you want to take non-element nodes into account)

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search