I want to get the top and left values for a div on the screen.
I have been using the code to calculate the top and left values.
var total1 = 0;
var total2 = 0;
while(element){
total1+=element.offsetTop;
total2+=element.offsetLeft;
try{
element=element.offsetParent;
}catch(E){
break;
}
}
For the same DOM TREE this code is giving a performance reading of
30msec in IE8 and 80 to 200msec in IE6. I want to gain a considerable
performance improvement in IE6.
I am open to all ideas.
By the way I also tried
var total1 = 0;
var total2 = 0;
do{
total1+=element.offsetTop;
total2+=element.offsetLeft;
}while(element=element.offsetParent);
after reading a blog entry or two. The performace is similar.
I found that the bulk of the time is always spent in getting property
value rather than parsing the DOM TREE which less constantly from my
logs.(I might be wrong)
Also the code I have put here is on the fly....might have made
mistakes.
Am looking at performance gain. The floor is open to try anything only
constraint is just javascript, jquery, prototype etc are not an
option.
Thanks in advance!! :)
physical screen or upper-left corner of the page (which may be out of
view if the page is scrolled.)?
As Richard Cornford has mentioned here many times, this problem is not
solved in general. If your div has parents that scroll, have table
elements, is a button, etc, then the calculation of the div's upper-
left corner relative to the upper-left corner of the page is complex.
> I have been using the code to calculate the top and left values.
>
> var total1 = 0;
> var total2 = 0;
> while(element){
> total1+=element.offsetTop;
> total2+=element.offsetLeft;
> try{
> element=element.offsetParent;
>
> }catch(E){
> break;
> }
> }
You should not need a try-catch block to calculate the position. Using
feature detection once when this code first runs, or when the page
first loads, should be enough to know how to calculate the offset in
that browser for the remainder of the life of the page.
Also, perhaps someone else can comment on the possible slowness of the
try-catch. I rarely use them.
> For the same DOM TREE this code is giving a performance reading of
> 30msec in IE8 and 80 to 200msec in IE6. I want to gain a considerable
> performance improvement in IE6.
Why is 80 ms considered a performance problem?
> I am open to all ideas.
>
> By the way I also tried
>
> var total1 = 0;
> var total2 = 0;
> do{
> total1+=element.offsetTop;
> total2+=element.offsetLeft;
>
> }while(element=element.offsetParent);
>
> after reading a blog entry or two. The performace is similar.
>
> I found that the bulk of the time is always spent in getting property
> value rather than parsing the DOM TREE which less constantly from my
> logs.(I might be wrong)
"parsing the DOM TREE"? That is done when the page loads, not when
your calculation is occurring.
> Also the code I have put here is on the fly....might have made
> mistakes.
The better the code you post, the more valuable the responses will be.
Peter
> I want to get the top and left values for a div on the screen.
>
> I have been using the code to calculate the top and left values.
>
> var total1 = 0;
> var total2 = 0;
> while(element){
> total1+=element.offsetTop;
> total2+=element.offsetLeft;
> try{
> element=element.offsetParent;
> }catch(E){
Should be `e' as it does not refer to a constructor.
> break;
> }
> }
>
> For the same DOM TREE this code is giving a performance reading of
> 30msec in IE8 and 80 to 200msec in IE6.
That is unsurprising since that try...catch statement does not do anything
useful here as the assignment is not going to fail:
If `element' does not refer to an object, the `while (element)' statement
prevents execution from ever reaching the problematic assignment.
If `element' does refer to an object, and that object does not have an
`offsetParent' property or its `offsetParent' property value is `undefined'
or `null', `element' will be assigned either `undefined' or `null'. Since
that converts to `false', the next iteration is not going to happen and the
case that one would attempt to access the `offsetParent' property of
`undefined' or `null'.
> I want to gain a considerable
> performance improvement in IE6.
>
> I am open to all ideas.
In most cases you do not need to determine the absolute position of an
element in the first place. For example, if you want to move an element by
10 px towards the right margin and by 20 px towards the bottom margin, you
simply increase its current `left' and `top' px-measured style property
values by those distances (while keeping the unit). If you have not set
those properties before, use the element's computed style.
However, if you insist, read this article, among others about this oft-
discussed problem in this newsgroup:
<https://developer.mozilla.org/en/Determining_the_dimensions_of_elements>
> By the way I also tried
>
> var total1 = 0;
> var total2 = 0;
> do{
> total1+=element.offsetTop;
> total2+=element.offsetLeft;
> }while(element=element.offsetParent);
>
> after reading a blog entry or two.
Do not believe into anything written.
> The performace is similar.
It should be more efficient. Are you sure your benchmark is sound?
> I found that the bulk of the time is always spent in getting property
> value rather than parsing the DOM TREE which less constantly from my
> logs.(I might be wrong)
You are. You do not know what "(to) parse" means to begin with.
> Also the code I have put here is on the fly....might have made
> mistakes.
It is hardly readable in the first place.
> Am looking at performance gain. The floor is open to try anything only
> constraint is just javascript, jquery, prototype etc are not an
> option.
jQuery and Prototype are written in "javascript", though. But you are
correct avoiding them because of their bad code quality.
PointedEars
--
realism: HTML 4.01 Strict
evangelism: XHTML 1.0 Strict
madness: XHTML 1.1 as application/xhtml+xml
-- Bjoern Hoehrmann
As Peter Michaux replied to you, your description of the problem for
which you require assistance is not accurate, too general. An URL
would have helped. And maybe, just maybe, you may be wrongly using
offsetLeft and offsetTop to get the left and top values of a div on
the screen. We can't be sure of this without a real webpage, URL.
> I have been using the code to calculate the top and left values.
>
> var total1 = 0;
> var total2 = 0;
> while(element){
> total1+=element.offsetTop;
> total2+=element.offsetLeft;
> try{
> element=element.offsetParent;
>
> }catch(E){
> break;
> }
> }
First, the while statement does not make sense.
You want an element (which is going to execute the controlled block)
that has offsetTop and offsetLeft values to do the controlled block.
Therefore, your while statement should be
while (element.offsetParent) {..controlled block..}
meaning as long as the current element being examined has an non-null
offsetParent...
Second, using a try.. catch does not perfection make sense from a
debugging perspective and from a property detection support. Let's say
the assignment fails because the current element being examined in
that while block does not have an offsetParent: why should it
generates an exception or an error object? Anyway, try.. catch is for
managing exceptions, for debugging purposes. At least, this is what I
would want to do when choosing to add a try...catch. And here, you do
not even try to identify the error message, error line, type of error,
etc.. So why resort to a try..catch block anyway?
Third, your local variable identifiers (total1, total2) are not
recommendable. You should always try to choose identifiers for
variables that are meaningful, intuitive, that helps debugging, code
maintenance, examining in debugging tools, that helps review by others
who may not be accustomed to your internal function logic (or help
review by yourself years later). This helps everyone and can make a
huge difference when the code is very long, complex, with many
intricated functions.
Here's how I did the same function 7 years ago:
var Element = evt.target ;
var CalculatedTotalOffsetLeft = CalculatedTotalOffsetTop = 0 ; while
(Element.offsetParent)
{
CalculatedTotalOffsetLeft += Element.offsetLeft ;
CalculatedTotalOffsetTop += Element.offsetTop ;
Element = Element.offsetParent ;
} ;
OffsetXForNS6 = evt.pageX - CalculatedTotalOffsetLeft ;
OffsetYForNS6 = evt.pageY - CalculatedTotalOffsetTop ;
http://www.gtalbot.org/DHTMLSection/WindowEventsNS6.html#screenLeft#NoteOffsetXY
http://www.gtalbot.org/DHTMLSection/WindowEventsIE6.html#screenLeft#NoteOffsetXY
> For the same DOM TREE this code is giving a performance reading of
> 30msec in IE8 and 80 to 200msec in IE6. I want to gain a considerable
> performance improvement in IE6.
IE6 <sigh .. Why do you need to support IE6?>. Imagine that people
are less and less using that browser and that IE8 implemented an
improved offsetParent, offsetLeft and offsetTop model.
With those numbers, don't you want to tell your IE6 users to upgrade
or to switch? It would solve many many problems...
"30msec in IE8 and 80 to 200msec" does not mean much if we do not know
on which machine (CPU, RAM, video card, etc) these results are
gathered from. 30msec is very long for a super-computer and 200msec is
very fast on a Pentium 1 90Mhz.
If nodeA is an area HTML element which has a map HTML element
somewhere in the ancestor chain, then nodeA.offsetParent returns the
nearest ancestor map HTML element... but that is not the case in IE 7;
IE8 corrected this.
http://www.gtalbot.org/BrowserBugsSection/MSIE8Bugs/CSSOM-offsetParent-prop.html#FourthTest
If an element has no offsetParent, then its offsetLeft value must be 0
and its offsetTop value must be 0 ... but that is not the case in IE6.
http://www.gtalbot.org/BrowserBugsSection/MSIE6Bugs/OffsetValues.html
> I am open to all ideas.
Post an URL. Make sure your webpage is using valid markup code
(including a doctype declaration, preferably declaring a strict DTD),
uses valid CSS code.
http://validator.w3.org/
http://jigsaw.w3.org/css-validator/
Also, read the comp.lang.javascript FAQ on posting code:
http://www.jibbering.com/faq/#posting
> By the way I also tried
>
> var total1 = 0;
> var total2 = 0;
> do{
> total1+=element.offsetTop;
> total2+=element.offsetLeft;
>
> }while(element=element.offsetParent);
An assignment in a while clause is not recommendable, at least,
definitely not my recommendation. Some assignment may succeed and
return 0 (and be resolved as false while the assignment is successful
and correct).
Same thing with assignment in a if clause:
if(a = b)
may succeed but the value may be resolved as false because b == 0.
Some other regular posters may help me here on this precise issue.
> after reading a blog entry or two. The performace is similar.
Why is performance important to you, with regards to offsetTop and
offsetLeft and with regards to IE 6?
Please elaborate.
(There is such a thing has having an overexcessive number of
positioned containers (like nested tables)... in a very bloated
webpage)
> I found that the bulk of the time is always spent in getting property
> value rather than parsing the DOM TREE which less constantly from my
> logs.(I might be wrong)
Post an URL according to the constraints I gave you.
And if you are open to all ideas, then add a IE6nomore or IE6RIP
button in your webpage so that people get the message that IE6 is
buggy, not recommendable, etc. should upgrade or switch.
> Also the code I have put here is on the fly....might have made
> mistakes.
Well, whose fault is it then? Are you asking to get code answers on
the fly as well... with possible mistakes too?
"
The better the code you post, the more valuable the responses will
be.
"
Thank you Peter Michaud for speaking up my mind. :)
Gérard
> For the same DOM TREE this code is giving a performance reading of
> 30msec in IE8 and 80 to 200msec in IE6. I want to gain a considerable
> performance improvement in IE6.
Those "30msec in IE8 and 80 to 200msec in IE6" numbers are entirely
dependent and relative to the depth of the DOM tree of the tested
webpage and to the CPU+RAM of the tested machines. The best possible
(short term and long term) proactive solution for anyone/everyone
involved is still to always use updated web-capable softwares and not
to use very buggy, unreliable, non-trustworthy software like IE6.
> I am open to all ideas.
>
> By the way I also tried
>
> var total1 = 0;
> var total2 = 0;
> do{
> total1+=element.offsetTop;
> total2+=element.offsetLeft;
>
> }while(element=element.offsetParent);
Making an assignment in a while statement is not recommendable;
definitely not my recommendation. The while statement should be a
condition, an expression resulting into a boolean condition (and only
that). The while statement should not be an assignment: you want to
avoid side effects here.
Correct and coherent is:
do
{
total1+=element.offsetTop;
total2+=element.offsetLeft;
element = element.offsetParent;
/* moves upward in the offsetParent containment hierarchy: this
assignment must succeed because the while statement must have been
true */
}
while(element.offsetParent);
/* first test if the current element being actually examined has an
offsetParent before entering the controlled block */
Gérard
Just don't pass orphaned elements. I imagine that's what that
mysterious try-catch was about.
> meaning as long as the current element being examined has an non-null
> offsetParent...
And it better not have typeof "unknown" either. ;)
>
> Second, using a try.. catch does not perfection make sense from a
> debugging perspective and from a property detection support.
Right. It's just hiding some other problem (code passing an orphaned
element).
> Let's say
> the assignment fails because the current element being examined in
> that while block does not have an offsetParent: why should it
> generates an exception or an error object?
It definitely can.
> Anyway, try.. catch is for
> managing exceptions, for debugging purposes. At least, this is what I
> would want to do when choosing to add a try...catch.
Right. There should not be a try-catch here.
> And here, you do
> not even try to identify the error message, error line, type of error,
> etc.. So why resort to a try..catch block anyway?
Exactly. It's just covering up a problem.
>
> Third, your local variable identifiers (total1, total2) are not
> recommendable. You should always try to choose identifiers for
> variables that are meaningful, intuitive, that helps debugging, code
> maintenance, examining in debugging tools, that helps review by others
> who may not be accustomed to your internal function logic (or help
> review by yourself years later). This helps everyone and can make a
> huge difference when the code is very long, complex, with many
> intricated functions.
>
> Here's how I did the same function 7 years ago:
>
> var Element = evt.target ;
> var CalculatedTotalOffsetLeft = CalculatedTotalOffsetTop = 0 ; while
> (Element.offsetParent)
> {
> CalculatedTotalOffsetLeft += Element.offsetLeft ;
> CalculatedTotalOffsetTop += Element.offsetTop ;
> Element = Element.offsetParent ;
>
> } ;
>
> OffsetXForNS6 = evt.pageX - CalculatedTotalOffsetLeft ;
> OffsetYForNS6 = evt.pageY - CalculatedTotalOffsetTop ;
>
> http://www.gtalbot.org/DHTMLSection/WindowEventsNS6.html#screenLeft#N...
>
> http://www.gtalbot.org/DHTMLSection/WindowEventsIE6.html#screenLeft#N...
That doesn't take borders into account. If you _must_ measure all the
way to the document origin (virtually never), use
getBoundingClientRect.
>
> > For the same DOM TREE this code is giving a performance reading of
> > 30msec in IE8 and 80 to 200msec in IE6. I want to gain a considerable
> > performance improvement in IE6.
>
> IE6 <sigh .. Why do you need to support IE6?>.
Because lots of corporate users are stuck with it? And because
there's virtually no difference with IE7. And then there are the
browsers that copied IE6 oddities...
> Imagine that people
> are less and less using that browser and that IE8 implemented an
> improved offsetParent, offsetLeft and offsetTop model.
Yes, less people are using IE6. IE6-8 (and perhaps earlier) all have
getBoundingClientRect (and other browsers have copied). But it is
much simpler and less problematic to measure to the origin of a
positioned ancestor.
>
> With those numbers, don't you want to tell your IE6 users to upgrade
> or to switch? It would solve many many problems...
Because you can't tell users to upgrade their browsers. Some can't
upgrade them. Some don't know what a browser _is_. ;)
>
> "30msec in IE8 and 80 to 200msec" does not mean much if we do not know
> on which machine (CPU, RAM, video card, etc) these results are
> gathered from. 30msec is very long for a super-computer and 200msec is
> very fast on a Pentium 1 90Mhz.
>
> If nodeA is an area HTML element which has a map HTML element
> somewhere in the ancestor chain, then nodeA.offsetParent returns the
> nearest ancestor map HTML element... but that is not the case in IE 7;
> IE8 corrected this.
>
> http://www.gtalbot.org/BrowserBugsSection/MSIE8Bugs/CSSOM-offsetParen...
Skip the image maps and you'll be fine.
[...]
>
> Why is performance important to you, with regards to offsetTop and
> offsetLeft and with regards to IE 6?
> Please elaborate.
>
> (There is such a thing has having an overexcessive number of
> positioned containers (like nested tables)... in a very bloated
> webpage)
Yes. And there is such a thing as making one of them
position:relative. ;)
>
> > I found that the bulk of the time is always spent in getting property
> > value rather than parsing the DOM TREE which less constantly from my
> > logs.(I might be wrong)
>
> Post an URL according to the constraints I gave you.
>
> And if you are open to all ideas, then add a IE6nomore or IE6RIP
> button in your webpage so that people get the message that IE6 is
> buggy, not recommendable, etc. should upgrade or switch.
Hell no. You _never_ insult the user's browser. They may not be able
(or know how) to upgrade.
It's been done. It's just not an advisable cross-browser design to
rely on such complex code when simpler options are available.
I do not understand your "Just don't pass orphaned elements." .. or
I'm not sure I understand what you mean to say.
If the currently tested element has no offsetParent, then the
controlled block is not executed and the execution continues, carries
on, goes out of the while loop. Isn't that what is sought here?
> > Let's say
> > the assignment fails because the current element being examined in
> > that while block does not have an offsetParent: why should it
> > generates an exception or an error object?
>
> It definitely can.
Yes, you're right. If the assignment fails, then there should be an
exception created. I got mixed up with something else.
Sometimes the assignment succeeds but the resulting expression is
evaluated as false.
if(a = b) {... controlled block ...};
if b == 0, then the controlled block may not be executed even though
the assignment was successfully executed. So, it shouldn't be what the
coder expected.
> > var Element = evt.target ;
> > var CalculatedTotalOffsetLeft = CalculatedTotalOffsetTop = 0 ; while
> > (Element.offsetParent)
> > {
> > CalculatedTotalOffsetLeft += Element.offsetLeft ;
> > CalculatedTotalOffsetTop += Element.offsetTop ;
> > Element = Element.offsetParent ;
>
> > } ;
>
> > OffsetXForNS6 = evt.pageX - CalculatedTotalOffsetLeft ;
> > OffsetYForNS6 = evt.pageY - CalculatedTotalOffsetTop ;
> That doesn't take borders into account. If you _must_ measure all the
> way to the document origin (virtually never), use
> getBoundingClientRect.
Borders. This is news to me. I'll have to verify this some day.
> > > For the same DOM TREE this code is giving a performance reading of
> > > 30msec in IE8 and 80 to 200msec in IE6. I want to gain a considerable
> > > performance improvement in IE6.
>
> > IE6 <sigh .. Why do you need to support IE6?>.
>
> Because lots of corporate users are stuck with it? And because
> there's virtually no difference with IE7.
As far as offsetParent, offsetLeft and offsetTop are involved, there
is very little difference between IE6 and IE7: only 1 difference,
IIRC.
There are some/more differences between IE 6 and IE 7 with regards to
positioniseverything.net bugs
Explorer Exposed
http://www.positioniseverything.net/explorer.html
> And then there are the
> browsers that copied IE6 oddities...
>
> > Imagine that people
> > are less and less using that browser and that IE8 implemented an
> > improved offsetParent, offsetLeft and offsetTop model.
>
> Yes, less people are using IE6. IE6-8 (and perhaps earlier) all have
> getBoundingClientRect (and other browsers have copied). But it is
> much simpler and less problematic to measure to the origin of a
> positioned ancestor.
When the ancestor is positioned (non-static), yes. But what happens
when the elements are within a table or within nested tables? I think
you still have to resort to offsetParent.
> > With those numbers, don't you want to tell your IE6 users to upgrade
> > or to switch? It would solve many many problems...
>
> Because you can't tell users to upgrade their browsers.
I try to invite them to upgrade and try to address their intelligence
at all times. Ultimately, it's all up to them to decide. But I don't
hide (or don't try to hide) to them that IE6 is very buggy,
unreliable, not-trustworthy, etc. I certainly want them to know and
understand that web-capable softwares (or any kind of softwares)
should be using the latest stable available version for all kinds of
reasons: security, bug fixes, stability, speed, accessibility and
usability features, etcetctectcc.
> Some can't
> upgrade them.
Often, these people can still/nevertheless install an alternate
browser.
In June 11th 2009 in the US, television signal stopped being for
analog tv; about 15% of users could no longer get local tv. In Canada,
the deadline for getting ready for digital-only tv signal is august
2011. It's roughly the same for other countries regarding the
transition to digital tv.
If you have to buy a new tv because of technological reasons (and FCC
and government rules), then I don't understand why corporate users can
not upgrade their browser softwares. They certainly were warned in the
past that their applications shouldn't be entirely dependent on
Microsoft products and Microsoft Windows platform.
The top 20 IT mistakes to avoid, November 19, 2004
11. Developing Web apps for IE only
http://www.infoworld.com/d/developer-world/top-20-it-mistakes-avoid-314?page=0,3
> Some don't know what a browser _is_. ;)
Those (like seniors) are the most difficult portion of the market.
There's very little you can do ... unless you're a friend of them and
you visit them at home.
[snipped]
> > And if you are open to all ideas, then add a IE6nomore or IE6RIP
> > button in your webpage so that people get the message that IE6 is
> > buggy, not recommendable, etc. should upgrade or switch.
>
> Hell no. You _never_ insult the user's browser. They may not be able
> (or know how) to upgrade.
If your message is not agressive or on purpose bashing the browser
itself, if you invite diplomatically to upgrade or switch and if you
address their intelligence, then those who can may do so. Those who
can not .. whatever the reasons .. will not.
It is objectively still in the user's best interests to always use the
most updated stable release (for countless of reasons) of any software
(s)he may be using.
regards, Gérard
| 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
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).
The CSSOM Views editor had tried to factor in offsetParent's borderWidth
to the equation, and that was implemented for a year or so like that in
Opera (I believe Mac IE had similar behavior). FInally the draft was
changed to match what IE (windows) does. CSSOM Views makes body "magic"
and IE8 changed behavior from IE7 to behave this way.
Recent browsers and IE from version 5 implement
element.getBoundingClientRect.
The method fails miserably on Opera mini by returning Device Pixels
instead of CSS Pixels. Otherwise, it is very fast, simple and easy to use:-
var body = document.body,
box = document.body.getBoundingClientRect();
box.top; // 8
box.left; // 8
// Unreliable.
body.offsetTop;
body.offsetLeft;
Otherwise, if the compatibility with more browsers is needed, consider
solving the problem in a way that allows for your program to function
properly, possibly allowing for addition of borders to the element, but
not measuring offsets of TABLE or BODY.
[snip]
--
Garrett
comp.lang.javascript FAQ: http://jibbering.com/faq/
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.
>
> If the currently tested element has no offsetParent, then the
> controlled block is not executed and the execution continues, carries
> on, goes out of the while loop. Isn't that what is sought here?
See above. Just evaluating it is enough to trigger an exception.
Just search the archive or the Web. You have to include the borders
(clientLeft/Top) in most browsers (it's something that has to be
tested). Some older Opera's were broken in this regard.
>
> > > > For the same DOM TREE this code is giving a performance reading of
> > > > 30msec in IE8 and 80 to 200msec in IE6. I want to gain a considerable
> > > > performance improvement in IE6.
>
> > > IE6 <sigh .. Why do you need to support IE6?>.
>
> > Because lots of corporate users are stuck with it? And because
> > there's virtually no difference with IE7.
>
> As far as offsetParent, offsetLeft and offsetTop are involved, there
> is very little difference between IE6 and IE7: only 1 difference,
> IIRC.
> There are some/more differences between IE 6 and IE 7 with regards to
> positioniseverything.net bugs
There are a few. Most (if not all) are avoidable.
>
> Explorer Exposedhttp://www.positioniseverything.net/explorer.html
>
> > And then there are the
> > browsers that copied IE6 oddities...
>
> > > Imagine that people
> > > are less and less using that browser and that IE8 implemented an
> > > improved offsetParent, offsetLeft and offsetTop model.
>
> > Yes, less people are using IE6. IE6-8 (and perhaps earlier) all have
> > getBoundingClientRect (and other browsers have copied). But it is
> > much simpler and less problematic to measure to the origin of a
> > positioned ancestor.
>
> When the ancestor is positioned (non-static), yes. But what happens
> when the elements are within a table or within nested tables? I think
> you still have to resort to offsetParent.
I didn't mean that you didn't have to use offsetParent at all. I mean
limit the number of "hops" and stop short of the body (unless it has
position:relative).
>
> > > With those numbers, don't you want to tell your IE6 users to upgrade
> > > or to switch? It would solve many many problems...
>
> > Because you can't tell users to upgrade their browsers.
>
> I try to invite them to upgrade and try to address their intelligence
> at all times.
See, the typical user don't want to hear about their intelligence.
Thin ice. :)
> Ultimately, it's all up to them to decide. But I don't
> hide (or don't try to hide) to them that IE6 is very buggy,
> unreliable, not-trustworthy, etc.
That's ridiculous. If your page is buggy and/or unreliable, the user
will (rightfully) blame _you_. No amount of blaming the browser will
move them (as well it should not).
> I certainly want them to know and
> understand that web-capable softwares (or any kind of softwares)
> should be using the latest stable available version for all kinds of
> reasons: security, bug fixes, stability, speed, accessibility and
> usability features, etcetctectcc.
>
> > Some can't
> > upgrade them.
>
> Often, these people can still/nevertheless install an alternate
> browser.
Some can and some can't.
>
> In June 11th 2009 in the US, television signal stopped being for
> analog tv; about 15% of users could no longer get local tv. In Canada,
> the deadline for getting ready for digital-only tv signal is august
> 2011. It's roughly the same for other countries regarding the
> transition to digital tv.
> If you have to buy a new tv because of technological reasons (and FCC
> and government rules), then I don't understand why corporate users can
> not upgrade their browser softwares.
You don't need to understand everything to be successful. ;)
> They certainly were warned in the
> past that their applications shouldn't be entirely dependent on
> Microsoft products and Microsoft Windows platform.
>
> The top 20 IT mistakes to avoid, November 19, 2004
> 11. Developing Web apps for IE onlyhttp://www.infoworld.com/d/developer-world/top-20-it-mistakes-avoid-3...
That's another topic altogether. Some corporate users are simply
stuck with IE6/7 and will be for years. In most cases, it has nothing
to do with building IE-only websites.
>
> > Some don't know what a browser _is_. ;)
>
> Those (like seniors) are the most difficult portion of the market.
Lots of PC-savvy corporate users are clueless about browsers and/or
disallowed from making decisions about which browsers to use.
> There's very little you can do ... unless you're a friend of them and
> you visit them at home.
Sounds like a very hard way to go. They won't let you waltz into
corporate sites changing browsers anyway. I don't think you have time
to visit every "senior" at home either. So tackle the problem from
the other end. ;)
>
> [snipped]
>
> > > And if you are open to all ideas, then add a IE6nomore or IE6RIP
> > > button in your webpage so that people get the message that IE6 is
> > > buggy, not recommendable, etc. should upgrade or switch.
>
> > Hell no. You _never_ insult the user's browser. They may not be able
> > (or know how) to upgrade.
>
> If your message is not agressive or on purpose bashing the browser
> itself, if you invite diplomatically to upgrade or switch and if you
> address their intelligence, then those who can may do so. Those who
> can not .. whatever the reasons .. will not.
Nobody wants to hear about it from your site, unless your site is
about browsers.
>
> It is objectively still in the user's best interests to always use the
> most updated stable release (for countless of reasons) of any software
> (s)he may be using.
See above for various reasons why not.
Right. One more consideration is that IE (JScript, actually) will add
the identifier not to catch-block's scope, but to the function's
variable object.
In an event handler callback, it is common to use - e - for the event
parameter.
When a function with variable - e- reatches a catch block and the catch
block has `e`, then in IE, the function's variable `e` refers to the
Error in IE.
Example:
document.body.onclick = function(e) {
e = e || window.event;
try {
throw new Error("catch scope bugs!");;
} catch(e) { //<-- XXX JScript bug, replaced e's value with error.
} finally {
alert(e.message || "Pass:" + e.type);
}
};
IE elerts: "catch scope bugs!"
The convention I have adopted is to name exception identifier as - ex -
and event as - ev -.
JSLint lets you know about such ambiguities before they bite you.
Error:
Problem at line 5 character 12: 'e' is already defined.
} catch(e) { //<-- XXX JScript bug, replaced e's value with error.
Implied global: window 1,2,7
Also, you've got an "unreachable" semi-colon and a couple of implied
globals (the alert one is troubling).
I've never seen such code and whoever claims "it does everything" is
probably not correct.
> It's just not an advisable cross-browser design to
> rely on such complex code
The implication of that statement is that the code likely doesn't do
everything and so code that does everything doesn't really exist.
> when simpler options are available.
Agreed.
Peter
If we are now off topic, some folks like to write globals in all
capitals. Since that looks like it might be an (implied) global then
captial 'E' may be appropriate.
> > break;
> > }
> > }
>
> > For the same DOM TREE this code is giving a performance reading of
> > 30msec in IE8 and 80 to 200msec in IE6.
>
> That is unsurprising since that try...catch statement does not do anything
> useful here as the assignment is not going to fail:
The assignment will not fail but getting a host object's property may.
> In most cases you do not need to determine the absolute position of an
> element in the first place.
That is absolutely ;-) correct. I think I've only needed absolute
position once in the past couple years.
Peter
I'm not saying the last one I wrote does it all, but it covers most
(if not all) of the issues mentioned.
>
> > It's just not an advisable cross-browser design to
> > rely on such complex code
>
> The implication of that statement is that the code likely doesn't do
> everything and so code that does everything doesn't really exist.
Not exactly. I mean that even if it does work 100%, the code is quite
complex with multiple forks (shouldn't a first choice for a design).
Nevermind. I really don't use try-catch enough.
Peter
The case that Richard Cornford refers to is the case where the code
truly does it all. Even the full "etc" I mentioned.
Peter
[...]
>> The convention I have adopted is to name exception identifier as - ex -
>> and event as - ev -.
>
> JSLint lets you know about such ambiguities before they bite you.
>
JSLint has so much imposition of the author's viewpoint's conveyed as
"errors" that it is hard to find the *real* errors. I would call a real
error someting like assignment to undeclared identifier.
I do not follow Doug's coding conventions. I do take advantage of YUI
warnings, and do pay attention to Firebug's "DOM" tab for globals that
got created.
I would like a lint tool that can find errors or be configured to handle
things like:-
document.addEventListener("click", documentClicked, false);
function documentClicked(ev){ }
JSLint doesn't allow that perfectly valid, easily understandable program
to pass.
> Error:
>
> Problem at line 5 character 12: 'e' is already defined.
>
> } catch(e) { //<-- XXX JScript bug, replaced e's value with error.
>
> Implied global: window 1,2,7
>
JSLint thinks that is an error. Even when "assume a browser" is checked.
> Also, you've got an "unreachable" semi-colon and a couple of implied
> globals (the alert one is troubling).
What is troubling about using alert?
JSLint parses window.alert(); or alert(); as an Error. See I just don't
get that. Now I can't figure out what makes that an error, yet:-
document.parentWindow.alert(1);
- is perfectly fine in JSLint. No error whatsoever. I don't get it.
Nah, default settings yield about a dozen "errors" in My Library (out
of roughly 9,000 lines).
>
> I do not follow Doug's coding conventions. I do take advantage of YUI
> warnings, and do pay attention to Firebug's "DOM" tab for globals that
> got created.
JSLint does far more than that.
>
> I would like a lint tool that can find errors or be configured to handle
> things like:-
>
> document.addEventListener("click", documentClicked, false);
>
> 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.
>
> > Error:
>
> > Problem at line 5 character 12: 'e' is already defined.
>
> > } catch(e) { //<-- XXX JScript bug, replaced e's value with error.
>
> > Implied global: window 1,2,7
>
> JSLint thinks that is an error. Even when "assume a browser" is checked.
Well, I don't care for that one.
>
> > Also, you've got an "unreachable" semi-colon and a couple of implied
> > globals (the alert one is troubling).
>
> What is troubling about using alert?
Nothing troubling about using alert. Now, calling it unqualified in a
- finally - clause is another story.
>
> JSLint parses window.alert(); or alert(); as an Error. See I just don't
> get that.
He wants it to be fully qualified. There are cases where that message
is helpful (e.g. generalizing functions for use with frames).
> Now I can't figure out what makes that an error, yet:-
>
> document.parentWindow.alert(1);
>
> - is perfectly fine in JSLint. No error whatsoever. I don't get it.
That's an implied global for sure. Or perhaps you mean with "assume a
browser"? Yes, I agree that assuming a browser should allow for the
user of window (it used to).
[...]
>> 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.
A beginner might find it *odd* that a function could be referenced
before it appeared in source order. A beginner might not know about
entering an execution context, what a FunctionDeclaration was, what a
FunctionExpression was, but would just notice that "it works".
A beginner would not know a lot of things, including things about
unicode support, ===, typeof, Host object.
>>> Also, you've got an "unreachable" semi-colon and a couple of implied
>>> globals (the alert one is troubling).
>> What is troubling about using alert?
>
> Nothing troubling about using alert. Now, calling it unqualified in a
> - finally - clause is another story.
>
What difference does it make if it is finally clause?
>> JSLint parses window.alert(); or alert(); as an Error. See I just don't
>> get that.
>
> He wants it to be fully qualified. There are cases where that message
> is helpful (e.g. generalizing functions for use with frames).
>
What is it that you think he wants to be fully qualified?
>> Now I can't figure out what makes that an error, yet:-
>>
>> document.parentWindow.alert(1);
>>
>> - is perfectly fine in JSLint. No error whatsoever. I don't get it.
>
> That's an implied global for sure. Or perhaps you mean with "assume a
> browser"? Yes, I agree that assuming a browser should allow for the
> user of window (it used to).
It is odd because document is a property of the window.
You know exactly what I mean.
>
> A beginner might find it *odd* that a function could be referenced
> before it appeared in source order.
Especially if they are coming to JS from another language.
> A beginner might not know about
> entering an execution context, what a FunctionDeclaration was, what a
> FunctionExpression was, but would just notice that "it works".
>
> A beginner would not know a lot of things, including things about
> unicode support, ===, typeof, Host object.
So what?
>
> >>> Also, you've got an "unreachable" semi-colon and a couple of implied
> >>> globals (the alert one is troubling).
> >> What is troubling about using alert?
>
> > Nothing troubling about using alert. Now, calling it unqualified in a
> > - finally - clause is another story.
>
> What difference does it make if it is finally clause?
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.
>
> >> JSLint parses window.alert(); or alert(); as an Error. See I just don't
> >> get that.
>
> > He wants it to be fully qualified. There are cases where that message
> > is helpful (e.g. generalizing functions for use with frames).
>
> What is it that you think he wants to be fully qualified?
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
So that "error" in JSLint helps to spot these situations as well.
>
> >> Now I can't figure out what makes that an error, yet:-
>
> >> document.parentWindow.alert(1);
>
> >> - is perfectly fine in JSLint. No error whatsoever. I don't get it.
>
> > That's an implied global for sure. Or perhaps you mean with "assume a
> > browser"? Yes, I agree that assuming a browser should allow for the
> > user of window (it used to).
>
> It is odd because document is a property of the window.
In a browser (assuming a browser), the Global object has a - document
- property as well. At least, that is the underlying assumption here.
[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.
> > Ultimately, it's all up to them to decide. But I don't
> > hide (or don't try to hide) to them that IE6 is very buggy,
> > unreliable, not-trustworthy, etc.
>
> 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.
> > They certainly were warned in the
> > past that their applications shouldn't be entirely dependent on
> > Microsoft products and Microsoft Windows platform.
>
> > The top 20 IT mistakes to avoid, November 19, 2004
> > 11. Developing Web apps for IE onlyhttp://www.infoworld.com/d/developer-world/top-20-it-mistakes-avoid-3...
>
> 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 .
> > > Some don't know what a browser _is_. ;)
>
> > Those (like seniors) are the most difficult portion of the market.
>
> 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]
> > If your message is not agressive or on purpose bashing the browser
> > itself, if you invite diplomatically to upgrade or switch and if you
> > address their intelligence, then those who can may do so. Those who
> > can not .. whatever the reasons .. will not.
>
> 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
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();
}
})();
>> A beginner might find it *odd* that a function could be referenced
>> before it appeared in source order.
>
> Especially if they are coming to JS from another language.
>
>> A beginner might not know about
>> entering an execution context, what a FunctionDeclaration was, what a
>> FunctionExpression was, but would just notice that "it works".
>>
>> A beginner would not know a lot of things, including things about
>> unicode support, ===, typeof, Host object.
>
> 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.
>>>>> Also, you've got an "unreachable" semi-colon and a couple of implied
>>>>> globals (the alert one is troubling).
>>>> What is troubling about using alert?
>>> Nothing troubling about using alert. Now, calling it unqualified in a
>>> - finally - clause is another story.
>> What difference does it make if it is finally clause?
>
> 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`.
>>>> JSLint parses window.alert(); or alert(); as an Error. See I just don't
>>>> get that.
>>> He wants it to be fully qualified. There are cases where that message
>>> is helpful (e.g. generalizing functions for use with frames).
>> What is it that you think he wants to be fully qualified?
>
> 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.
>>>> Now I can't figure out what makes that an error, yet:-
>>>> document.parentWindow.alert(1);
>>>> - is perfectly fine in JSLint. No error whatsoever. I don't get it.
>>> That's an implied global for sure. Or perhaps you mean with "assume a
>>> browser"? Yes, I agree that assuming a browser should allow for the
>>> user of window (it used to).
>> It is odd because document is a property of the window.
>
> 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.
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?
>
> })();
> >> A beginner might find it *odd* that a function could be referenced
> >> before it appeared in source order.
>
> > Especially if they are coming to JS from another language.
>
> >> A beginner might not know about
> >> entering an execution context, what a FunctionDeclaration was, what a
> >> FunctionExpression was, but would just notice that "it works".
>
> >> A beginner would not know a lot of things, including things about
> >> unicode support, ===, typeof, Host object.
>
> > 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.
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.
>
> >>>>> Also, you've got an "unreachable" semi-colon and a couple of implied
> >>>>> globals (the alert one is troubling).
> >>>> What is troubling about using alert?
> >>> Nothing troubling about using alert. Now, calling it unqualified in a
> >>> - finally - clause is another story.
> >> What difference does it make if it is finally clause?
>
> > 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.
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?
>
> >>>> JSLint parses window.alert(); or alert(); as an Error. See I just don't
> >>>> get that.
> >>> He wants it to be fully qualified. There are cases where that message
> >>> is helpful (e.g. generalizing functions for use with frames).
> >> What is it that you think he wants to be fully qualified?
>
> > 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'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.
>
> >>>> Now I can't figure out what makes that an error, yet:-
> >>>> document.parentWindow.alert(1);
> >>>> - is perfectly fine in JSLint. No error whatsoever. I don't get it.
> >>> That's an implied global for sure. Or perhaps you mean with "assume a
> >>> browser"? Yes, I agree that assuming a browser should allow for the
> >>> user of window (it used to).
> >> It is odd because document is a property of the window.
>
> > 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.
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).
> 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 ...'
--
Lasse Reichstein Holst Nielsen
'Javascript frameworks is a disruptive technology'
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
> David Mark wrote:
>> Garrett Smith wrote:
>>> David Mark wrote:
>>>> Garrett Smith wrote:
>>>>> document.addEventListener("click", documentClicked, false);
>>>>> 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.
To be fair, that is what a lint-like tool is supposed to flag:
,-<http://en.wikipedia.org/wiki/Lint_%28software%29>
|
| 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
--
Prototype.js was written by people who don't know javascript for people
who don't know javascript. People who don't know javascript are not
the best source of advice on designing systems that use javascript.
-- Richard Cornford, cljs, <f806at$ail$1$8300...@news.demon.co.uk>
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
Some versions of Opera have that deviation. If 8 introduced that, I'm
blissfully unaware (feature testing takes care of that for me).
>>>
>>> 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).
>
> 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.
[snip example]
>>
>> 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.
>
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.
[...]
>> 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.
>
> 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.
>> 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.
>
Yes, that's what I meant.
[...]
>>>>> Nothing troubling about using alert. Now, calling it unqualified in a
>>>>> - finally - clause is another story.
>>>> What difference does it make if it is finally clause?
>>> 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.
>
> 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?
>
What could I possibly worry about here? Naming the catch clause's
identifier `alert`?
[...]
>>> 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'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.
>
I get the point about passing window reference around.
Why are you carrying on about elements wrt an example that uses
window.event?
[...]
>
> 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.
Actually, last time time I checked, offsetParent of any element lacking
parentNode would blow up (not necessarily the one orphaned by innerHTML):
In other words, this should be true:
typeof document.createElement('div').offsetParent == 'unknown';
And, interestingly, offsetParent of element that's a child of
parent-less element would just return null. Go figure.
[...]
--
kangax
[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/