Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

getBoundingClientRect() is returning zero in XUL

I have a problem with my firefox extension

I have a XUL popup panel with a hbox for the tag cloud, and a JS code to add divs to this hbox:

<hbox id="tag_base" ondblclick="alert('done')"/>

JS:

var root = document.getElementById('tag_base');
var tag = document.createElement('div');
tag.textContent = 'test';
root.appendChild(tag);
var rect = tag.getBoundingClientRect()
alert(rect.top)

I need to get the dimensions of each added div, however, getBoundingClientRect simply refuses to work. If I remove alerts, it's always zero. With alerts the story is different: The first time the alert is called it returns zero, although the div appears on the screen. Any subsequent alerts return the correct coordinates.

If I set a breakpoint in Chromebug, everything is reported correctly. If I do not interupt the execution in any way, and run a loop, only zeroes got returned.

This has got me quite confused. Calling "boxObject" produces the same results, while "getClientRects[0]" is undefined on the first call.

Any hints on what might be causing this will be greatly appreciated.

like image 539
Andrei Sch. Avatar asked Jan 01 '11 23:01

Andrei Sch.


People also ask

What does getBoundingClientRect return?

The getBoundingClientRect() method returns the size of an element and its position relative to the viewport. The getBoundingClientRect() method returns a DOMRect object with eight properties: left, top, right, bottom, x, y, width, height.

What is element getBoundingClientRect ()?

The Element. getBoundingClientRect() method returns a DOMRect object providing information about the size of an element and its position relative to the viewport.

What is getBoundingClientRect relative to?

getBoundingClientRect() gives a result relative to the viewport's top-left corner ( 0,0 ), not relative to an element's parent, whereas el.


1 Answers

Although I can't find any documentation on this seemingly fundamental issue, the problem you noticed is most likely because the layout (aka "reflow") process has not yet run by the moment you ask for the coordinates.

The layout/reflow process takes the page's DOM with any styles the page has and determines the positions and dimensions of the elements and other portions of the page (you could try to read Notes on HTML reflow, although it's not targeted at web developers and probably is a bit outdated).

This reflow process doesn't run synchronously after any change to the DOM, otherwise code like

elt.style.top = "5px";
elt.style.left = "15px";

would update the layout twice, which is inefficient.

On the other hand, asking for elements position/dimension (at least via .offsetTop) is supposed to force layout to return the correct information. This doesn't happen in your case for some reason and I'm not sure why.

Please create a simple testcase demonstrating the problem and file a bug in bugzilla.mozilla.org (CC me - [email protected]).

My guess is that this is related to XUL layout, which is less robust than HTML; you could try creating the cloud in an HTML doc in an iframe or at least in a <description> using createElementNS to create real HTML elements instead of xul:div you're creating with your current code.

like image 141
Nickolay Avatar answered Sep 30 '22 10:09

Nickolay