views:

646

answers:

3

Before I ask my question, here's the offending code:

var coords = dojo.coords(g);
g.style.left = coords.x + "px";
g.style.top = coords.y + "px";
g.style.position = "absolute";

Now imagine that g is a relatively positioned element with an x position of 70 and a y position of 30. If I comment out the last line of the above code, that's what dojo.coords(g) gives me. But as soon as I add the last line, dojo.coords(g) returns an x position of 18, which is where the element would be if it were absolutely positioned. It seems to me that the call to dojo.coords() shouldn't be affected by code below it, but it is.

I'm also seeing the same problem with dojo.require() where if I call it directly before the function call that it's loading, I get an undefined error for that given function.

I'm testing in Firefox 3, but I also am noticing similar problems in Safari 3. Any ideas?

A: 

Hi there, sorry to not respond your question, (because I do not know dojo) but unless coords.x and coords.y returns a string, there is an error in your function,

g.style.left = coords.x + "px";

g.style.top = coords.y + "px";

You need to pass always a string to style, so add these also:

g.style.left = parseInt(coords.x) + "px";
g.style.top = parseInt(coords.y) + "px";

You would be surprised how many times this kind of error got my head spinning. About the answer, sorry, but I can't help you.

Good luck!

Edited:

Oh, if I understood, I can help you now.. well, since I do not know dojo, I can point out to you a javascript similar that will do what you want.

g.offsetTop

and

g.offsetLeft

Will give you the coords from the position of the element. Try them out and see if it works..

José Leal
??, next time I won't even try to help then.
José Leal
`parseInt()` returns an integer, not a string. `coords.x + "px"` works fine because javascript data types are converted automatically during execution.
inxilpro
Ok, say this to firefox then.
José Leal
Changing it to native functions doesn't seem to affect it. This definitely seems to be an execution order issue, not a choice of method call issue.
inxilpro
A: 

I still would love someone to explain why this works, but here's a solution:

var coords = dojo.coords(g);
g.style.left = coords.x + "px";
g.style.top = coords.y + "px";
setTimeout(function(h) {
    h.style.position = "absolute";
}, 0, g);

Cheers

inxilpro
+1  A: 

It is not the Dojo quirk but the way browsers work. Basically it may take some time for DOM to reflect your changes and reposition elements, or even change the layout. That's why you see what you see.

Another reason may be in the parent of your element. dojo.coords() returns the position relative to the viewport. If you pass "true" as the second value, it will return the position relative to the document root. Assigning top/left directly and changing position to "absolute" makes the element positioned relatively to its parent, if it was positioned too (absolute, relative, or fixed), or to the document root. It is a subtle difference, but sometimes it bites people. Relevant references: Containing Block, MSDN: position Attribute, Google doctype: position.

PS: personally I rely on Dojo to set left/top hoping it'll do the right thing working around browser quirks, and I set the position first:

var coords = dojo.coords(g);
g.style.position = "absolute";
dojo.marginBox(g, {l: coords.x, t: coords.y});
Eugene Lazutkin