Mouse position in both fixed and relative positioning

  • Thread starter Nikolai Prokoschenko
  • Start date
N

Nikolai Prokoschenko

Hello,

this question is connected to AmCharts (http://amcharts.com/javascript/) but it's not *about* AmCharts, it's just the context of the problem I'm having. (NB: AmCharts' API and general code provide enough material for several pages of flaming ;))

AmCharts, like almost every charting solution, has a concept of a "balloon", those are small popups which follow the mouse cursor and show some more or less relevant information about the chart item under this cursor. They use some browser-detecting code to find mouse's position for these balloons, which failed for me on several occasions, so I monkey-patched that code by the code provided by Peter-Paul Koch at http://www.quirksmode.org/js/events_properties.html. For the record, here is his code:

function doSomething(e) {
var posx = 0;
var posy = 0;
if (!e) var e = window.event;
if (e.pageX || e.pageY) {
posx = e.pageX;
posy = e.pageY;
}
else if (e.clientX || e.clientY) {
posx = e.clientX + document.body.scrollLeft
+ document.documentElement.scrollLeft;
posy = e.clientY + document.body.scrollTop
+ document.documentElement.scrollTop;
}
// posx and posy contain the mouse position relative to the document
// Do something with this information
}

This works splendidly in most cases, but as you can see, it's relative to the document, which means it won't work properly for fixed elements (e.g., lightboxed charts) when the document is scrolled. It turns out, AmCharts' original code also fails on fixed elements. By removing the scrolling position from the calculations, I'd probably get correct values for fixed elements, but instead the values would be broken for elements inside the document flow. Unfortunately, in my case, it has to work for both types of elements :(

My idea was to get the element under cursor, go all the way up in the DOM tree to check whether there are any elements with fixed positioning and calculate the cursor position relative to the scroll position of that element instead of documentElement's. However, I'm not sure whether this is correct or even doable.

So the actual question is: how do I find the correct mouse position for both fixed and relatively positioned elements? Note: I don't need complete code, some hints and directions would suffice for a start.

Thanks.

Nikolai.
 
T

Tyrone Slothrop

Hello,

this question is connected to AmCharts (http://amcharts.com/javascript/) but it's not *about* AmCharts, it's just the context of the problem I'm having. (NB: AmCharts' API and general code provide enough material for several pages of flaming ;))

AmCharts, like almost every charting solution, has a concept of a "balloon", those are small popups which follow the mouse cursor and show some more or less relevant information about the chart item under this cursor. They use some browser-detecting code to find mouse's position for these balloons, which failed for me on several occasions, so I monkey-patched that code by the code provided by Peter-Paul Koch at http://www.quirksmode.org/js/events_properties.html. For the record, here is his code:

function doSomething(e) {
var posx = 0;
var posy = 0;
if (!e) var e = window.event;
if (e.pageX || e.pageY) {
posx = e.pageX;
posy = e.pageY;
}
else if (e.clientX || e.clientY) {
posx = e.clientX + document.body.scrollLeft
+ document.documentElement.scrollLeft;
posy = e.clientY + document.body.scrollTop
+ document.documentElement.scrollTop;
}
// posx and posy contain the mouse position relative to the document
// Do something with this information
}

This works splendidly in most cases, but as you can see, it's relative to the document, which means it won't work properly for fixed elements (e.g., lightboxed charts) when the document is scrolled. It turns out, AmCharts' original code also fails on fixed elements. By removing the scrolling position from the calculations, I'd probably get correct values for fixed elements, but instead the values would be broken for elements inside the document flow. Unfortunately, in my case, it has to work for both types of elements :(

My idea was to get the element under cursor, go all the way up in the DOM tree to check whether there are any elements with fixed positioning and calculate the cursor position relative to the scroll position of that element instead of documentElement's. However, I'm not sure whether this is correct or even doable.

So the actual question is: how do I find the correct mouse position for both fixed and relatively positioned elements? Note: I don't need complete code, some hints and directions would suffice for a start.

Thanks.

Nikolai.

This code is very similar to something I had to deal with last week
where the calculations were passed on current window and not the
document. Follows is a snippet of code I found on the web.

This will give you the relative position of an element in the
document, looping through all elements until it gets to the top:

function findPos(obj)
{
var curleft = curtop = 0;
if (obj.offsetParent)
{
do
{
curleft += obj.offsetLeft;
curtop += obj.offsetTop;
}
while (obj = obj.offsetParent);
return [curleft,curtop];
}
}

Then , within your code:

var posEl = findPos(document.getElementById('someElement'));
posX = posEl[0];
posY= posEl[1];

From there you should be able to do your calculations (assuming I have
understood your question).
 
D

darwinist

Hello,

this question is connected to AmCharts (http://amcharts.com/javascript/) but it's not *about* AmCharts, it's just the context of the problem I'm having. (NB: AmCharts' API and general code provide enough material for several pages of flaming ;))

AmCharts, like almost every charting solution, has a concept of a "balloon", those are small popups which follow the mouse cursor and show some moreor less relevant information about the chart item under this cursor. They use some browser-detecting code to find mouse's position for these balloons, which failed for me on several occasions, so I monkey-patched that code by the code provided by Peter-Paul Koch athttp://www.quirksmode.org/js/events_properties.html. For the record, here is his code:

function doSomething(e) {
        var posx = 0;
        var posy = 0;
        if (!e) var e = window.event;
        if (e.pageX || e.pageY)         {
                posx = e.pageX;
                posy = e.pageY;
        }
        else if (e.clientX || e.clientY)        {
                posx = e.clientX + document.body.scrollLeft
                        + document.documentElement.scrollLeft;
                posy = e.clientY + document.body.scrollTop
                        + document.documentElement.scrollTop;
        }
        // posx and posy contain the mouse position relative to the document
        // Do something with this information

}

This works splendidly in most cases, but as you can see, it's relative tothe document, which means it won't work properly for fixed elements (e.g.,lightboxed charts) when the document is scrolled. It turns out, AmCharts' original code also fails on fixed elements. By removing the scrolling position from the calculations, I'd probably get correct values for fixed elements, but instead the values would be broken for elements inside the documentflow. Unfortunately, in my case, it has to work for both types of elements:(

My idea was to get the element under cursor, go all the way up in the DOMtree to check whether there are any elements with fixed positioning and calculate the cursor position relative to the scroll position of that elementinstead of documentElement's. However, I'm not sure whether this is correct or even doable.

I think that will work (if I understand your question correctly). If
it's within a fixed node, you don't substract the scrolling position.
I've used a similar approach when deciding where there's enough space
to position a sub-menu, which may or may not be from a fixed header,
depending on how far the page is scrolled down. The way I check if
something is fixed is like this:

//////////// Start Code //////////////

function is_fixed(element)
{
// While not at the top of the document tree, or not fixed, keep
searching upwards.
while (element.nodeName != "HTML" && used_style(element,
"position") != "fixed")
element = element.parentNode;
if (element.nodeName == "HTML") return false;
else return true;
}

// Used style is to get around browsers' different methods of getting
the currently used (e.g. inline, class, etc) style for an element
function used_style(element, property)
{
// getComputedStyle is the standard way but some ie versions don't
support it
if (window.getComputedStyle)
style = window.getComputedStyle(element, null);
else style = element.currentStyle;

return style[property];
}

// You can get the target element of an event like this, again using
standard or (if necssary) ie technique:
function event_target(e) { return e.target ? e.target :
e.srcElement; }

//////////// End Code //////////////

Note this is only tested in/targeted for (standards mode) ie7,8,9, and
recent firefox, opera, safari or chrome.
You can test the menu positioning stuff at ( http://webinterfacetricks.com
)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top