domxulcoordinates

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.


Solution

  • 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 - ***********@gmail.com).

    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.