PDA

View Full Version : [2.0b1][CLOSED with outstanding query] Element.getBox and FF, odd results



tjcrowder
18 Oct 2007, 3:48 PM
Hi folks,

Using ExtJS 2.0-beta1, I'm getting odd behavior from Element.getBox in FF 2.0. At first I wondered if I was just misunderstanding and was going to post to the Help forum, but when I tried it in Opera 9 and Safari 3 beta, I got the results I was expecting, so I think it's a bug specific to ExtJS+FF.

Basically, it looks like the x and y params point to the content area (rather than the bounding area) even when you ask for the bounding area; and if you actually ask for the content area (contentBox = true), the x and y params come back as though the borders had been allowed for twice.

Here's the code for a test page:



<html>
<head>
<title>ExtJS - getBox</title>
<link rel="stylesheet" type="text/css" href="../../resources/css/ext-all.css" />
<script type="text/javascript" src="../../adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="../../ext-all.js"></script>
</head>
<body>
<div id='abox' style='background-color: #d0d0d0; position: absolute; left: 10px; top: 10px; width: 10px; height: 10px; border: 2px solid black; padding: none; '></div>
<div id='bbox' style='background-color: #d0d0d0; position: absolute; left: 30px; top: 10px; width: 10px; height: 10px; border: none; padding: none; '></div>
<div id='cbox' style='background-color: #d0d0d0; position: absolute; left: 60px; top: 10px; width: 10px; height: 10px; border: 2px solid black; padding: 3px;'></div>
<div id='dbox' style='background-color: #d0d0d0; position: absolute; left: 90px; top: 10px; width: 10px; height: 10px; border: none; padding: 3px;'></div>

<div id='inlinespacer' style='height: 30px;'></div>

<div id='msgs' style='padding: 0.5em; font-family: Courier, Courier New, fixed'>
</div>

</body>
<script type="text/javascript">
Ext.onReady(function() {

Ext.get("msgs").update(
"abox: false: " + boxToString(Ext.get("abox").getBox(false))
+ " true: " + boxToString(Ext.get("abox").getBox(true))
+ "<br>bbox: false: " + boxToString(Ext.get("bbox").getBox(false))
+ " true: " + boxToString(Ext.get("bbox").getBox(true))
+ "<br>cbox: false: " + boxToString(Ext.get("cbox").getBox(false))
+ " true: " + boxToString(Ext.get("cbox").getBox(true))
+ "<br>dbox: false: " + boxToString(Ext.get("dbox").getBox(false))
+ " true: " + boxToString(Ext.get("dbox").getBox(true))
);
});
function boxToString(box)
{
return "" + box.x + "," + box.y + " " + box.width + "x" + box.height;
}
</script>
</html>


Here are the results I get from FF2.0:

abox: false: 12,12 14x14 true: 14,14 10x10
bbox: false: 30,10 10x10 true: 30,10 10x10
cbox: false: 62,12 20x20 true: 67,17 10x10
dbox: false: 90,10 16x16 true: 93,13 10x10

These are from Opera 9 and Safari 3 beta, and what I would expect:

abox: false: 10,10 14x14 true: 12,12 10x10
bbox: false: 30,10 10x10 true: 30,10 10x10
cbox: false: 60,10 20x20 true: 65,15 10x10
dbox: false: 90,10 16x16 true: 93,13 10x10

Can anyone confirm, or point out what I'm getting wrong? (BTW, you can mostly ignore cbox and dbox, they were there to see if padding caused a problem.)

Thanks in advance,

tjcrowder
19 Oct 2007, 9:35 AM
No takers on the confirmation?

brian.moeskau
20 Oct 2007, 1:28 AM
I have confirmed the behavior. The issue is actually in each base adapter's Ext.lib.Dom.getXY function. There's lots of browser-specific code in there, and the culprit seems to be:


if (Ext.isGecko) {
pe = fly(p);

var bt = parseInt(pe.getStyle("borderTopWidth"), 10) || 0;
var bl = parseInt(pe.getStyle("borderLeftWidth"), 10) || 0;

x += bl;
y += bt;

if (p != el && pe.getStyle('overflow') != 'visible') {
x += bl;
y += bt;
}
}


It seems to be specifically adding the border widths to the XY only for Gecko. I have no idea why -- I'll let Jack comment since I presume that the code is there for a reason... :-/

If you haven't gotten a reply in a couple of days please bump -- Jack has been out of town and it may take him a while to make it through all the posts.

brian.moeskau
20 Oct 2007, 1:29 AM
BTW -- thanks for the nice test case. Hopefully others will take your example for how to make our jobs a smidge easier ;)

tjcrowder
20 Oct 2007, 1:56 AM
Thanks Brian. I should also have mentioned that setBox must have the reciprocal problem, because this code doesn't move the box:


var abox;
abox = Ext.get("abox");
abox.setBox(abox.getBox(false));

If setBox weren't similarly affected, I'd expect the box to scoot right and down a little bit each time that was trigger (in my test case, via a button click), but it doesn't...


BTW -- thanks for the nice test case. Hopefully others will take your example for how to make our jobs a smidge easier ;)

:)) No worries, thanks.

jack.slocum
20 Oct 2007, 9:38 PM
The values returned by getXY and set with setXY are not intended to be identical values in all browsers, they are intended to put things in the same spot on all browsers and adjust for differences. Hopefully that makes sense. So in a nutshell, XY 12, 12 should be in the same position on screen as XY 10,10 since FireFox messes up the body's position. To confirm, try setXY(10,10) and see if they all end up in the same position.

If what you want are basic left, top values (which will be the same cross browser in your sample) then you should grab them.

tjcrowder
21 Oct 2007, 12:33 AM
Hi Jack,


If what you want are basic left, top values (which will be the same cross browser in your sample) then you should grab them.

Thanks. I wasn't sure initially where to grab them from, though, as Element.getLeft and Element.getTop returned the same values Element.getBox did by default. Then I noticed the "local" flag, and actually Element.getBox has that flag as well as a second parameter. Changing my getBox calls above to...


abox.getBox(false, true)

...gives me the correct 10,10 (for "abox") on all browsers I tested. Is that a reasonable way to get the values? Also, Element.get____(true) (e.g., getLeft, getTop, etc.) works.

A second question, if I may, just out of curiousity: What are these "page coordinates" the documentation talks about, if not the coordinates relative to the page in CSS units?

Thanks again,

tjcrowder
21 Oct 2007, 1:25 AM
Hi again,

FYI, I've started a follow-on thread about getLeft/getTop and setLeft/setTop over here (http://extjs.com/forum/showthread.php?t=15846).

jack.slocum
21 Oct 2007, 10:26 PM
The page coordinates are the actual visible position on the screen, calculated at runtime, taking parent nodes, scroll position and offset parents into consideration.

tjcrowder
21 Oct 2007, 11:09 PM
Hi Jack,

The page coordinates are the actual visible position on the screen, calculated at runtime, taking parent nodes, scroll position and offset parents into consideration.

Thanks. Huh, that's not what I'm seeing. With my page in the OP, the box reported at 12,12 is at 10,10. The content area starts at 12,12 (because there's a 2px left and top border), but the element is at 10,10. I've snapshotted the browser page and checked it in a graphics program. The only parent node is the document body, which has no borders, no padding; the page is unscrolled.

tjcrowder
30 Oct 2007, 10:03 PM
Bumping this again, since the element really is not at 12,12, I'd like to pursue it a bit.

Thanks,

tjcrowder
4 Nov 2007, 1:04 AM
Bumping this again, this really needs to be checked out before the end of beta in case it's a bug that needs fixing.

brian.moeskau
8 Nov 2007, 3:49 AM
I've added it to our list of things to look at before end of beta.

tjcrowder
8 Nov 2007, 4:48 AM
Thanks Brian. The RC is looking really good, hope it's clear sailing...

jack.slocum
13 Nov 2007, 7:00 AM
I already replied to this thread and the issue is closed. Please quit reopening it. Thanks.


The values returned by getXY and set with setXY are not intended to be identical values in all browsers, they are intended to put things in the same spot on all browsers and adjust for differences. Hopefully that makes sense. So in a nutshell, XY 12, 12 should be in the same position on screen as XY 10,10 since FireFox messes up the body's position. To confirm, try setXY(10,10) and see if they all end up in the same position.

If what you want are basic left, top values (which will be the same cross browser in your sample) then you should grab them.

tjcrowder
13 Nov 2007, 7:14 AM
I already replied to this thread and the issue is closed. Please quit reopening it. Thanks.

Jack, that tone seems uncalled-for.

Please re-read this post (http://extjs.com/forum/showthread.php?p=76302#post76302). You've said:


The page coordinates are the actual visible position on the screen, calculated at runtime, taking parent nodes, scroll position and offset parents into consideration.

And I've said:


With my page in the OP, the box reported at 12,12 is at 10,10...I've snapshotted the browser page and checked it in a graphics program. The only parent node is the document body, which has no borders, no padding; the page is unscrolled.

That's a discrepancy, that's the nature of the question. I don't "keep" reopening this. I pushed back on an explanation that doesn't explain what I'm seeing, and suggested reviewing it before going with the final. That's not inappropriate. I frankly believe this response was.

JasonMichael
28 Jan 2008, 8:42 AM
I've spent a couple hours working with this, as I use alot of 'boxes' in my projects these days.


To answer your question above, to use Ext.getBox(false, true) is absolutely what you want to use to get a sane result. The result otherwise seems to be determined by whatever values Firefox gives, and is not the fault of the Ext code. I looked at the DOM element values using FIREBUG (you should install this if you haven't already... impossible to work with Extjs projects without it.) by storing it in a variable I put in the namespace using Ext.ns('Ext.DEBUG'), and Firefox 2 insists on giving it a offsetWidth and offsetHeight value of 14, which in turn puts the upper, left corner of our 10 x 10 element with no border or padding, at position 12,12 IF you used Ext.getBox(false) and not Ext.getBox(false,true), though it displays correctly (I used a graphics program as you did.

Sooooooo In in conclusion......(my English essay teacher hates me, cuz I make more money than he does while I write so badly....) save yourself some time and just count on Ext.getBox with he locale paramemter set to true, to get proper X,Y coordinates that you can count on.... not the unpredictable value you end up with using getBox(false).

Hope that helps calm things a bit.

tjcrowder
28 Jan 2008, 9:00 AM
Thanks for the post, Jason. (I don't use ExtJS at the moment for various reasons -- the attitude in this thread certainly being one of them -- but I got the thread update notification.)

Just replying to say that I don't think Firefox (Gecko, really) is misreporting the position, at least not in the overall normal case. It's been weeks and weeks, but I did check that early on with a non-ExtJS page.

Thanks again,

andrei.neculau
22 Mar 2008, 8:22 AM
Need to bump this. I managed to get into the same situation, but I do seem to have an example/argument that hasn't been used so far.

Open the examples/form/combos.html available in the ExtJS 2.0.2 build.
Expand the first combo's list, hover/select the "Alaska" and move the scrollbar 5px down.
Now press the Up arrow-key to select "Alabama".

The element should have been scrolled into view. Except for its top-border - you can click on the scrollbar's up arrow to notice the 1px difference.

I have read through all the frustrations, ideas and "decisions" regarding the getXY code when Ext.isGecko. It feels inappropriate to comment on that since both parties seem to have it right.

Instead, I will simply post my code/modification, which so far seems to be working just fine:



if (Ext.isGecko) {
// pe = fly(p);
pe = Ext.fly(p);

var bt = parseInt(pe.getStyle("borderTopWidth"), 10) || 0;
var bl = parseInt(pe.getStyle("borderLeftWidth"), 10) || 0;

// ANDRIE
// x += bl;
// y += bt;
//
// if (p != el && pe.getStyle('overflow') != 'visible') {
// x += bl;
// y += bt;
// }
if (p != el) {
x += bl;
y += bt;

if (pe.getStyle('overflow') != 'visible') {
x += bl;
y += bt;
}
}
// END
}

This code can override ExtJS code by using



Ext.apply(Ext.lib.Dom, {
getXY : function(el) {
... modified code + replace "fly(" with "Ext.fly(" ...
}
});