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.
Other Posts you might also like