Find Element Position

D

David Mark

That way absolutely-positioned children of BODY stay inside body. I do
this a lot.

Why? To avoid the bizarre "edge cases" (pun intended) involving the
HTML element?
And that's why it's weird. You have a 10px margin around body.
#adiv's containing block is HTML.
BODY is not (or shouldn't be) a majical element.

Weird is a good description for the behavior of the various browsers
with regard to absolutely positioned elements without positioned
parents. Your strategy of positioning the body seems like a good way
to avoid some of the quirks.
My Definition:
offsetParent - a containing block that is offset by margin or left/top
values.

I assume that is your abridged definition.
Anne van kesteren started this 2 years ago:

Editor's Draft 9 December 2007
"1. If any of the following holds true return null and stop this
algorithm:

    * A is the root element.
    * A is the HTML body element.
    * The computed value of the position property for element A is
fixed.

2...

3. Return the nearest ancestor element of A for which at least one of
the following is true and stop this algorithm if such an ancestor is
found:

    * The computed value of the position property is not static.
    * It is the HTML body element.
    * The computed value of the position property of A is static and
the ancestor is one of the following HTML elements: td, th, or table.
"

http://dev.w3.org/cvsweb/csswg/cssom-view/Overview.html?rev=1.2#offse...



I would hope that this spec be forgotten a new one started.

Yes, I glanced at it recently and it seems out-of-touch with reality.
The spec is self contradictory, and thus impossible to implement
correctly.

Always a bad thing for a technical specification.
What is A's offsetParent?
if A is BODY then
offsetParent is null

As such, A can then have neither offsetTop, nor offsetLeft. BODY can
have margin, top, left, border, and position.

All of these things move the BODY element.

For some reason, containing block doesn't come up in the document at
all. Nor does "initial containing block".

The spec is inaccurate to the point of being almost completely
fictitious. The damage of having such a spec is considerably large.

I agree. Hopefully it will not become the basis for a standard.
The damage can be seen in Opera, Mozilla, and Safari. These browsers
have seemed to have attempted to implement the (impossible) spec. None
of them get it right, of course. It's impossible.

Now I know who caused this mess. Thanks Anne!
This is a simple test that barely scratches the surfacehttp://dhtmlkitchen..com/ape/test/tests/dom/inline-offsetTop.html




getBoxObjectFor is for XUL

Ah, there is only XUL. I wonder why it works so well for (X)HTML
documents? Perhaps it is just a lucky coincidence. I can't remember
where I got the idea to use it, but it seemed like a sound idea at the
time.
When checking drop target coords, with scrolling or moving dropTargets
(while dragging), coord checks must be done continually, while

Drop targets inside of scrolling containers that can be scrolled
during the drag operation I can see. But moving drop targets? Other
than a video game of some sort, the application for that eludes me.
dragging.

There might be a better strategy for checking coords.

Certainly. For the scrolling example, the dragged element could share
the same positioned parent as the drop targets, which could be
positioned absolutely. Then the overlap logic would only need to use
computed styles.
Besides, I've got load-time constant for determining certain things
about the document, those things could easily be different in the
framed document. It is an edge case that is not worth testing. It

Yes, if a document that triggers standards-based layout contains an
IFrame that triggers quirks mode, things could get very ugly. This is
something I need to document.
might be worth testing to throw an error if el.ownerDocument != doc;
Then the user knows because it fails right away.



Why just use ownerDocument?

Because it can't be assumed to be there. The fallback branch isn't
too involved.
I didn't consider that. I reading some old thread where it says that
IE5.0 doesn't support |in|, so my library will break there. I use |in|

That's the biggest reason I don't use it in low-level code like this.
a lot. It's really the only way to tell if an object has a property.

See the three methods recently discussed in the thread about Peter's
feature testing article.
var IS_BACK_COMPAT = document.compatMode === "BackCompat" ||
documentElement && documentElement.clientWidth === 0);

It's a stronger inference than compatMode (value or absence) alone.
Not perfect, but better.

I don't think that will work. For instance, I know the
documentElement in IE5 has a non-zero scrollHeight/Width. I tried
everything to come up with a proper feature test for this. I finally
came up with a partial solution that uses a multiple object inference
only until the page has been scrolled (then it knows for sure which to
use.) In my entire library, this is the only quirk that I couldn't
find a pure feature test for.
Does getComputedStyle provides more accurate results?

Well, they are apples and oranges, but other than left/top and height/
width for statically positioned elements, I have found no problems
with getComputedStyle in Opera.
Opera has some css rounding issues anyway IIRC.

I haven't run into those in Opera.
getting styles is painful topic worthy of a new group. I can't even
get currentStyle.clip in IE. I found only clipTop/Left, et c.

Interesting. IE's implementation of clip is completely bizarre. I
couldn't include a two line function that "unclips" an element in my
core build as it required conditional compilation. For this reason,
it is offered only as an add-on, which is only required for certain
animation effects.
I was probably confused with setting fontWeight or zIndex.
style.fontWeight = 101 => Error
style.zIndex = 1.2 => Error? I can't remember. IE is less forgiving.

That looks like a sure error to me.

Thanks. I'll skip that one.
Try using a torture case and you'll see more errors.

My test page layout is fairly torturous I think, but within reasonable
limits.

Here's a really weird one. I have a "grow" effect that can optionally
size the font of the element. Using my em-based layout (which was my
first stab at aligning to a baseline grid), I found that setting
inline font sizes to their cascaded or computed values would make the
fonts change in size (which makes no sense to me) and this only
happened at certain text size settings (e.g. larger, smaller,
smallest, but not medium.) However, if I set the inline font size
style to what I know is the cascaded value before I run the animation,
then all is well (the fonts have already jumped in size.) That is the
one strange workaround I had to implement in all of the animation
tests. I still don't understand what the deal was with that (and
don't really care.) I suspect my CSS is just too convoluted, but the
baseline grid does work well in all of the browsers I have tested.
I used fontSize = "777px";
with 1.18em on two nested elements.

It's a real torture test. Amazinly, MOzilla got it. webkit's 2px off.

What Webkit browser do you test with? Windows Safari Beta? That
browser still has some serious issues. I wonder if they will ever
finish it. Despite it being a Beta, I duly added some quirk detection
logic in a few places to make the unit tests behave (more as an
exercise in feature testing than anything else.) I still have an
issue when I replace a static (and streaming) Flash movie with one
created on page load (to prevent the "click to activate" problem) and
Safari's status bar indicates that it is still loading the replaced
object element. I've seen it crash when interacting with Apple's own
Quicktime plug-in as well. Whatever.
I don't like seeing failing tests, but I'm leaving it in. It's a way
to say:
"if you try to get an exact calcuation off EM units, it might be off a
few px in some edge cases on some browsers."

Makes sense.
testGetOffsetLeftFloatingPointEM : function() {
    var fontSize = "10px";
    var target = document.getElementById("target");
    var container = document.getElementById("container");
    var c1 = document.getElementById("c1");
    document.documentElement.style.fontSize =
    document.body.style.fontSize =
        c1.style.fontSize =
        container.style.fontSize =
        target.style.fontSize = "777px";

    container.style.borderLeft =
    c1.style.borderLeft = "1.18em solid red";
    target.style.marginLeft = "1.18em";
    target.style.left = 0;
    var expected = Math.round(777 * 1.18 * 3);
    var actual = dom.getOffsetCoords(target);
    Assert.areEqual(expected, actual.x, "getting computed coords from
EM values failed.");
Interesting.



I'm not testing in older browsers. I am going to try to get it going
in IE6, Safari 2, FF 2, Opera 9.

I am going to exit the function if neither getCOmputedStyle nor
getBoundingRect are supported.

To be future-proof, you need getComputedStyle or
(getBoundingClientRect AND clientLeft/Top.)
I hope you're not talking about the Dean Edwards hack that's used in
jQuery's css(). I've tested it thoroughly. The rounding errors are as
bad as Opera (or worse).

In the case of IE computing the pixel-based value, I am talking of a
modified version of that hack. It has worked thus far for me. The
unmodified original was clearly no good.
Using that hack, it's possible to have close results.

style.fontSize = "10px";
style.height= "2em";

You can get an acceptible result.

When I started using bigger numbers, I got rounding errors.

I probably will too. The lesson is that nothing is going to be 100%
perfect for all cases in all browsers. I figure that the best I can
shoot for is 99%. It seems to me that the currently popular libraries
take a stance like "three out of four ain't bad."
Webkit returns 'auto' when margin: auto and left is undeclared.http://www.dhtmlkitchen.com/test/bug/getComputedStyle.html

My gCS wrapper will never return "auto", but instead returns null.
IRC, IE's currentStyle property (which is cascaded


Hmm.

There's also style.pixelTop and curentStyle.pixelTop (Opera).

I don't use those, except in the aforementioned hack to convert
cascaded styles to pixel units in an IE-only branch (Opera always uses
getComputedStyle.)
Yes, but often much faster when you don't.  I think that most
applications will not need to worry about element scroll offsets.

I need to get that profiler going.

Yes, but I think the extra effort is worth it.  These sorts of
functions are always going to be a bottleneck, so I endeavor to design
systems that call them as infrequently as possible (if at all.)

var TABLE = /[A-Z]/.test(documentElement.tagName) ? "TABLE" : "table";

Now I can use it as a constant:

(parent.tagName === TABLE

Interesting solution.
Only 0 would make sense to me.

Or null I would think. Regardless, Opera, FF and others go ahead and
return what they think is the offset position in pixels (as mentioned,
Opera gets them wrong when borders are involved.)
When an element has position: static, top and left values do not
apply.

Exactly, so I consider the above-mentioned behavior a non-standard
bonus feature. Needless to say, I do not rely on its presence.
I've got Opera 9.25 and it doesn't do that.

That means they fixed it and my code will skip the workaround in that
and subsequent versions. Isn't feature testing wonderful?
It seemed simple enough. I guess it's making the code messy the way I
have it?

It is definitely confusing to see a timeout in there.
Sure, why not?

I don't know. It is the last thing I am worried about at the moment.
I figure when I get to the unit test for the style switcher, I will
create some more distinct (and perhaps more appealing) alternate
styles.
I've gone and set the height to "0" (string).
Good.


I want to see the twitch you mentioned. I generally dislike making
changes without a proven reason.

Think about it. If the statically positioned element added at the
bottom has a height, then the page will grow longer. Removing it will
restore the previous height. Watch the scrollbar closely during the
load and you will see it jump briefly to reflect the change.
That's why I need a demo.


Only browsers that do not support getBoundingClientRect get there.

I see.
I don't doubt that it is and will continue to be a source of pain for
a lot of people, including members of the Webkit team.

I bet they struggled - and will continue to struggle - with Anne van
Kesteren's "unofficial" spec.

I imagine so.
I wonder how many man hours (or months) have been put into
compensating for this careless mistake?

I know I spent at least a few days tearing my hair out over the
various "edge cases" (pun intended.)
I'm going to have a look at getElementPosition().

Have fun.

[snip]
 
H

Henry

On Feb 18, 8:05 pm, dhtml wrote:

Well, there is no standard for offsetParent yet, so it is
hard to say who is right.


If that spec ever becomes a standard, then we can say that
IE is wrong.
<snip>

That could be said but it would be massively unfair to Microsoft to
retrospectively declare what they have been doing for years with a
property they introduced as being 'wrong'. And Microsoft cannot change
the behaviour of IE with regard to offsetParent just because someone
publishes a retrospective standard. Microsoft's biggest concern is the
IE only Intranet applications belonging to its corporate customers
(the ones they really cannot afford to encourage to stop using
Windows).

This is what happened with the 'add' method of SELECT elements.
Microsoft had an - add - method from IE4, then the W3C 'formalised' it
as part of the HTML DOM, but in a way that was incompatible with what
Microsoft had already done, and Microsoft decided to ignore the W3C
and keep all of the pre existing Intranet applications that were
already using - add - working fine. They elected not to break their
corporate customer's Intranets.

And the solution to this situation is as simple as thinking about the
names a little more. If the 'add' method of SELECT elements had been
named 'addOption' in the W3C spec (or something of the sort) then
Microsoft could have implemented it in their browsers fully in
accordance with the W3C specification and still maintained back-
compatibility with existing code. And we would all have benefited
from that.

No if someone is fool enough to attempt to standardise "offsetParent"
in any way other than formalising precisely what IE already does
(which does not appear to be the approach being taken) then we
probably will not see any single usable approach in the foreseeable
future. On the other hand, if they were defining the precise behaviour
of a set of values called, say, "layoutParent", "layoutLeft",
"layoutTop" and so on, Microsoft would have no reason for not
delivering on that new standard in their next browser, because it
would not break any existing code on any of their commercial
customer's Intranets.
 
D

David Mark

On Feb 19, 2:51 am, David Mark wrote:> On Feb 18, 8:05 pm, dhtml wrote:




<snip>

That could be said but it would be massively unfair to Microsoft to

True, it could be taken that way. All I meant was that MS would no
longer be compliant with the standard in this respect.
retrospectively declare what they have been doing for years with a
property they introduced as being 'wrong'. And Microsoft cannot change
the behaviour of IE with regard to offsetParent just because someone
publishes a retrospective standard. Microsoft's biggest concern is the
IE only Intranet applications belonging to its corporate customers
(the ones they really cannot afford to encourage to stop using
Windows).

This is what happened with the 'add' method of SELECT elements.
Microsoft had an - add - method from IE4, then the W3C 'formalised' it
as part of the HTML DOM, but in a way that was incompatible with what
Microsoft had already done, and Microsoft decided to ignore the W3C
and keep all of the pre existing Intranet applications that were
already using - add - working fine. They elected not to break their
corporate customer's Intranets.
Right.


And the solution to this situation is as simple as thinking about the
names a little more. If the 'add' method of SELECT elements had been
named 'addOption' in the W3C spec (or something of the sort) then
Microsoft could have implemented it in their browsers fully in
accordance with the W3C specification and still maintained back-
compatibility with existing code.  And we would all have benefited
from that.

I agree.
No if someone is fool enough to attempt to standardise "offsetParent"

Apparently someone was.
in any way other than formalising precisely what IE already does
(which does not appear to be the approach being taken) then we

It was definitely not the approach taken.
probably will not see any single usable approach in the foreseeable

Not without a ton of feature testing. The offset* properties are a
real mess.
future. On the other hand, if they were defining the precise behaviour
of a set of values called, say, "layoutParent", "layoutLeft",
"layoutTop" and so on, Microsoft would have no reason for not
delivering on that new standard in their next browser, because it
would not break any existing code on any of their commercial
customer's Intranets.

That would be nice, but I doubt it will happen.
 
T

Thomas 'PointedEars' Lahn

David said:
Use isHostMethod! Feature testing by boolean type conversion is out.

isHostMethod() as it currently is (trunk), is unnecessarily inefficient:

| var isHostMethod = function(o, m) {
| var t = typeof(o[m]);
| return !!(((t=='function' || t=='object') && o[m]) ||
| t == 'unknown');
| };

Consider this:

function isHostMethod(o, m)
{
var t = typeof o[m];
return (/^(function|object)$/.test(typeof o[m]) && o[m])
|| t == "unknown";
}

Would work in JavaScript 1.2+ (NN 4+), JScript 3.1.3510+ (MSHTML 4.01+),
ECMAScript 3+ (Opera 6+).

If you really need to have it return a boolean value *always* (although
because of implicit type conversion in the calling code that is hardly
required), you can write !!o[m] instead.

CWR code should use spaces for indentation, not tabs.


PointedEars
 
T

Thomas 'PointedEars' Lahn

Thomas said:
isHostMethod() as it currently is (trunk), is unnecessarily inefficient:

| var isHostMethod = function(o, m) {
| var t = typeof(o[m]);
| return !!(((t=='function' || t=='object') && o[m]) ||
| t == 'unknown');
| };

Consider this:

function isHostMethod(o, m)
{
var t = typeof o[m];
return (/^(function|object)$/.test(typeof o[m]) && o[m])
|| t == "unknown";
}

I meant

function isHostMethod(o, m)
{
var t = typeof o[m];
return (/^(function|object)$/.test(t) && o[m])
|| t == "unknown";
}

of course.


PointedEars
 
D

David Mark

Use isHostMethod!  Feature testing by boolean type conversion is out.

isHostMethod() as it currently is (trunk), is unnecessarily inefficient:

| var isHostMethod = function(o, m) {
|   var t = typeof(o[m]);
|   return !!(((t=='function' || t=='object') && o[m]) ||
|             t == 'unknown');
| };

Consider this:

  function isHostMethod(o, m)
  {
    var t = typeof o[m];
    return (/^(function|object)$/.test(typeof o[m]) && o[m])
           || t == "unknown";
  }

My posted version uses a regexp, but not a literal. Peter asserts
that the other way is faster.
Would work in JavaScript 1.2+ (NN 4+), JScript 3.1.3510+ (MSHTML 4.01+),
ECMAScript 3+ (Opera 6+).

Regular expression literals work in IE4 and NN4?
If you really need to have it return a boolean value *always* (although
because of implicit type conversion in the calling code that is hardly
required), you can write !!o[m] instead.

Yes, that is roughly what I did. I don't think it makes sense to
return a truthy property of the o object.
CWR code should use spaces for indentation, not tabs.

It does in general. Apparently that early entry did not.

Thanks for the constructive input "PointedEars." I should duly note
that the isHostMethod function owes a debt to your isMethodType
function.
 
T

Thomas 'PointedEars' Lahn

David said:
David said:
else if(el.getBoxObjectFor) {
}
Use isHostMethod! Feature testing by boolean type conversion is out.
isHostMethod() as it currently is (trunk), is unnecessarily inefficient:

| var isHostMethod = function(o, m) {
| var t = typeof(o[m]);
| return !!(((t=='function' || t=='object') && o[m]) ||
| t == 'unknown');
| };

Consider this:

function isHostMethod(o, m)
{
var t = typeof o[m];
return (/^(function|object)$/.test(typeof o[m]) && o[m])
|| t == "unknown";
}

My posted version uses a regexp, but not a literal. Peter asserts
that the other way is faster.

Interesting. I will have to do more benchmarks.
Regular expression literals work in IE4 and NN4?

Yes, they do (it's tested), as long as they don't include the multi-line
modifier (`m'). The latter is only supported since JavaScript 1.5
(Mozilla/5.0), JScript 5.5.6330 (MSHTML 5.5), ECMAScript 3 (Opera 6*).

See also http://PointedEars.de/scripts/es-matrix/

* This is an assumption based on <http://www.opera.com/docs/specs/opera6/>.
As always, feedback including test results of language features is
appreciated.
Thanks for the constructive input "PointedEars."

You're welcome. You may use my nickname without quotes, or my first name.
I should duly note that the isHostMethod function owes a debt to your
isMethodType function.

I would appreciate that.


PointedEars
 
D

David Mark

David said:
David Mark wrote:
else if(el.getBoxObjectFor) {
}
Use isHostMethod!  Feature testing by boolean type conversion is out..
isHostMethod() as it currently is (trunk), is unnecessarily inefficient:
| var isHostMethod = function(o, m) {
|   var t = typeof(o[m]);
|   return !!(((t=='function' || t=='object') && o[m]) ||
|             t == 'unknown');
| };
Consider this:
  function isHostMethod(o, m)
  {
    var t = typeof o[m];
    return (/^(function|object)$/.test(typeof o[m]) && o[m])
           || t == "unknown";
  }
My posted version uses a regexp, but not a literal.  Peter asserts
that the other way is faster.

Interesting.  I will have to do more benchmarks.
Regular expression literals work in IE4 and NN4?

Yes, they do (it's tested), as long as they don't include the multi-line
modifier (`m').  The latter is only supported since JavaScript 1.5
(Mozilla/5.0), JScript 5.5.6330 (MSHTML 5.5), ECMAScript 3 (Opera 6*).

Good to know.
See alsohttp://PointedEars.de/scripts/es-matrix/

* This is an assumption based on <http://www.opera.com/docs/specs/opera6/>..
  As always, feedback including test results of language features is
  appreciated.


You're welcome.  You may use my nickname without quotes, or my first name.


I would appreciate that.

It has been duly noted. This is about as official as it gets for
CWR. There are no credits in the comments AFAIK (everything is
credited to the group as a whole.) I will make a note in my project
though.
 
D

dhtml

Why? To avoid the bizarre "edge cases" (pun intended) involving the
HTML element?

Mostly so I can visually keep everything inside BODY. Sometimes
layouts use a main #container div. I just use BODY position: relative;

so instead of
BODY - static
#main-content - relative

I just have
BODY - relative
Weird is a good description for the behavior of the various browsers
with regard to absolutely positioned elements without positioned
parents. Your strategy of positioning the body seems like a good way
to avoid some of the quirks.

The problem is, really, it makes harder to calculate the offset
position in Opera.
I assume that is your abridged definition.

A TD, TR, or TBODY that does not have a positioned ancestor should use
its TABLE.

Feel free to add to it.
Ah, there is only XUL. I wonder why it works so well for (X)HTML
documents? Perhaps it is just a lucky coincidence. I can't remember
where I got the idea to use it, but it seemed like a sound idea at the
time.

The bug report said it best, and this is the worst part:

"-- in Mozilla, it's only available when XUL is enabled, so some
embedded Geckos
don't have it --- actually, it's worse, they have the function, but it
always
fails"
https://bugzilla.mozilla.org/show_bug.cgi?id=340571

Certainly. For the scrolling example, the dragged element could share
the same positioned parent as the drop targets, which could be
positioned absolutely. Then the overlap logic would only need to use
computed styles.

Dualling scrollable lists would have different containing blocks.

#outer-cont
#list-1-cont #list-2-cont

I should probably worry about that when I get to it, and it probably
wouldn't be hard enough to optimize to the point that reusing coords
was pointless.
Yes, if a document that triggers standards-based layout contains an
IFrame that triggers quirks mode, things could get very ugly. This is
something I need to document.

Or if an HTML containing a frame loaded as application/xhtml+xml, and
I had a constant TABLE == "TABLE"
(less likely)

Because it can't be assumed to be there. The fallback branch isn't
too involved.

The only time I could think is if it's in abstract view.
See the three methods recently discussed in the thread about Peter's
feature testing article.

function isHostObject(object, property) {
return !!(typeof(object[property]) == 'object' && object[property]);
}

would work.
I don't think that will work. For instance, I know the
documentElement in IE5 has a non-zero scrollHeight/Width. I tried
everything to come up with a proper feature test for this. I finally
came up with a partial solution that uses a multiple object inference
only until the page has been scrolled (then it knows for sure which to
use.) In my entire library, this is the only quirk that I couldn't
find a pure feature test for.

IE5 propagates viewport dimensions to BODY, but you've pointed out a
case where there's documentElement.scrollWidth.

http://13thparallel.com/archive/viewport/example2.htm

Three possibilities where my approach will fail:
getBoundingClientRect supported, and:
compatMode = undefined, document rendered standard => fails by
incorrectly subtracting body border width
compatMode = BackCompat, document rendered IE quirls => ditto
compatMode = BackCompat, document rendered Moz quirls => ditto

The only reason those bugs aren't apparent is that only IE supports
getBoundingClientRect.

So compatMode is out. It means different things in different
browsers.

// True only in IE5, or IE6+ quirks mode.
var IS_BODY_ACTING_ROOT = documentElement &&
documentElement.clientWidth === 0;

This seems to be true only in IE5, or IE6+ in quirks mode. I don'
I haven't run into those in Opera.
It goes to those sub-pixel measurements.

When converting an em to px, for clientWidth, I get an uint.

el.style.border='1.92em solid red';
el.clientWidth => 18em;

When using larger numbers for font size, it becomes apparent that
there's also some internal miscalcuation. The numbers aren't off by 1.
They're off by a lot.

When cumulatively adding clientLeft/Top the rounded pixelValues are
added up, resulting in a much more skewed result.
That looks like a sure error to me.
Sorry, zIndex works with floating points. It was the fontSize that
didn't work with anything other than 100,200...900 (or keyword)
Here's a really weird one. I have a "grow" effect that can optionally
size the font of the element. Using my em-based layout (which was my
first stab at aligning to a baseline grid), I found that setting
inline font sizes to their cascaded or computed values would make the
fonts change in size (which makes no sense to me) and this only
happened at certain text size settings (e.g. larger, smaller,
smallest, but not medium.) However, if I set the inline font size
style to what I know is the cascaded value before I run the animation,
then all is well (the fonts have already jumped in size.)

Try putting what you know to be cascade in the style attribute.

Try inspecting the currentStyle (if this is IE we're talking a

That is the
one strange workaround I had to implement in all of the animation
tests. I still don't understand what the deal was with that (and
don't really care.) I suspect my CSS is just too convoluted, but the
baseline grid does work well in all of the browsers I have tested.
What Webkit browser do you test with? Windows Safari Beta?
Yes, and also mac Safari 2 and Webkit recent build.

That
browser still has some serious issues.
It's fast. It's a lot more standards than Opera.

I probably will too. The lesson is that nothing is going to be 100%
perfect for all cases in all browsers. I figure that the best I can
shoot for is 99%. It seems to me that the currently popular libraries
take a stance like "three out of four ain't bad."

There are cases of working, not working, or somewhere in between. It
works, but it's buggy/returns inaccurate results. I guess there's a
degree of acceptibility in "not quite working" that I'm not
considering. I'll try to just take what I know about degradation and
old browser bugs and try not to cause problems. I don't like thinking
about that too much; though. Having conditions for browsers I can't
test in complicates the code.

My gCS wrapper will never return "auto", but instead returns null.

I would probably return an empty string. to avoid having to write:

if(val != null && val != "")

Interesting solution.

var TABLE = /^h/.test(documentElement.tagName) ? "table" : "TABLE";

Shorter.

That means they fixed it and my code will skip the workaround in that
and subsequent versions. Isn't feature testing wonderful?

Doesn't mean they fixed a bug. It means you've got a workaround for
something that I can't reproduce.

There are bugs in Opera's left values that I am aware of, but they
come from margins.
http://www.dhtmlkitchen.com/test/bug/getComputedStyle.html

Those two divs at the top? getPropertyValue('left') should be '0'.
Opera returns '8px', which comes from the body's margin.

Maybe a complication of trying to implement the CSSOM views spec.
It is definitely confusing to see a timeout in there.
Hmm.
I want to do this as soon as body is reached.

I don't know. It is the last thing I am worried about at the moment.
I figure when I get to the unit test for the style switcher, I will
create some more distinct (and perhaps more appealing) alternate
styles.

Yeah, it's not priority. Code first. But if there's blinking
scrollbars caused by my code, that's bad.

Think about it. If the statically positioned element added at the
bottom has a height, then the page will grow longer. Removing it will
restore the previous height. Watch the scrollbar closely during the
load and you will see it jump briefly to reflect the change.

When I think about it, I'm a little worried about the tree structure
being wrong.

<body>
<div>
<p>..parsing...
appendChild called -> <div/>

That would be an error that should not happen, but with invalid HTML,
anything is possible.

So if |x| is appended to body with height: 0, then there's no reflow?
What about if it has a width?

<snip>

Garrett
 
D

David Mark

Mostly so I can visually keep everything inside BODY. Sometimes
layouts use a main #container div. I just use BODY position: relative;

so instead of
BODY - static
#main-content - relative

I just have
BODY - relative

I like that! I am often guilty of adding an extra container div to
otherwise semantic markup. I will consider this for future multi-
column layouts.
The problem is, really, it makes harder to calculate the offset
position in Opera.

It certainly doesn't help.
A TD, TR, or TBODY that does not have a positioned ancestor should use
its TABLE.

Feel free to add to it.

I'll see if I can come up with some additional verbage.
The bug report said it best, and this is the worst part:

"-- in Mozilla, it's only available when XUL is enabled, so some
embedded Geckos
don't have it --- actually, it's worse, they have the function, but it
always
fails"https://bugzilla.mozilla.org/show_bug.cgi?id=340571

Oops. Fails how? If it returns something falsy, then I am covered.
If it blows up, I need to remove it immediately (which I should
probably do anyway.) It looks like they (and others) are going to
move on to getBoundingClientRect and NOT implement the IE chrome
border quirk. That will require an additional (trivial) feature test.
Dualling scrollable lists would have different containing blocks.
Right.


#outer-cont
#list-1-cont #list-2-cont

I should probably worry about that when I get to it, and it probably

That's my strategy for high-level UI components like scrolling lists
with draggable items. I need to make sure the foundation is sound
before considering such things. I do plan to port my popup menus to
use the re-packaged API soon after the Beta release, partly as a
simple example and partly because I need them for other things I am
doing.
wouldn't be hard enough to optimize to the point that reusing coords
was pointless.
Probably.


Or if an HTML containing a frame loaded as application/xhtml+xml, and
I had a constant TABLE == "TABLE"
(less likely)

Yes, that would be a strange application.
The only time I could think is if it's in abstract view.

I was referring to ancient browsers. Can you elaborate on your point?
See the three methods recently discussed in the thread about Peter's
feature testing article.

function isHostObject(object, property) {
return !!(typeof(object[property]) == 'object' && object[property]);

}

would work.

All three work and each has its own specific purpose.
IE5 propagates viewport dimensions to BODY, but you've pointed out a
case where there's documentElement.scrollWidth.

Don't ask me why IE5 does that though. Perhaps IE considers the
chrome border to be the only visible part of the documentElement.
http://13thparallel.com/archive/viewport/example2.htm

Three possibilities where my approach will fail:
getBoundingClientRect supported, and:
compatMode = undefined, document rendered standard => fails by
incorrectly subtracting body border width
Right.

compatMode = BackCompat, document rendered IE quirls => ditto

Why would this one fail? BackCompat => IE quirks mode => body has the
chrome border.
compatMode = BackCompat, document rendered Moz quirls => ditto

We'll have to wait and see what Moz does with getBoundingClientRect
and the chrome borders quirk.
The only reason those bugs aren't apparent is that only IE supports
getBoundingClientRect.

So compatMode is out. It means different things in different
browsers.

It can still be part of various tests, just not the only test. That
is how I have always treated it. If you test for "CSS" instead of
"BackCompat", you at least know that the HTML element is rendered. It
is when it is "BackCompat" or undefined that there is an ambiguity. I
just checked my code and it looks like I can lose it altogether.
// True only in IE5, or IE6+ quirks mode.
var IS_BODY_ACTING_ROOT = documentElement &&
documentElement.clientWidth === 0;

I just tested this and you are right. Stupid me! When looking for a
feature test for IE5 (for viewport size and document scroll size), I
checked the scrollWidth/Height properties (which do evaluate to non-
zero numbers), but must not have checked the clientWidth/Height
properties (which do indeed return 0!) I updated my code accordingly.

Thanks. I had one (multiple) object inference and now there are
none! Good thing too as it was a really ugly one.
This seems to be true only in IE5, or IE6+ in quirks mode. I don'



It goes to those sub-pixel measurements.

When converting an em to px, for clientWidth, I get an uint.

el.style.border='1.92em solid red';
el.clientWidth => 18em;

I don't follow that. Where did you convert to px and how can
clientWidth be in anything but pixels? I assume the second line has a
typo.

What does the computed border width evaluate to? I suppose it doesn't
matter much as I use clientLeft/Top when available, which are always
going to be rounded in whatever way the browser sees fit. Oh well,
none of this is going to be perfect for every possible layout.
When using larger numbers for font size, it becomes apparent that
there's also some internal miscalcuation. The numbers aren't off by 1.
They're off by a lot.

I see.
When cumulatively adding clientLeft/Top the rounded pixelValues are
added up, resulting in a much more skewed result.

This sounds like a good case for using gCS in the offset position
function, ignoring clientLeft/Top. I think I will do that.
Sorry, zIndex works with floating points. It was the fontSize that
didn't work with anything other than 100,200...900 (or keyword)

Did you mean fontWeight? And I did not know you could have non-
integer zIndex values. I can't imagine a use for them though.
Try putting what you know to be cascade in the style attribute.

That's what I do (in IE.)
Try inspecting the currentStyle (if this is IE we're talking a

The issue I mentioned is present in most browsers.

Has Google mangled your post here? The quotes seem to trail off. I
would expect currentStyle to stay the same, but in this case I imagine
it does not (at least at certain font size settings.) Now why on
earth would that be? And BTW, ever test any of this stuff with zoom
enabled in IE7? That feature is so buggy that I don't really care
about it, but I suspect it will amplify weird cases like this.
That is the


Yes, and also mac Safari 2 and Webkit recent build.

Well, I'll try your unit tests in IE5.x and perhaps you can try mine
in the Mac Safari browsers (I have heard hey differ wildly from the
Windows Beta.)
That> browser still has some serious issues.

It's fast. It's a lot more standards than Opera.

It is indeed fast at DOM traversal and perhaps a tie with IE for
smooth animations. It seems to take a bit longer to load (pages and
itself) than other browsers.

I like the font rendering too.
There are cases of working, not working, or somewhere in between. It
works, but it's buggy/returns inaccurate results. I guess there's a
degree of acceptibility in "not quite working" that I'm not
considering. I'll try to just take what I know about degradation and
old browser bugs and try not to cause problems. I don't like thinking
about that too much; though. Having conditions for browsers I can't
test in complicates the code.

That's always a concern.
I would probably return an empty string. to avoid having to write:

if(val != null && val != "")

But when would the computed style ever be an empty string? I know
cases where it can be null (e.g. display:none makes all of them null
in some browsers), but an empty string?
var TABLE = /^h/.test(documentElement.tagName) ? "table" : "TABLE";

Shorter.




Doesn't mean they fixed a bug. It means you've got a workaround for
something that I can't reproduce.

Trust me, you'd be able to reproduce this easily enough. Just get the
computed height/width style of any element with a border. When this
bug is present, the border is included in the dimensions (!) From
looking at my test for this, they don't have to be statically
positioned (as previously reported.) As for the similar left/top
issue, from looking at my test, it is either not exactly as I
remembered (and reported) it or I botched the test code when I
transplanted it into the library (doubtful.) I will have to re-test
that case.
There are bugs in Opera's left values that I am aware of, but they
come from margins.http://www.dhtmlkitchen.com/test/bug/getComputedStyle.html

My test code is currently testing whether the border width of a
positioned parent is included (which isn't what I remembered it
doing.) Could be the same issue. Regardless, I have a bullet-proof
way of fixing problems with computed dimensions and positions that
also accounts for box model differences.
Those two divs at the top? getPropertyValue('left') should be '0'.
Opera returns '8px', which comes from the body's margin.

That will happen with borders too. Apparently my test is correct, but
I just remembered the bug wrong. I typically try to forget bugs once
a feature test has been proven to work around them. As an aside, I
wonder if anyone out there reading this thread still thinks that
browser sniffing is either necessary or a good idea.
Maybe a complication of trying to implement the CSSOM views spec.

The what?
Hmm.
I want to do this as soon as body is reached.

Do you mean as soon as it has finished parsing (i.e. the end tag has
been processed.)
Yeah, it's not priority. Code first. But if there's blinking
scrollbars caused by my code, that's bad.

Yes, such twitches can seriously detract from the initial
presentation.
When I think about it, I'm a little worried about the tree structure
being wrong.

<body>
<div>
<p>..parsing...
appendChild called -> <div/>

You lost me there.
That would be an error that should not happen, but with invalid HTML,
anything is possible.

I didn't follow the previous part, can you elaborate?
So if |x| is appended to body with height: 0, then there's no reflow?

If it is statically positioned, then there is certainly a reflow, but
it won't result in any visible changes (perhaps browsers will be smart
enough to skip it?)
What about if it has a width?

Well, if the width is wider than the viewport you would get an even
worse effect (a flash of a horizontal scrollbar.) Unless you (or some
user style sheet) explicitly assign a width, you don't have to worry
about it. For safety you could set the width to 0 as well (then only !
important rules would have the potential to cause a problem.)

[snip]
 
D

dhtml

<snip>

correction:
A TD, TR, or TBODY that does not have a positioned ancestor between it
and it's table uses its TABLE as offsetParent

(so <tr| tbody style="position: relative"> makes the TR an
offsetParent)

<snip about reused coords>
I should probably worry about that when I get to it, and it probably

That's my strategy for high-level UI components like scrolling lists
with draggable items. I need to make sure the foundation is sound
before considering such things. I do plan to port my popup menus to
use the re-packaged API soon after the Beta release, partly as a
simple example and partly because I need them for other things I am
doing.
wouldn't be hard enough to optimize to the point that reusing coords
was pointless.
Probably.

Why [not] just use ownerDocument?
Because it can't be assumed to be there. The fallback branch isn't
too involved.

The only time I could think is if it's in abstract view.

I was referring to ancient browsers. Can you elaborate on your point?

document.createDocument() is the only thing I could think about where
there ight not be an ownerDocument. I don't use that, so I don't know.

Why would this one fail? BackCompat => IE quirks mode => body has the
chrome border.

You're right. But the other 2 fail.
We'll have to wait and see what Moz does with getBoundingClientRect
and the chrome borders quirk.

Mozilla generally considers the viewport to be the ICB, but they've
made all sorts of special cases like
document.documentElement.clientHeight - which returns the ICB's
height, not what would be the height of the documentElement.

Firebug:
getComputedStyle(document.documentElement,'').height;
document.documentElement.clientHeight

For any other element without scrollbars, those two would be equal.
HTML does not, in mozilla, have scrollbars, the window does, but then
they sort of made HTML work like it does in IE (partially).

[snip]
It can still be part of various tests, just not the only test. That
is how I have always treated it. If you test for "CSS" instead of
"BackCompat", you at least know that the HTML element is rendered. It
is when it is "BackCompat" or undefined that there is an ambiguity. I
just checked my code and it looks like I can lose it altogether.

I'm going to try to stay away from it.

Thanks. I had one (multiple) object inference and now there are
none! Good thing too as it was a really ugly one.
cool.

??

What does the computed border width evaluate to? I suppose it doesn't
matter much as I use clientLeft/Top when available, which are always
going to be rounded in whatever way the browser sees fit. Oh well,
none of this is going to be perfect for every possible layout.

The border width of em gets based on the fontSize, but gets rounded.
I see.


This sounds like a good case for using gCS in the offset position
function, ignoring clientLeft/Top. I think I will do that.

That is true.

[snip about IE requiring 100 based fontWeights]
Did you mean fontWeight? And I did not know you could have non-
integer zIndex values. I can't imagine a use for them though.

In doing animation transitions, just use floats, but I guess it's nota
problem anyway.
That's what I do (in IE.)


The issue I mentioned is present in most browsers.
Has Google mangled your post here?

Yeah, goddam WTF keeps happening to my post?

It's like verizon just invaded Safari.

Can you hear me now?

j/k

The quotes seem to trail off. I
would expect currentStyle to stay the same, but in this case I imagine
it does not (at least at certain font size settings.) Now why on
earth would that be? And BTW, ever test any of this stuff with zoom
enabled in IE7? That feature is so buggy that I don't really care
about it, but I suspect it will amplify weird cases like this.

Again WTF? See, I knew it. I sometimes get Gmail or groups (only once
in groups) chopping off the last half of the message on a dropped wifi
connection in Safari. The chopping mid line I cannot explain. I don't
know how that would be possible. I can't imagine I had that many edit
mistakes. 1 or two, but it's three so far.

Well, I'll try your unit tests in IE5.x and perhaps you can try mine
in the Mac Safari browsers (I have heard hey differ wildly from the
Windows Beta.)

It's not actually here. I mean, I have a mac, but not here. Last time
I checked, the offsetStuff worked the same in 2. 2's got more bugs
than 3. Send me a link. It's automated, right?
It is indeed fast at DOM traversal and perhaps a tie with IE for
smooth animations. It seems to take a bit longer to load (pages and
itself) than other browsers.

Safari kicks IE's ass in animation.
I like the font rendering too.

The soft side of David Mark.

j/k.

:D
That's always a concern.

Graceful degradation is a very good consideration, if it works. If it
can't be tested... well, if I'm not testing in a browser, it's got a
good chance of failing, and possibly in a totally different and stupid
way. It's those seemingly well-intentioned ideas, like adding a
remove() method to compliment add(). You're intuition/subconcious does
not give it as much importance. These cases are where I worry. if it
does happen, what will it do?

That's why I have dumb tests for things like Assert.isTypeof("string",
el.toString()).

I remember staying at work late one night because toString didn't work
on a certain library -- threw an error, actually. I didn't call
toString, but other code in the library did.

The author probably just put in toString for debugging but then
changed the design. Being javascript, there was no compile-time error.
The design was also a contributing factor in that one. A 3-4 long
inheritance chain, which was nicely diagrammed on the libary's website
in *reverse* UML (the graphical arrows -- which were quite attractive
-- were all backwards). Anyway, the code worked fine and went to
production. Then toString didn't work in my case. The author of the
script had to leave early, but I stayed late, trying to figure out
what was wrong.

So the point is that toString was not mission critical, was not
tested, and actually caused a problem (related to a complicated
design). I'm not saying toString is bad.

I don't have a good partial degradation strategy. If i could test more
browsers, I degrade to acceptable levels. This takes a lot more time,
from what I remember about the old version 4 browsers, it was a lot of
work to do small things. It is definitely the right approach and
attitude for web scripting.
But when would the computed style ever be an empty string? I know
cases where it can be null (e.g. display:none makes all of them null
in some browsers), but an empty string?

A lot of times.

Safari returns '' for clip
Mozilla does too, for any shorthand prop, like border. Mozilla at
first only implemented a few styles.

if(s != null && s.split(" "))

You could turn it around and use /\s/.exec(s), I suppose.

I like String methods to return strings. I like my code to be safe
enough for me to use on a bad day, and hopefully safe enough for
others, too.

Its more annoying with arrays.

var m = s.match(exp);
if(m && m[0])
v = m[0];

I would rather have had match return an empty array.

Same thing with request.getCookies() (Java).

Josh Bloch is big on this. If you haven't checked out Effective Java,
it's not too heavy reading. Good stuff.

With YUI compressor TABLE will be convered to a 1 letter symbol. This
will reduce file size. Of course the best benefit is that for the
entire life of the function, it only creates one "TABLE" string which
is needed many times. This reduces memory. fewer temp string objects.
fewer function calls.

About build... When you've got time, I'd like to ask you about YUI
compressor. (we can kill this thread) I'd really like to hear your
build process (in a new thread, of course).
Trust me, you'd be able to reproduce this easily enough. Just get the
computed height/width style of any element with a border. When this
bug is present, the border is included in the dimensions (!) From
looking at my test for this, they don't have to be statically
positioned (as previously reported.) As for the similar left/top
issue, from looking at my test, it is either not exactly as I
remembered (and reported) it or I botched the test code when I
transplanted it into the library (doubtful.) I will have to re-test
that case.

wow that blows. I can repro that. Opera.

My test code is currently testing whether the border width of a
positioned parent is included (which isn't what I remembered it
doing.) Could be the same issue. Regardless, I have a bullet-proof
way of fixing problems with computed dimensions and positions that
also accounts for box model differences.

That feature detection is very clean. Where I have comments, you have
a variable that points to the execution of an inline function. I will
eventually adopt this style into my code.
That will happen with borders too. Apparently my test is correct, but
I just remembered the bug wrong. I typically try to forget bugs once
a feature test has been proven to work around them. As an aside, I
wonder if anyone out there reading this thread still thinks that
browser sniffing is either necessary or a good idea.

I used to use it. I thought it was a bad idea, but still used it
anyway.

I wonder if everyone thinks I'm crazy for trying to get an element's
position. Sounds a lot simpler than it is.

Maybe.

The what?

CSSOM Views. That's AVK's offsetParent spec.

You lost me there.

1. polling for document.body every 60ms
2. document.body is evaluated as true in our poll, but after some of
it's content has been parsed.
3. call body.appendChild
4. what will IE do?

I don't expect you to know the answer. But it's something I'm afraid
of.

Garrett
 
D

David Mark

<snip>

correction:
A TD, TR, or TBODY that does not have a positioned ancestor between it
and it's table uses its TABLE as offsetParent

(so <tr| tbody style="position: relative"> makes the TR an
offsetParent)
Right.
That's my strategy for high-level UI components like scrolling lists
with draggable items. I need to make sure the foundation is sound
before considering such things. I do plan to port my popup menus to
use the re-packaged API soon after the Beta release, partly as a
simple example and partly because I need them for other things I am
doing.
wouldn't be hard enough to optimize to the point that reusing coords
was pointless.
Probably.

Why [not] just use ownerDocument?
Because it can't be assumed to be there. The fallback branch isn't
too involved.
The only time I could think is if it's in abstract view.
I was referring to ancient browsers. Can you elaborate on your point?

document.createDocument() is the only thing I could think about where
there ight not be an ownerDocument. I don't use that, so I don't know.

For that case, getElementDocument returns null, indicating that the
element is not part of any document. I wouldn't expect an application
to call that function for such an element, but it won't hurt anything.
You're right. But the other 2 fail.

I thought that must have been a typo.
Mozilla generally considers the viewport to be the ICB, but they've
made all sorts of special cases like
document.documentElement.clientHeight - which returns the ICB's
height, not what would be the height of the documentElement.

WHen the HTML element (or body element in quirks mode) has borders or
margins (a really odd case of course), measuring the inner viewport
area using the clientWidth/Height properties requires several feature
tests to work cross-browser. I don't remember which browsers required
which workarounds (and happily I don't have to!)
Firebug:
getComputedStyle(document.documentElement,'').height;
document.documentElement.clientHeight

For any other element without scrollbars, those two would be equal.

With the standard box model, yes.
HTML does not, in mozilla, have scrollbars, the window does, but then
they sort of made HTML work like it does in IE (partially).

Yes. Each layout engine has its own idea about what constitutes the
viewport. Getting a working viewport measurement for standards and
quirks mode was hell on earth. Opera 9 (and perhaps other versions)
has the worst quirk (bug?) of all in that the clientHeight of the
documentElement is a figure more akin to the scrollHeight (which is
ridiculous.) Oddly enough, clientWidth works as expected. (!)
[snip]
It can still be part of various tests, just not the only test. That
is how I have always treated it. If you test for "CSS" instead of
"BackCompat", you at least know that the HTML element is rendered. It
is when it is "BackCompat" or undefined that there is an ambiguity. I
just checked my code and it looks like I can lose it altogether.

I'm going to try to stay away from it.

I am going to remove all references to it when I get a chance. I've
got maybe three functions that use it and it is mostly a source of
convolution.
??



The border width of em gets based on the fontSize, but gets rounded.

Oh well.
This sounds like a good case for using gCS in the offset position
function, ignoring clientLeft/Top. I think I will do that.

That is true.

[snip about IE requiring 100 based fontWeights]
Did you mean fontWeight? And I did not know you could have non-
integer zIndex values. I can't imagine a use for them though.

In doing animation transitions, just use floats, but I guess it's nota
problem anyway.

I don't follow you there. Regardless, I have no control over what
sort of element is transitioned. I endeavored to support everything
for all of the effects. For instance, using the slide effect (the one
that Prototype fakes by requiring an extra container element),
positions a static element in its initialization.
Yeah, goddam WTF keeps happening to my post?

No idea.
It's like verizon just invaded Safari.

Can you hear me now?

Good!

j/k

The quotes seem to trail off. I


Again WTF? See, I knew it. I sometimes get Gmail or groups (only once
in groups) chopping off the last half of the message on a dropped wifi
connection in Safari. The chopping mid line I cannot explain. I don't
know how that would be possible. I can't imagine I had that many edit
mistakes. 1 or two, but it's three so far.

I've never seen such a thing. Clearly something went horribly wrong
when you posted this message.
It's not actually here. I mean, I have a mac, but not here. Last time
I checked, the offsetStuff worked the same in 2. 2's got more bugs
than 3. Send me a link. It's automated, right?

The link I sent you before is the only version online. It does not
have test page has no cases for verification of offset positioning.
And none of my testing is automated at this time. You click buttons
and observe the results. I realize this is not ideal, but it is what
I have always done. I am sure I will add some more in-depth automated
testing in the future.

The separate CSS selector test page is a hacked version of the
MooTools "SlickSpeed" test page and is semi-automatic (you click one
button to run all of the tests.) Check it out when you a get a
chance. Testing here, mine wins every time overall and wins most of
the individual tests as well. As an aside, Prototype is by far the
slowest for virtually every test. I am sure if I add Ext to the mix I
will lose in browsers that don't support XPath (and Safari 3 where I
disable XPath due to a failed feature test.) Adding the Function
constructor trick that Peter demonstrated in the tabbed pane sample
will likely rectify that.
Safari kicks IE's ass in animation.

I suppose it depends on a number of factors. In my testing, they
appear to be of similar capabilities.

FF is the worst. And what is the deal with that stupid blink when
setting opacity to 1? I had heard that FF 2 fixed this. Not here (at
least not in my test cases.) Setting opacity to .9999 and then
setting it to 1 (even when using a timeout that fires seconds later)
causes a blink. To get around this, I simply animate to .9999 and
stop (a workaround that I am not happy with.) There is an indirect
test for this in the Beta as I had to set one widget to 100% opacity
to work around some other FF rendering weirdness involving its use
with unrelated effects. I'll be interested to hear if others see the
blink.

Opera's quality is somewhere in between IE and FF.
The soft side of David Mark.

j/k.

:D

LOL. I like pretty fonts as much as the next guy. But seriously, my
primary monitor is an ancient 60" TV (S-VHS connection) and Safari's
rendering is much easier on the eyes.
Graceful degradation is a very good consideration, if it works. If it
can't be tested... well, if I'm not testing in a browser, it's got a
good chance of failing, and possibly in a totally different and stupid
way. It's those seemingly well-intentioned ideas, like adding a
remove() method to compliment add(). You're intuition/subconcious does
not give it as much importance. These cases are where I worry. if it
does happen, what will it do?

The unknown will always have to be considered when planning for
graceful degradation.
That's why I have dumb tests for things like Assert.isTypeof("string",
el.toString()).

I remember staying at work late one night because toString didn't work
on a certain library -- threw an error, actually. I didn't call
toString, but other code in the library did.

Didn't work in what way?
The author probably just put in toString for debugging but then
changed the design. Being javascript, there was no compile-time error.
The design was also a contributing factor in that one. A 3-4 long
inheritance chain, which was nicely diagrammed on the libary's website
in *reverse* UML (the graphical arrows -- which were quite attractive
-- were all backwards). Anyway, the code worked fine and went to
production. Then toString didn't work in my case. The author of the
script had to leave early, but I stayed late, trying to figure out
what was wrong.

So the point is that toString was not mission critical, was not
tested, and actually caused a problem (related to a complicated
design). I'm not saying toString is bad.

I didn't follow that, but I don't use toString on elements anyway.
I don't have a good partial degradation strategy. If i could test more
browsers, I degrade to acceptable levels. This takes a lot more time,
from what I remember about the old version 4 browsers, it was a lot of
work to do small things. It is definitely the right approach and
attitude for web scripting.



A lot of times.

LOL. I was blinded by my own abstractions. I convert them to null.
Safari returns '' for clip

That makes sense as clip is shorthand.
Mozilla does too, for any shorthand prop, like border. Mozilla at
first only implemented a few styles.

Computed shorthand styles sounds like a contradiction in terms to me.
I wouldn't rely on being able to query styles like that.
if(s != null && s.split(" "))

You could turn it around and use /\s/.exec(s), I suppose.

What are you doing there?
I like String methods to return strings. I like my code to be safe
enough for me to use on a bad day, and hopefully safe enough for
others, too.

Generally, I prefer that they return strings only for valid results
and null otherwise. Some functions are allowed to return empty
strings and some are not. The gCS wrapper is one that is not.
Its more annoying with arrays.

var m = s.match(exp);
if(m && m[0])
v = m[0];

I would rather have had match return an empty array.

I don't follow what you are doing with these last two examples.
Same thing with request.getCookies() (Java).

I don't concern myself with Java. I have enough headaches with
browser scripting. I haven't looked at my cookie code in ages, but
IIRC, it returns null only if the cookie does not exist. An empty
string would indicate an empty (no calorie) cookie. Granted, most
applications likely wouldn't care one way or the other.

Speaking of those, it was a pain, but I have crumbs working in a way
that is compatible with ASP's "keyed" cookies. I find that very
useful.
Josh Bloch is big on this. If you haven't checked out Effective Java,
it's not too heavy reading. Good stuff.

Java doesn't exist as far as I am concerned.
With YUI compressor TABLE will be convered to a 1 letter symbol. This
will reduce file size. Of course the best benefit is that for the

Yes, I designed to leverage that. 330K+ for the full build (with
fairly sparse comments) minifies to something like 110K. Just to
compare it to other libraries, I GZIP'ed the resulting file and it is
almost exactly 40K. Granted, it would take one hellacious application
to require the full build.
entire life of the function, it only creates one "TABLE" string which
is needed many times. This reduces memory. fewer temp string objects.
fewer function calls.

Yes, I like that trick. I might have to copy it.
About build... When you've got time, I'd like to ask you about YUI
compressor. (we can kill this thread) I'd really like to hear your
build process (in a new thread, of course).

Okay. In a nutshell, the YUI compressor is outstanding. It has never
let me down.
wow that blows. I can repro that. Opera.

Doesn't it? As you can imagine, the feature test is simple.
That feature detection is very clean. Where I have comments, you have
a variable that points to the execution of an inline function. I will
eventually adopt this style into my code.

Thanks. I copied that pattern from Richard Cornford's sample
scripts. AFAIK, he invented the "one-off" feature test. My whole
library is based on it, so I will certainly give him an
acknowledgement (if he wants one.)
I used to use it. I thought it was a bad idea, but still used it
anyway.

I used to use it for virtually everything. Who didn't in the 90's? I
even did server side sniffing. What is unthinkable is that people
continue to do it in 2008. I've seen blog posts recently that
advocated server side sniffing for dealing with the XHTML MIME type
issue. (!)
I wonder if everyone thinks I'm crazy for trying to get an element's
position. Sounds a lot simpler than it is.

Maybe.

It is needed for some applications. Personally, I try to avoid it at
all costs.
CSSOM Views. That's AVK's offsetParent spec.

Oh. That thing.
1. polling for document.body every 60ms
2. document.body is evaluated as true in our poll, but after some of
it's content has been parsed.
3. call body.appendChild
4. what will IE do?

IE6 will throw the dreaded "operation aborted" error AFAIK. You
really need to change that. See the attachDocumentReadyListener
ticket in CWR.
I don't expect you to know the answer. But it's something I'm afraid
of.

Be very afraid. There's no catastrophe (short of ill-formed XHTML)
that can compare to "operation aborted."

BTW, do you know in what way gBOF fails in embedded Mozilla-based
browsers? An exception? If so, I need to get rid of it ASAP.
 
D

dhtml

[snip about offsetParent]


[snip about rying to get the position of an element in abstract view][
[snip]


[snip about several feature tests req'd to calc the viewport width in
quirks mode]

[snip about detecting viewport dimensions]

[snip about compatMode]
Opera seems to have problems calculating ems.

http://dhtmlkitchen.com/ape/test/tests/dom/style-f-test.html

testGetComputedStyle : function() {
var Assert = YAHOO.util.Assert;
var ArrayAssert = YAHOO.util.ArrayAssert;
var dom = APE.dom;

var testNode = document.getElementById( "testNode" );
var rule = this.data.rule;
rule.style.fontSize = "12px";
rule.style.fontFamily="fantasy";
rule.style.padding = "6em";
rule.style.height = "1000em";

var foundFontSize = dom.getStyle(testNode, "fontSize" );
var foundPadding = dom.getStyle(testNode, "paddingBottom" );
var foundHeight = dom.getStyle(testNode, "height" );

Assert.areEqual( "12px", foundFontSize );
//Assert.areEqual( (12 * 6) + "px", foundPadding );
Assert.areEqual( "12000px", foundHeight,
"height was set in em, and was either \nreturned wrong or
miscalc'd by the browser." );

},

FAIL testGetComputedStyle: height was set in em, and was either
returned wrong or miscalc'd by the browser. Expected: 12000px (string)
Actual:12144px (string)


Using currentStyle, well, it's completely f'd in Opera.
currentStyle.opacity => always 1
letterSpacing => 1, when it should be 0
currentStyle.fontSize => floor(expected) + unit.


Opera 9.25:

javascript:void(document.body.style.fontSize ='.9em');
javascript:alert(document.body.currentStyle.fontSize );

result:

"0em"

This one's really weird:
javascript:alert(document.getElementsByTagName("head")
[0].currentStyle.fontSize);

currentStyle is broken in Opera.

Opera is worse at Math than I am.
That is true.
[snip about IE requiring 100 based fontWeights]
Did you mean fontWeight? And I did not know you could have non-
integer zIndex values. I can't imagine a use for them though.
In doing animation transitions, just use floats, but I guess it's nota
problem anyway.

I don't follow you there.

floating point numbers for zIndex. I guess it's nota prob.

Regardless, I have no control over what
sort of element is transitioned. I endeavored to support everything
for all of the effects. For instance, using the slide effect (the one
that Prototype fakes by requiring an extra container element),
positions a static element in its initialization.

I did change taht example I showed you to use em for fonts. It's
probably your TV.

[snip]

The separate CSS selector test page is a hacked version of the
MooTools "SlickSpeed" test page and is semi-automatic (you click one
button to run all of the tests.) Check it out when you a get a
chance. Testing here, mine wins every time overall and wins most of
the individual tests as well. As an aside, Prototype is by far the
slowest for virtually every test. I am sure if I add Ext to the mix I
will lose in browsers that don't support XPath (and Safari 3 where I
disable XPath due to a failed feature test.) Adding the Function
constructor trick that Peter demonstrated in the tabbed pane sample
will likely rectify that.

I missed that one.

[animation]
FF is the worst. And what is the deal with that stupid blink when
setting opacity to 1?

I saw the blink in old 1.x, pre 1.5. I thought it got fixed. I haven't
seen it. I don't like having such workarounds either.

There's not test for "did blink".

I'd be inclined to let it just blink. This kind of browser bug is
unacceptable, and especially if it's a regression. If a browser cannot
correctly support a feature, it should not support it in a broken way.
This seems broken to me.
LOL. I like pretty fonts as much as the next guy. But seriously, my
primary monitor is an ancient 60" TV (S-VHS connection) and Safari's
rendering is much easier on the eyes.
Weird.

[snip]
That's why I have dumb tests for things like Assert.isTypeof("string",
el.toString()).
I remember staying at work late one night because toString didn't work
on a certain library -- threw an error, actually. I didn't call
toString, but other code in the library did.

Didn't work in what way?

They had a to string that had a ReferenceError (they changed the API)

toString : function() {
return this.noexistant.prop;
}
I didn't follow that, but I don't use toString on elements anyway.


They had a toString that was broken. The problem with not testing is
it invites problems to creep in to less common execution paths.

I use toString a lot. It makes debugging easier (for me).
I don't have a good partial degradation strategy. If i could test more
browsers, I degrade to acceptable levels. This takes a lot more time,
from what I remember about the old version 4 browsers, it was a lot of
work to do small things. It is definitely the right approach and
attitude for web scripting.
A lot of times.

LOL. I was blinded by my own abstractions. I convert them to null.


Safari returns '' for clip

That makes sense as clip is shorthand.
Mozilla does too, for any shorthand prop, like border. Mozilla at
first only implemented a few styles.

Computed shorthand styles sounds like a contradiction in terms to me.
I wouldn't rely on being able to query styles like that.


if(s != null && s.split(" "))
You could turn it around and use /\s/.exec(s), I suppose.

What are you doing there?


I like String methods to return strings. I like my code to be safe
enough for me to use on a bad day, and hopefully safe enough for
others, too.

Generally, I prefer that they return strings only for valid results
and null otherwise. Some functions are allowed to return empty
strings and some are not. The gCS wrapper is one that is not.


Its more annoying with arrays.
var m = s.match(exp);
if(m && m[0])
v = m[0];
I would rather have had match return an empty array.

I don't follow what you are doing with these last two examples.

using String.prototype.match.

match returns an array, or null if the array would be empty.

I'd rather have an empty array than have to do a null check.

[snip]

Okay. In a nutshell, the YUI compressor is outstanding. It has never
let me down.

I'm using it, but I've got to get it hooked into ANT and automate the
process.

[snip]

IE6 will throw the dreaded "operation aborted" error AFAIK. You
really need to change that. See the attachDocumentReadyListener
ticket in CWR.

Grabbing documentElement.innerHTML every 10ms seems pretty
inefficient. That's a lot of large strings. I've got a
ContentLoadAdapter.
Be very afraid. There's no catastrophe (short of ill-formed XHTML)
that can compare to "operation aborted."

I remember now, yeah.
BTW, do you know in what way gBOF fails in embedded Mozilla-based
browsers? An exception? If so, I need to get rid of it ASAP.

All I know is what I read in that bugzilla report. I would guess that
if it's available but doesn't work, it would return a Null Object (all
0's), but then, it might return null or throw an Error. You could try
a capability detection test to see if it works.

getBoxObjectFor = (function(){
// create element,
// do some assertions.
// return supported.
})();

Check the buzilla rep't to see if it throws an error or how it fails.
The reporter had strong words about not using it.

Garrett
 
D

David Mark

[snip about offsetParent]

[snip about rying to get the position of an element in abstract view][
[snip]

[snip about several feature tests req'd to calc the viewport width in
quirks mode]

[snip about detecting viewport dimensions]

[snip about compatMode]



Opera seems to have problems calculating ems.

http://dhtmlkitchen.com/ape/test/tests/dom/style-f-test.html

testGetComputedStyle : function() {
        var Assert = YAHOO.util.Assert;
        var ArrayAssert = YAHOO.util.ArrayAssert;
        var dom = APE.dom;

        var testNode = document.getElementById( "testNode" );
        var rule = this.data.rule;
        rule.style.fontSize = "12px";
        rule.style.fontFamily="fantasy";
        rule.style.padding = "6em";
        rule.style.height = "1000em";

        var foundFontSize = dom.getStyle(testNode, "fontSize" );
        var foundPadding = dom.getStyle(testNode, "paddingBottom" );
        var foundHeight = dom.getStyle(testNode, "height" );

        Assert.areEqual( "12px", foundFontSize );
        //Assert.areEqual( (12 * 6) + "px", foundPadding  );
        Assert.areEqual( "12000px", foundHeight,
            "height was set in em, and was either \nreturned wrong or
miscalc'd by the browser." );

    },

FAIL testGetComputedStyle: height was set in em, and was either
returned wrong or miscalc'd by the browser. Expected: 12000px (string)
Actual:12144px (string)

Oh well.
Using currentStyle, well, it's completely f'd in Opera.
currentStyle.opacity => always 1
letterSpacing => 1, when it should be 0
currentStyle.fontSize => floor(expected) + unit.

Opera 9.25:

javascript:void(document.body.style.fontSize ='.9em');
javascript:alert(document.body.currentStyle.fontSize );

result:

"0em"

This one's really weird:
javascript:alert(document.getElementsByTagName("head")
[0].currentStyle.fontSize);

currentStyle is broken in Opera.

Last I tested my cascaded style function in Opera, it was returning
some really strange results. My combined get style function always
tries to get the computed style first. I wasn't even aware that
currentStyle was available outside of IE until I saw that the test
buttons for that were enabled in Opera. Does it support runtimeStyle
too? I didn't even bother to create a test for that one.

And oh by the way, something is wrong with that cascaded to computed
IE hack in IE5.5. I ran into that during testing tonight.
Opera is worse at Math than I am.

An odd attribute for computer software. It must be hanging out with
some of Google's processes.
When using larger numbers for font size, it becomes apparent that
there's also some internal miscalcuation. The numbers aren't off by 1.
They're off by a lot.
I see.
When cumulatively adding clientLeft/Top the rounded pixelValues are
added up, resulting in a much more skewed result.
This sounds like a good case for using gCS in the offset position
function, ignoring clientLeft/Top.  I think I will do that.
That is true.
[snip about IE requiring 100 based fontWeights]
Did you mean fontWeight?  And I did not know you could have non-
integer zIndex values.  I can't imagine a use for them though.
In doing animation transitions, just use floats, but I guess it's nota
problem anyway.
I don't follow you there.

floating point numbers for zIndex. I guess it's nota prob.

I can't conceive of an effect that would use zIndex anyway.
Regardless, I have no control over what


I did change taht example I showed you to use em for fonts. It's
probably your TV.

Do you mean my video card? It is one of those crappy ATI All-in-
Wonder things. I'm on my second one of those in that box as the first
one had a meltdown (literally) and had to be shipped back for
replacement.
[snip]


The separate CSS selector test page is a hacked version of the
MooTools "SlickSpeed" test page and is semi-automatic (you click one
button to run all of the tests.)  Check it out when you a get a
chance.  Testing here, mine wins every time overall and wins most of
the individual tests as well.  As an aside, Prototype is by far the
slowest for virtually every test.  I am sure if I add Ext to the mix I
will lose in browsers that don't support XPath (and Safari 3 where I
disable XPath due to a failed feature test.)  Adding the Function
constructor trick that Peter demonstrated in the tabbed pane sample
will likely rectify that.

I missed that one.

Peter's selector query? It's in the tabbed pane thread somewhere.
[animation]
FF is the worst.  And what is the deal with that stupid blink when
setting opacity to 1?

I saw the blink in old 1.x, pre 1.5. I thought it got fixed. I haven't

I thought they did too. I'm not sure what is going on with that, but
it happens on two different test boxes. It isn't just during
animations either. Just setting opacity to 1 and then something else
(or vice versa) triggers it. It might be a quirk of my aforementioned
torturous style rules as I checked an old page that had a fade effect
and it didn't do it. That one used a similar but less efficient
setOpacity function (set all three variations of the style every
time.) I really need to run some more tests to compare the two
functions in FF.
seen it. I don't like having such workarounds either.

There's not test for "did blink".
Right.


I'd be inclined to let it just blink. This kind of browser bug is

If it turns out that the majority of people who try the test page are
not seeing the blink (it is impossible to miss), I might go that
route.
unacceptable, and especially if it's a regression. If a browser cannot
correctly support a feature, it should not support it in a broken way.
This seems broken to me.
Certainly.


Weird.

Not really. I hate hunching over a keyboard at a desk. I have a
wireless keyboard and mouse so I can sit on the couch in the den. The
PC is basically part of my entertainment system. The secondary
monitor is a touch screen mounted in the wall next to it. I typically
drag Winamp and my "soft phone" to that one. I've got some home
automation software on that box too, so I can use the touch screen to
control and monitor various things in the house too.
[snip]

[snip]
IE6 will throw the dreaded "operation aborted" error AFAIK.  You
really need to change that.  See the attachDocumentReadyListener
ticket in CWR.

Grabbing documentElement.innerHTML every 10ms seems pretty
inefficient. That's a lot of large strings. I've got a
ContentLoadAdapter.

Sounds like a much better idea.
I remember now, yeah.


All I know is what I read in that bugzilla report. I would guess that
if it's available but doesn't work, it would return a Null Object (all
0's), but then, it might return null or throw an Error. You could try
a capability detection test to see if it works.

getBoxObjectFor = (function(){
// create element,
// do some assertions.
// return supported.

})();

I am guarding against a null return currently, but plan to pull the
method completely when I get a chance. If the authors of FF say it is
a bad idea to use it, I believe them.
Check the buzilla rep't to see if it throws an error or how it fails.
The reporter had strong words about not using it.

The documents I read didn't say how it fails.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,023
Latest member
websitedesig25

Latest Threads

Top