Best Performance Javascript on IE6 for finding top and left usingoffsetTop and offsetLeft

G

GTalbot

[snipped]


Orphaned (removed from the document) elements can become ActiveX
objects behind the scenes.  IIRC, orphaning by innerHTML replacement
is a sure bet.

if (typeof element.offsetParent == 'unknown') {
    (element.offsetParent); // Boom

}

So you wouldn't normally pass such an element to such a function
(offset position makes no sense for orphans).  The try-catch hides
such mistakes.


Ok. I understand now.

That's ridiculous.  If your page is buggy and/or unreliable,


No. The warning/advice/browser support notice they should get is that
the webpage complies with all known mature and stable web standards
(HTML 4, CSS 2.1, WCAG) and that the browser version they use may not
be able to comply accordingly so they may see a strange offset here, a
gap there, an unexpected overlapping over here, etc... which is very
typical of IE6 (hasLayout, broken float+clear model, broken inline
level model, adjoining margin collapsing, etc). If the page has been
tested without CSS enabled, without javascript support enabled,
without image download support and works reasonably correctly or
accordingly, then the web author can calmly and confidently claim that
IE6 *_is_* the problem here and not his work.

I have seen and read dozens, maybe 200 sites which have explained why
IE6 is unreliable, unsafe, not-trustworthy, very buggy, non-compliant,
etc.. and I think often they made a good case. The best ones are the
ones (with a good soft touch) which address the intelligence of users
and are not at all agressive. A scare campain on security is generally
not very convincing (e.g. the swine flu vaccine campain in my country
started first as a scare campain and it created a reverse behavior
than expected when it became time to get vaccinated). An agressive
campain is less fruitful: pure force never succeeds on the internet.
That's another topic altogether.  Some corporate users are simply
stuck with IE6/7 and will be for years.

If they are stuck with IE6/7 for years, it is because someone
somewhere made a terrible decision at some point. So, they pay now .

Lots of PC-savvy corporate users are clueless about browsers and/or
disallowed from making decisions about which browsers to use.


I understand. I think a campain can still be effective when targeting
straight at normal non-corporate users.
There's very little you can do ... unless you're a friend of them and
you visit them at home.
[snipped]


 I don't think you have time
to visit every "senior" at home either.

Occasionally, I can give my advice to older friends and seniors that I
know of and help them.


[snipped]
Nobody wants to hear about it from your site, unless your site is
about browsers.

A part of my web authoring website is about browsers. One thing I
noticed is how often I get visitors linking to my IE bugs webpages and/
or coming from websites campaining to eradicate IE6 or IE7 or just IE.

regards, Gérard
 
G

Garrett Smith

David said:
David said:
David Mark wrote:
Thomas 'PointedEars' Lahn wrote:
moha297 wrote:
[...] [...]

function documentClicked(ev){ }
JSLint doesn't allow that perfectly valid, easily understandable program
to pass.
Bad style. Makes it more confusing than it needs to be (for beginners
who may have to maintain it). And you can turn that one off I think.
It is fine that way; nothing really confusing about it. It is
syntactically valid, standard code for any js engine.

You know exactly what I mean.

I got that you think it is bad style, but I don't see it like that. I
see it as potentially *good* style, depending on how it is used.

I use that a lot in defining modules.

// Scope.
(function(){
APE.mixin( APE.dom,
{
method1 : method1,
method2 : method2
});
function method1(){/*...*.}
function method2(){/*...*.}
})();

I find this way is nice for me because it is declarative from the top of
the file. I know right away what is being added to APE.dom. I can look
further down to see that.

The only trouble is when you have some expressions that need to be part
of the export, and those expressions need variables defined. Then it
gets a little messsy.

// Scope.
(function(){

var x = 10,
y = x + Math.random();

APE.mixin( APE.dom,
{
method1 : method1,
method2 : method2,
y : y
});
function method1(){/*...*/}
function method2(){/*...*/}
})();

To me that is uglier because the variable statement is up at the top. I
prefer to see more like:-

// Scope.
(function(){

APE.mixin( APE.dom,
{
method1 : method1,
method2 : method2,
y : getY()
});
function method1(){/*...*/}
function method2(){/*...*/}
function getY(){
return 10 + Math.random();
}
})();

Especially if they are coming to JS from another language.


So what?

I know beginners are sometimes surprised to see that, but they are also
surprised with other things like typeof anArray == "object" or a == b,
yet, a !== b, new F().constructor !== F, augmented scope chain in catch
clause.

A beginner would probably know that that FunctionDeclaration is added to
the variable object upon entering the execution context. He would
probably figure that "you can do that" and "it works", without
understanding the mechanics of it.

If he decided to change FunctionDeclaration around and instead use
FunctionExpression:-

document.addEventListener("click", documentClicked, false);
var documentClicked = function(ev) {};

Whoops, all of a sudden "it doesn't work." Bummer. I guess "you can't do
that."

From a beginner's point of view, it wouldn't be so confusing. It might
seem odd, but once he saw it running, he would know that it works.
Augmented scope of course. It's best to reference alert as a method
of the window object (that's what it is after all). Then these
questions don't come up.

Ah, no, that is not true. There is no augmented scope for a finally clause.

Putting it in the catch clause, there would be an augmented scope, but
it wouldn't matter unless the identifier for the catch clause was `alert`.
The window reference of course. He wants to see it referenced as a
property of an object (e.g. the Global object). As for frames,
consider this:-

e = e || window.event; // No good for elements in other frames

events, not elements.
So that "error" in JSLint helps to spot these situations as well.

That's a long stretch. Is JSLint really encouraging passing around
window references? I can't say I've tried passing window.event to
another frame.
In a browser (assuming a browser), the Global object has a - document
- property as well. At least, that is the underlying assumption here.

window is a property of global object and acts as the global object
itself. If using unqualified window is an Error because won't work
across frames, then unqualified document should be, too.
 
D

David Mark

David said:
David Mark wrote:
David Mark wrote:
Thomas 'PointedEars' Lahn wrote:
moha297 wrote:
[...]
[...]
function documentClicked(ev){ }
JSLint doesn't allow that perfectly valid, easily understandable program
to pass.
Bad style.  Makes it more confusing than it needs to be (for beginners
who may have to maintain it).  And you can turn that one off I think.
It is fine that way; nothing really confusing about it. It is
syntactically valid, standard code for any js engine.
You know exactly what I mean.

I got that you think it is bad style, but I don't see it like that. I
see it as potentially *good* style, depending on how it is used.

I use that a lot in defining modules.

// Scope.
(function(){
   APE.mixin( APE.dom,
      {
        method1 : method1,
        method2 : method2
   });
   function method1(){/*...*.}
   function method2(){/*...*.}

})();

I find this way is nice for me because it is declarative from the top of
the file. I know right away what is being added to APE.dom. I can look
further down to see that.

Why? Look up instead.
The only trouble is when you have some expressions that need to be part
of the export, and those expressions need variables defined. Then it
gets a little messsy.

// Scope.
(function(){

   var x = 10,
       y = x + Math.random();

   APE.mixin( APE.dom,
      {
        method1 : method1,
        method2 : method2,
        y : y
   });
   function method1(){/*...*/}
   function method2(){/*...*/}

})();

I don't see why you want those declarations _after_ the mixin call.
Seems backwards to me.
To me that is uglier because the variable statement is up at the top. I
prefer to see more like:-

// Scope.
(function(){

   APE.mixin( APE.dom,
      {
        method1 : method1,
        method2 : method2,
        y : getY()
   });
   function method1(){/*...*/}
   function method2(){/*...*/}
   function getY(){
       return 10 + Math.random();
   }

OMFG. Are you serious?
})();



I know beginners are sometimes surprised to see that, but they are also
surprised with other things like typeof anArray == "object" or a == b,
yet, a !== b, new F().constructor !== F, augmented scope chain incatch
clause.

Yes. So I think it is best to alleviate what you can.
A beginner would probably know that that FunctionDeclaration is added to
the variable object upon entering the execution context.

I assume you mean they would _not_ know that.
He would
probably figure that "you can do that" and "it works", without
understanding the mechanics of it.
Right.


If he decided to change FunctionDeclaration around and instead use
FunctionExpression:-

document.addEventListener("click", documentClicked, false);
var documentClicked = function(ev) {};

Whoops, all of a sudden "it doesn't work." Bummer. I guess "you can't do
that."

 From a beginner's point of view, it wouldn't be so confusing. It might
seem odd, but once he saw it running, he would know that it works.



Ah, no, that is not true. There is no augmented scope for a finally clause.

Yes, I was thinking of the catch clause.
Putting it in the catch clause, there would be an augmented scope, but
it wouldn't matter unless the identifier for the catch clause was `alert`..

Why even worry about mix-ups like this?
events, not elements.


That's a long stretch. Is JSLint really encouraging passing around
window references?

I'm not saying it is encouraging anything. Just that that "error" can
come in handy in some contexts.
I can't say I've tried passing window.event to
another frame.

I don't follow. My point is that the above code only works for
elements of one window. To work for frames, it would need to figure
the window that contains the target element. For such applications,
the unqualified window references are few and far between (if any).
There are none in My Library.
window is a property of global object and acts as the global object
itself.

Not necessarily. There's really no telling what goes on behind the
scenes with that (they may or may not be the same object).
If using unqualified window is an Error because won't work
across frames, then unqualified document should be, too.

As mentioned, I never liked that change (window as implied global).
 
L

Lasse Reichstein Nielsen

Garrett Smith said:
OffsetTop and offsetParent are really bad legacy features. They're
defined using circular definition. See MSDN:
| OffsetTop:
| Retrieves the calculated top position of the object relative to the
| layout or coordinate parent, as specified by the offsetParent
| property.
http://msdn.microsoft.com/en-us/library/ms534302(VS.85).aspx

| OffsetParent:
| Retrieves a reference to the container object that defines the
| offsetTop and offsetLeft properties of the object.
http://msdn.microsoft.com/en-us/library/ms534302(VS.85).aspx

That's not a circular definition. The two definitions say the *same*
thing: An object has a layout/coordinate parent (referenced through its
offsetParent property), and a position relative to the layout/coordinate
parent (referenced through the offsetTop and offsetLeft properties).

The "offsetParent" definition is a little vague in that it confuses
the offsetTop/offsetLeft properties and their values.
Other borwsers, desparate to get sites to work, copied the badly
defined features differently.

In addition to the cases you mentioned, the OP's function will fail
when offsetParent has a border (in most browsers).

That should probably be specified in the definition as well - which
point of element is positioned at the offsetTop/offsetLeft point -
in this case the top-left point of the border, if any), and what
point of the layout parent is it relative to (the top-left point of
the padding).

I admit that it's not a great definition, but it's not circular.

/L 'and if that's the best one can say of a definition ...'
 
L

Lasse Reichstein Nielsen

Lasse Reichstein Nielsen said:
That's not a circular definition. The two definitions say the *same*
thing: An object has a layout/coordinate parent (referenced through its
offsetParent property), and a position relative to the layout/coordinate
parent (referenced through the offsetTop and offsetLeft properties).

The "offsetParent" definition is a little vague in that it confuses
the offsetTop/offsetLeft properties and their values.


That should probably be specified in the definition as well - which
point of element is positioned at the offsetTop/offsetLeft point -
in this case the top-left point of the border, if any), and what
point of the layout parent is it relative to (the top-left point of
the padding).

Well, that was based on guessing from the quoted text. Reality is
a little more complex.

Internet Explorer(8) and Opera calculate offsetTop/offsetLeft as the
distances from the top-left point of the border of the layout parent
to the top-left point of the border of the child.

WebKit and Firefox calcualte it as the distance from the top-left
point of the padding of the layout parent to the top-left point of the
border of the child.

I.e., all of them include the padding of the parent and the margin of
the child, but IE and Opera include the border of the parent as well
(which is the useful thing to do, because then you can actually add
them up following the offsetParent chain and only need the margin of
the root to find the correct position).

Quick check code:

<div style="position:relative;width:200px;height:200px;
margin:1px;border:2px solid red;padding:4px;">
<div id="foo" style="position:absolute;width:100px;height:100px;
border:16px solid green;margin:8px;padding:32px;"
onclick="alert([this.offsetParent, this.offsetTop, this.offsetLeft])">
</div></div>

/L
 
T

Thomas 'PointedEars' Lahn

Garrett said:
I got that you think it is bad style, but I don't see it like that. I
see it as potentially *good* style, depending on how it is used.

I use that a lot in defining modules.

// Scope.
(function(){
APE.mixin( APE.dom,
{
method1 : method1,
method2 : method2
});
function method1(){/*...*.}
function method2(){/*...*.}
})();

I find this way is nice for me because it is declarative from the top of
the file. I know right away what is being added to APE.dom. I can look
further down to see that.

To be fair, that is what a lint-like tool is supposed to flag:

,-<http://en.wikipedia.org/wiki/Lint_(software)>
|
| In computer programming, lint was the name originally given to a
| particular program that flagged some suspicious and non-portable
| constructs (likely to be bugs) in C language source code. The term is now
| applied generically to tools that flag suspicious usage in software
| written in any computer language. The term lint-like behavior is
| sometimes applied to the process of flagging suspicious language usage.
| lint-like tools generally perform static analysis of source code.
| [...]
| Suspicious usage includes: variables being used before being set,
| conditions that are constant, and calculations whose result is likely
| to be outside the range of values representable in the type used.

However, IMHO, such a tool, when written for analyzing ECMAScript
implementations, SHOULD be aware that variable instantiation comes before
execution, thus function declarations need to be considered to be variable
initializations even if they come last in an execution context. I do not
think that would contradict the purpose of static code analysis.

So, at most, there should be a warning here, and it should be possible to
disable that warning.
The only trouble is when you have some expressions that need to be part
of the export, and those expressions need variables defined. Then it
gets a little messsy.

// Scope.
(function(){

var x = 10,
y = x + Math.random();

APE.mixin( APE.dom,
{
method1 : method1,
method2 : method2,
y : y
});
function method1(){/*...*/}
function method2(){/*...*/}
})();

Why, you could use the more complex expression in the initializer:

// Scope.
(function(){
var x = 10;

APE.mixin( APE.dom,
{
method1 : method1,
method2 : method2,
y : x + Math.random()
});

function method1(){/*...*/}
function method2(){/*...*/}
})();
To me that is uglier because the variable statement is up at the top. I
prefer to see more like:-

// Scope.
(function(){

APE.mixin( APE.dom,
{
method1 : method1,
method2 : method2,
y : getY()
});
function method1(){/*...*/}
function method2(){/*...*/}
function getY(){
return 10 + Math.random();
}
})();

You can also lose two declarations and write

// Scope.
(function(){
APE.mixin( APE.dom,
{
method1 : method1,
method2 : method2,
y : (function(x) { return x + Math.random(); })(10)
});

function method1(){/*...*/}
function method2(){/*...*/}
})();

instead.


PointedEars
 
G

GTalbot

That's not a circular definition. The two definitions say the *same*
thing: An object has a layout/coordinate parent (referenced through its
offsetParent property), and a position relative to the layout/coordinate
parent (referenced through the offsetTop and offsetLeft properties).

The "offsetParent" definition is a little vague in that it confuses
the offsetTop/offsetLeft properties and their values.



That should probably be specified in the definition as well - which
point of element is positioned at the offsetTop/offsetLeft point -
in this case the top-left point of the border, if any), and what
point of the layout parent is it relative to (the top-left point of
the padding).

I admit that it's not a great definition, but it's not circular.

/L 'and if that's the best one can say of a definition ...'

Circular, same thing, vague, confusing... It really sound similar to
me. 4 years ago, I created this test

http://www.gtalbot.org/BrowserBugsSection/MSIE6Bugs/OffsetValues.html

and said that the definitions were "circular, mutually inter-dependent
on each other" and I still believe they are circular today.

The "relative to the layout or coordinate parent" words do not mean
much by themselves. Only after a lot of testing (trials and errors)
and examining empirical results, you could figure out what that means.

e.g.:
a.b
"a" is an object that defines the property "b" of object "a".
"b" is the property defined by the object "a".
is very much circular to me.

Finally, MSDN has lots of editorial problems of this sort. Missing
important info (like border in this offsetParent case), missing good
useful+meaningful examples, always missing valid+compliant examples,
all kinds of mistakes, sometimes (deliberate?) exaggerations, IE-
centric code (eg named form controls accessed unshamelessly in global
scope), IE-specific code (eg document.all), missing required
attributes everywhere in examples, no doctype decl., over-excessive
redundance and emphasis on using X-UA meta-tag to trigger IE8
standards mode, etc.

MSDN is often the abbreviation for misunderstanding or the
abbreviation for MisunderStanding Developers Network.

Regards and season's greetings, Gérard
 
D

David Mark

Well, that was based on guessing from the quoted text. Reality is
a little more complex.

Internet Explorer(8) and Opera calculate offsetTop/offsetLeft as the
distances from the top-left point of the border of the layout parent
to the top-left point of the border of the child.

Some versions of Opera have that deviation. If 8 introduced that, I'm
blissfully unaware (feature testing takes care of that for me).
 
G

Garrett Smith

Lasse said:
[...]
That should probably be specified in the definition as well - which
point of element is positioned at the offsetTop/offsetLeft point -
in this case the top-left point of the border, if any), and what
point of the layout parent is it relative to (the top-left point of
the padding).

Well, that was based on guessing from the quoted text. Reality is
a little more complex.

The definition of offsetParent requires a guess about what a "layout
parent" or "container object".
Internet Explorer(8) and Opera calculate offsetTop/offsetLeft as the
distances from the top-left point of the border of the layout parent
to the top-left point of the border of the child.

WebKit and Firefox calcualte it as the distance from the top-left
point of the padding of the layout parent to the top-left point of the
border of the child.

We still don't know what "container object" or "layout parent" is. Your
explanation doesn't define those.
I.e., all of them include the padding of the parent and the margin of
the child, but IE and Opera include the border of the parent as well
(which is the useful thing to do, because then you can actually add
them up following the offsetParent chain and only need the margin of
the root to find the correct position).

Ah, the browser perversions with offsetTop never stop, do they?

A slightly older versions Opera somewhere around v8.5 - v9.25
(uncertain) had this bug for over a year, corresponding to the CSSOM
View editor's Draft. Did the editor's draft copy Opera, or did Opera
copy the editor's draft? I asked Anne this question repeatedly about 18
months ago. I didn't ever get an answer.

Then Anne (the editor) changed draft so that offsetTop was defined as
measuring from border edge of A to padding edge of the offsetParent.
Opera changed to match this change.

Apparently Opera has once again reverted to the odd behavior. IE seems
to have been following the older Editor's draft, too, before it became a
Working Draft.

IE and Opera are flip-flopping on what offsetTop is.

Thank you for bringing this change to my attention. I was unaware of
that change in Opera and in IE.

That finding reinforces what I wrote earlier about offsetTop and
offsetParent being really bad legacy features. Developers should avoid.
They are far too unreliable across browsers and versions.

The most advisable solution is to create a wrapper to find an element's
position. The wrapper should prefer to use getBoundingClientRect, where
supported.

It is a very bad idea to make a generalization of how offsetTop works.
That type of generalization is common for browser vendors, and is the
single largest contributing factor to web browser incompatibility.
 
G

Garrett Smith

David said:
David said:
David Mark wrote:
David Mark wrote:
Thomas 'PointedEars' Lahn wrote:
moha297 wrote:
[...]
[...]
function documentClicked(ev){ }
JSLint doesn't allow that perfectly valid, easily understandable program
to pass.
Bad style. Makes it more confusing than it needs to be (for beginners
who may have to maintain it). And you can turn that one off I think.
It is fine that way; nothing really confusing about it. It is
syntactically valid, standard code for any js engine.
You know exactly what I mean.
I got that you think it is bad style, but I don't see it like that. I
see it as potentially *good* style, depending on how it is used.

I use that a lot in defining modules.

[snip example]
Why? Look up instead.

Most of us read top- down.
I don't see why you want those declarations _after_ the mixin call.
Seems backwards to me.
Those examples are kind of toy examples.

I do prefer that style, though, yes. I prefer the public exports as
close to the top of the file for the last few years, at least.

[...]
Yes. So I think it is best to alleviate what you can.

Sheilding a beginner from observing that something works by describing
that thing that "works" as an error is not only not best, it is
misleading to a beginner.
I assume you mean they would _not_ know that.
Yes, that's what I meant.
[...]
Yes, I was thinking of the catch clause.


Why even worry about mix-ups like this?

What could I possibly worry about here? Naming the catch clause's
identifier `alert`?

[...]
I'm not saying it is encouraging anything. Just that that "error" can
come in handy in some contexts.


I don't follow. My point is that the above code only works for
elements of one window. To work for frames, it would need to figure
the window that contains the target element. For such applications,
the unqualified window references are few and far between (if any).
There are none in My Library.

I get the point about passing window reference around.

Why are you carrying on about elements wrt an example that uses
window.event?
 
D

David Mark

[...]
I get the point about passing window reference around.

Why are you carrying on about elements wrt an example that uses
window.event?

As I explained, it is an example where the "error" in question is
useful. Its wording is confusing, but its presence can be beneficial.
 
G

GTalbot

[snipped]
IE and Opera are flip-flopping on what offsetTop is.

Thank you for bringing this change to my attention. I was unaware of
that change in Opera and in IE.

That finding reinforces what I wrote earlier about offsetTop andoffsetParentbeing really bad legacy features. Developers should avoid.
They are far too unreliable across browsers and versions.

Hello all,

I stumbled on this today and it is worth mentioning:

The offsetTop calculation for elements that are contained as children
of scrolled elements may be reported incorrectly in Windows Internet
Explorer 8

Article ID: 976948 - Last Review: November 2, 2009

"
Cumulative security update for Internet Explorer 974455 (described in
Microsoft security bulletin MS09-054 (http://www.microsoft.com/
technet/security/bulletin/MS09-054.mspx) ) introduced new logic to
calculate the value of the offsetTop property. Under certain
scenarios, the value of the offsetTop property may be calculated
incorrectly.
"

http://support.microsoft.com/kb/976948/

regards, Gérard
--
Internet Explorer 8 bugs: 60 bugs so far
http://www.gtalbot.org/BrowserBugsSection/MSIE8Bugs/
Internet Explorer 7 bugs: 185 bugs so far
http://www.gtalbot.org/BrowserBugsSection/MSIE7Bugs/
Contributions to the CSS 2.1 test suite
http://www.gtalbot.org/BrowserBugsSection/css21testsuite/
CSS 2.1 Conformance test suite (January 27th 2010)
http://www.w3.org/Style/CSS/Test/CSS2.1/20100127/html4/
comp.lang.javascript FAQ
http://jibbering.com/faq/
 

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,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top