tags:

views:

1287

answers:

12

The problem I'm trying to solve is "What's at this position?"

It's fairly trivial to get the x/y position (offset) of a DIV, but what about the reverse? How do I get the id of a DIV (or any element) given an x/y position?

+1  A: 

Use a JQuery selector to filter the list of all DIVs for one that matches your position criteria?

Graphain
A: 

The JQuery selector is pretty useful, but (unless I missed something in the docs) there really aren't any selectors that will do this. I can't filter down based on any other criteria because all I have to work with is an x and y position.

Allan
+2  A: 

Create a mouse event listener, then trigger a mouse event at that location. This should give you the entire stack of elements at that location.

Or, look at the source of Firebug.

Nick Retallack
A: 

this might be a little too processor intensive but going over the whole list of div elements on a page, finding their positions and sizes then testing if they're under the mouse. i don't think i'd want to do that to a browser though.

John Boker
A: 

Thanks Graphain. I wish it was that simple -- I already know how to get the position of a DIV - this is a little more tricky.

Nick and John - Unfortunately, I can't use the mouse position.

I'm thinking that the solution involves creating some logic that takes in the position, does some math, and outputs the DIV id. Looks like there's no easy answer.

Allan
Yeah, I think it is going to be like that. Especially for div.contains() type situations.
Graphain
+1  A: 

One option is to build an array of "div-dimension" objects. (Not to be confused with the divs themselves... IE7 perf is frustrating when you read dimensions off of object.)

These objects consist of a pointer to the div, their dimensions (four points... say top, left, bottom, and right), and possibly a dirty bit. (Dirty bit is only really needed if the sizes change.

You could then iterate through the array and check dimensions. It requires O(n) to do that on each mouse move. You might be able to do slightly better with a binary search style approach... maybe.

If you do a binary search style approach, one way is to store 4 arrays. Each with a single point of the dimension, and then binary search on all four. O(4logn) = O(logn).

I'm not saying I recommend any of these, but they MIGHT work.

Rob Rolnick
+2  A: 

If all you have is the X and Y position, (and you can't track mouse movement like you mentioned) then you will have to traverse the DOM, looping through every DIV. For each DIV you will need to compare its X and Y coordinates against those you have. This is an expensive operation, but it is the only way. I suggest you might be better off rethinking your problem instead of coming up with a solution for it.

hal10001
A: 

You might find it's more efficient to traverse the DOM tree once when the page is loaded, get all elements' positions and sizes, and store them in an array/hash/etc. If you design the data structure well, you should be able to find an element at the given coordinates fairly quickly when you need it later.

Consider how often you will need to detect an element, and compare that to how often the elements on the page will change. You would be balancing the number of times you have to re-compute all the element locations (an expensive computation) against the number of times you'd actually use the computed information (relatively cheap, I hope).

jonblock
A: 

I think what John is saying is that you can use document.createEvent() to simulate a mousemove at the location you want. If you capture that event, by adding an eventlistener to the body, you can look at the event.target and see what element was at that position. I'm unsure as to what degree IE supports this method, maybe someone else knows?

http://developer.mozilla.org/en/DOM/document.createEvent

Update: Here's a jquery plugin that simulates events:

http://jquery-ui.googlecode.com/svn/trunk/tests/simulate/jquery.simulate.js

Erlend Halvorsen
+1  A: 
function getDivByXY(x,y) {
   var alldivs = document.getElementsByTagName('div');

   var d;

   for(d = 0; d < alldivs.length; d++) {
      if((alldivs[d].offsetLeft == x) && (alldivs[d].offsetTop == y)) {
         return alldivs[d];
      }
   }

   return false;

}
+2  A: 

Unfortunately, triggering a manufactured/simulated mouse event won't work, since when you dispatch it, you have to provide a target element. Since that element is the one you're trying to figure out, all you could do is dispatch it on the body, as if it had already bubbled.

You really are left to do it on your own, that is manually walk through the elements you're interested in, and compare their position/size/zIndex to your x/y point and see if they overlap. Except in IE and more recently FF3, where you can use

var el = document.elementFromPoint(x, y);

See

http://developer.mozilla.org/En/DOM:document.elementFromPoint

http://msdn.microsoft.com/en-us/library/ms536417(VS.85).aspx

rdworth