jQuery.position() on Invisible Elements fails
Ah, just ran into a tricky issue with jQuery’s .position() function. position() returns the top and left position relative to its offset parent. For absolutely positioned elements in most cases this allows you retrieve the document relative position of the element to get an absolute page relative position. I use this function in many places of my internal library to move things around and resize them – it’s a handy function that I’m glad was integrated into the jQuery core.
So to retrieve the current position an object with left and top properties is returned:
var pos = $("#divHover").position(); alert(pos.left + " " + pos.top);
This works great if the selected element is visible. However if the object – as in my case – is initially invisible and you call position you get an exception:
[Exception... "Could not convert JavaScript argument arg 0 [nsIDOMViewCSS.getComputedStyle]" nsresult: "0x80570009 (NS_ERROR_XPC_BAD_CONVERT_JS)" location: "JS frame :: http://localhost/jqueryWeb/scripts/jQuery.js :: anonymous :: line 878" data: no]
http://localhost/jqueryWeb/scripts/jQuery.js
Line 878
This rather cryptic error occurs somewhere deep down in the jQuery stack as it’s trying to retrieve offsets from parent controls. Apparently most browsers don’t create the internal computed styles that are used to retrieve more reliable style information when the element is not visible with the styles simply not appearing in the list. The result is the error above.
The workaround is to make the element visible first so the following fixes the problem:
var pos = $("#divHover").show().position(); alert(pos.left + " " + pos.top);
Now in my case I have this code in some generic code in my library so this is a little more tricky – I have to detect whether the element is visible and then grab the position then hide it again. Here’s what this code looks like where el is the jQuery wrapped set for the matched element:
var vis = el.is(":visible"); if (!vis) el.show(); // must be visible to get .position var pos = el.position(); if (!vis) el.hide();
This was a bugger to find, because this code is already buried deep in my own codebase and it works most of the time except of course when the original object is invisible. Hopefully this will help somebody out running into a similar issue.
The Voices of Reason
# re: jQuery.position() on Invisible Elements fails
# re: jQuery.position() on Invisible Elements fails
It might be a different problem whatsoever, since my control was visible all the way through, but it seems very similar to me.This is my entry about it. <a>http://siderite.blogspot.com/2008/09/offsetparent-null-in-firefox-absolute.html</a>.
Also, about the visible/invisible switch being too fast to notice, I wouldn't be so sure. Different browsers do different things in different versions.
# re: jQuery.position() on Invisible Elements fails
Doing any sort of positioning before the DOM is loaded probably is not a good idea any way you look at it. If you're injecting inline there should be no reason to work with absolute positioned content - that should be able to wait until DOM's loaded (.ready()), no?
# Position absolute JQuery Datepicker
when activating the Datepicker calendar it always pops up wrongly at position (top 397px / left 520px). I could use your code (see above) to find out that the trigger (input) is positioned at 520px / 2215px. Are you aware of a way to position JQuery Datepicker absolutely so that it pops up next to its trigger?
Thanks a lot for your help!
Markus
# re: jQuery.position() on Invisible Elements fails
/Suleiman
# re: jQuery.position() on Invisible Elements fails
# re: jQuery.position() on Invisible Elements fails
Here's the funny part - the first time I got this, jQuery simply said the position propery didn't exist. I think this is because the page loaded with the default CSS having set the item to display: none. I got the same error as you once I tried to call .position() on an element that had had its class that made it visible removed.
Funky stuff! I wonder if this is better in later versions of jQuery? This is still with 1.2.6 I think.
# re: jQuery.position() on Invisible Elements fails
it gives me the correct value in firefox but gives 0 in chrome.
please help me.
Thanks in advance
# re: jQuery.position() on Invisible Elements fails
FWIW, it's a really bad idea to try to manipulate an inline element like <br> and treat it as positional. Use a div or other block element. If necessary wrap whatever you have into a block element.
# re: jQuery.position() on Invisible Elements fails
This way the element is still "invisible" when getting it's position.