11

Is there a simple way to locate all DOM elements that "cover" (that is, have within its boundaries) a pixel with X/Y coordinate pair?

Nakilon
  • 34,866
  • 14
  • 107
  • 142
Dennis Kreminsky
  • 2,117
  • 15
  • 23
  • 1
    Well you can get a decent answer from this question: http://stackoverflow.com/questions/48999/getting-div-id-based-on-x-y-position – Orbling Jan 24 '11 at 19:18
  • You mean there's more than one element? (you want all the overlaps to be calculated too?) – gblazex Jan 24 '11 at 20:04
  • Look if this solution help you out http://jsfiddle.net/eyxt2tt1/2/ the script can detect if your DOM elements are within a set of coordinated. – GibboK Apr 28 '15 at 09:18

3 Answers3

7

You can have a look at document.elementFromPoint though I don't know which browsers support it.
Firefox and Chrome do. It is also in the MSDN, but I am not so familiar with this documentation so I don't know in which IE version it is included.

Update:

To find all elements that are somehow at this position, you could make the assumption that also all elements of the parent are at this position. Of course this does not work with absolute positioned elements.

elementFromPoint will only give you the most front element. To really find the others you would have to set the display of the front most element to none and then run the function again. But the user would probably notice this. You'd have to try.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
3

I couldn't stop myself to jump on Felix Kling's answer:

var $info = $('<div>', {
    css: {    
        position:    'fixed',
        top:         '0px',
        left:        '0px',
        opacity:     0.77,
        width:       '200px',
        height:      '200px',
        backgroundColor: '#B4DA55',
        border:      '2px solid black'
    }
}).prependTo(document.body);

$(window).bind('mousemove', function(e) {
    var ele = document.elementFromPoint(e.pageX, e.pageY);
    ele && $info.html('NodeType: ' + ele.nodeType + '<br>nodeName: ' + ele.nodeName + '<br>Content: ' + ele.textContent.slice(0,20));
});

updated: background-color !

jAndy
  • 231,737
  • 57
  • 305
  • 359
  • Doing that on every `mousemove` is pretty much a *CPU overkill*. Not to mention the OP has never said for what he wants to use it. – gblazex Jan 24 '11 at 20:05
  • @galambalazs: don't take it too serious. However, my CPU load does not exceed 20%, but feel free to put a `clearTimeout` / `setTimeout` balancer around the inner mousemove handler ;) – jAndy Jan 24 '11 at 20:14
1

This does the job (fiddle):

$(document).click(function(e) {
    var hitElements = getHitElements(e);
});

var getHitElements = function(e) {
    var x = e.pageX;
    var y = e.pageY;
    var hitElements = [];

    $(':visible').each(function() {
        var offset = $(this).offset();
        if (offset.left < x && (offset.left + $(this).outerWidth() > x) && (offset.top < y && (offset.top + $(this).outerHeight() > y))) {
            hitElements.push($(this));
        }
    });

    return hitElements;
}​

When using :visible, you should be aware of this:

Elements with visibility: hidden or opacity: 0 are considered visible, since they still consume space in the layout. During animations that hide an element, the element is considered to be visible until the end of the animation. During animations to show an element, the element is considered to be visible at the start at the animation.

So, based on your need, you would want to exclude the visibility:hidden and opacity:0 elements.

Luca Fagioli
  • 12,722
  • 5
  • 59
  • 57