0

Please consider the following example:

const somevar = document.querySelectorAll('.someclass');

As a result we get a collection of items. How to detect which element is closest to the window in that collection? By closest I don't mean the physical position but the position in the DOM hierarchy.

I need to mention that in some situation we can get more than one element at the same DOM level, in that particular case I need the highest element in the DOM.

Note: no jquery pls.

Sorin GFS
  • 477
  • 3
  • 18
  • Does this answer your question? [How to get an element's top position relative to the browser's viewport?](https://stackoverflow.com/questions/1350581/how-to-get-an-elements-top-position-relative-to-the-browsers-viewport) – Justinas Jan 05 '21 at 07:15
  • @Justinas No, does not solve. I edited my question to be more specific. – Sorin GFS Jan 05 '21 at 07:19
  • How it does not solve? How are you using it? You must loop your `somevar` and apply referred question solution – Justinas Jan 05 '21 at 07:23
  • @Justinas I edited my question, I don't need the physical position, but the position in the DOM hierarchy. – Sorin GFS Jan 05 '21 at 07:24
  • Can you then give example of what you want? By *DOM hierarchy* I understand just array of elements. That array does not have any relation with computer window. – Justinas Jan 05 '21 at 07:26
  • @Justinas A document is a hierarchycal structure called DOM. In that structure the elemnts can be placed closer or farther from the top. – Sorin GFS Jan 05 '21 at 07:29
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/226855/discussion-between-justinas-and-sorin-gfs). – Justinas Jan 05 '21 at 07:30
  • @Justinas Sorry, I don't have time to chat, I have to go shortly. – Sorin GFS Jan 05 '21 at 07:32

1 Answers1

1

You can use the parentElement property to traverse the document tree of elements until the root in order to evaluate the depth of each element and through that decide on the element closest to the root:

// get all matching nodes as NodeList
const resultNodes = document.querySelectorAll(".someclass")
// convert NodeList object to Array of nodes
const results = [...resultNodes.keys()].map(key => resultNodes[key]);
// Compute the depth in the DOM tree for each element
const resultsWithDepth = results.map(result => {
    return {
        element: result,
        depth: computeDOMElementDepth(result, 0)
    }
})

getElementWithLowestDepth(resultsWithDepth);

// Computes the depth of a DOM element in an end-recursive fashion
function computeDOMElementDepth (element, currentDepth) {
    if (element.parentElement === null) {
        return currentDepth;
    }

    return computeDOMElementDepth(element.parentElement, ++currentDepth);
}

// Filters out the element highest in the DOM. (First element takes precedence)
function getElementWithLowestDepth (elements) {
    return elements.reduce((element1, element2) => {
        if (element2.depth < element1.depth) {
            return element2;
        }
        return element1;
    })
}