开发者

find elements that are stacked under (visually) an element in jquery

开发者 https://www.devze.com 2023-02-22 21:52 出处:网络
if i have 2 divs (z index is not assigned), one layered over the over, can i use the reference to the top div to find which div is below it?

if i have 2 divs (z index is not assigned), one layered over the over, can i use the reference to the top div to find which div is below it?

as far as the DOM structure goes, these two divs would be siblings. but visually they are stacked on one another.

here's an example:

<body>
<div id="box1" style="background:#e0e0e0;height:100px;width:100px;"></div>
<div id="box2" style="background:#000000;height:100px;width:100px;margin-top:-50px;"></div>
</body>

which results in this:

find elements that are stacked under (visually) an element in jquery

so i'm trying to figure out, when having the black div, box2, a way to return box1 in jquery (using selectors), because box1 is beneath box2, using 开发者_StackOverflow中文版jquery.


Check if box1 is sharing the same position as a certain spot on the page.


And only because I'm a little bored, I made this awesome-er

http://jsfiddle.net/hunter/PBAb6/

function GetAllElementsAt(x, y) {
    var $elements = $("body *").map(function() {
        var $this = $(this);
        var offset = $this.offset();
        var l = offset.left;
        var t = offset.top;
        var h = $this.height();
        var w = $this.width();

        var maxx = l + w;
        var maxy = t + h;

        return (y <= maxy && y >= t) && (x <= maxx && x >= l) ? $this : null;
    });

    return $elements;
}


Maybe something along these lines... detach the element under your cursor (in this case box1) and use document.elementFromPoint to fetch the next element underneath that x,y position.. rough example:

    var first_box = $('#box1');// more programmaticaly would be to use document.elementFromPoint to fetch the element under your cursor

    var first_box_offset = first_box.offset();
    var x = first_box_offset.left;
    var y= first_box_offset.top + first_box.height();

    var reattach_me = first_box.detach();
    var second_box = document.elementFromPoint(x, y);

    $('body').append(reattach_me);


As far as I know, there isn't a selector for this. You could probably write a function to do this though. I would iterate over each element that precedes the div in question and check whether or not it's bounding box is in the desired div.


The only way, as you have it in the sample case, to actually have another DIV layering over another is if it comes after it in the DOM. So, your simple answer is that any div is over another div if it comes after it in the DOM tree. Please provide a more illustrative example if this is insufficient.

You can illustrate that this works by attempting to add a positive margin to DIV1. You'll note that it kicks DIV2 downward. DIV2, however, when given a negative margin will "layer" over DIV1. In your scenario using margins and divs without z-index or other positioning methods, it's not possible for DIV1 to overlap DIV2.

EDIT based on comments:

The process of figuring out if two elements occupy the same space is a different game. A general run down of your method would be to get the coordinate position for your anchor and get its width and height as well. Then, loop through all the divs and see if the anchor's position overlaps any of their coordinates. If it overlaps multiple divs, take the one last in the DOM as it'll be on top of the other.

Please don't make me write a code sample. :)


I re-made the accepted answer by @hunter:

function getCertainElementsAt(selectors, x, y, around) {

    //selector variants: 'all' / '.selector' / ['.class','#id','[attribute="whatever"]', 'etc']
    if(Array.isArray(selectors)){
        selectors = 'body ' + selectors.join(', body ');
    } else {
        selectors = selectors === 'all' ? 'body *' : 'body ' + selectors;
    }

    let $around =  typeof around === 'undefined' ? 0 : parseInt(around);

    return $(selectors).map(function() {

        let $this = $(this);
        let offset = $this.offset();
        let l = offset.left;
        let t = offset.top;
        let h = $this.outerHeight();
        let w = $this.outerWidth();

        let Xmin = l - $around;
        let Xmax = l + w + $around;

        let Ymin = t - $around;
        let Ymax = t + h + $around;

        return (Xmin <= x && x <= Xmax) && (Ymin <= y && y <= Ymax) ? $this : null;
    });
}

What's new:

  • Unnecesary #elements variable has been removed
  • vars have been replaced with lets
  • Replaced width() and height() with outerWidth() and outerHeight()
  • The function accepts the selectors argument (possible values: 'all', a 'string' with a selector, an array of strings with selectors, see the example in the code)
  • The function accepts the around argument (a number of pixels around your specified point), which allows you to find adjacent elements.
  • Also, I made the final condition a little more readable
0

精彩评论

暂无评论...
验证码 换一张
取 消