Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Efficiently Finding DOM Elements Appearing over a Specified DOM Element

How can I efficiently find all of the DOM elements that are on top of a specified query element?

That is, I want a Javascript function that when I pass in a reference to a DOM element will return an array of all DOM elements that have non-zero overlap with the input element and appear above it visually. My specific goal is to find those elements that may be visually blocking elements below them.

The context is one in which I do not have advanced knowledge of the web page, the query element, or much of anything else. Elements can appear above others for a variety of reasons.

I can of course do this through an exhaustive search of the DOM, but that's very inefficient and not practical when the DOM tree grows large. I could also use the newer elementFromPoint to sample positions from within the query element to ensure that it is indeed on top, but that seems pretty inefficient.

Any ideas on how to do this better?

Thanks!

like image 533
user1586808 Avatar asked Nov 01 '12 18:11

user1586808


1 Answers

I cannot think of a simpler way than using elementFromPoint. You don't seem to want to use it but can give you some consistent result. If there are multi layered elements, you should adapt your code to move already grabbed elements or set them invisible and recall function to get new set of data elements.

For the basic idea:

function upperElements(el) {
    var top = el.offsetTop,
        left = el.offsetLeft,
        width = el.offsetWidth,
        height = el.offsetHeight,
        elemTL = document.elementFromPoint(left, top),
        elemTR = document.elementFromPoint(left + width - 1, top),
        elemBL = document.elementFromPoint(left, top + height - 1),
        elemBR = document.elementFromPoint(left + width - 1, top + height - 1),
        elemCENTER = document.elementFromPoint(parseInt(left + (width / 2)), parseInt(top + (height / 2))),
        elemsUpper = [];
    if (elemTL != el) elemsUpper.push(elemTL);
    if (elemTR != el && $.inArray(elemTR, elemsUpper) === -1) elemsUpper.push(elemTR);
    if (elemBL != el && $.inArray(elemBL, elemsUpper) === -1) elemsUpper.push(elemBL);
    if (elemBR != el && $.inArray(elemBR, elemsUpper) === -1) elemsUpper.push(elemBR);
    if (elemCENTER != el && $.inArray(elemCENTER, elemsUpper) === -1) elemsUpper.push(elemCENTER);
    return elemsUpper;
}​

jsFiddle

like image 139
A. Wolff Avatar answered Nov 07 '22 13:11

A. Wolff