From: David Mark on
On Jul 12, 7:33 pm, David Mark <dmark.cins...(a)gmail.com> wrote:
> On Jul 11, 5:00 pm, Garrett Smith <dhtmlkitc...(a)gmail.com> wrote:
>
>
>
>
>
> > On 2010-07-10 11:51 PM, David Mark wrote:
>
> > > On Jul 10, 11:31 pm, David Mark<dmark.cins...(a)gmail.com>  wrote:
> > >> On Jul 7, 8:54 am, Richard Cornford<Rich...(a)litotes.demon.co.uk>
> > >> wrote:
>
> > >>> On Jul 6, 10:38 pm, Garrett Smith wrote:
> > >>> <snip>>  <http://blog.davglass.com/2009/01/browser-sniffing-vs-object-detection/>
>
> > >>>> ... . The latter, Dav Glass' blog, is a classic example of bad
> > >>>> feature tests and used as a straw man for justifying browser
> > >>>> detection.
>
> > >>> <snip>
>
> > >>> That is exactly how it reads to me. This section, for example:-
>
> > >>> | In my opinion, isn’t this the same thing as browser sniffing?
> > >>> | Aren’t you checking something that you know is unique about a
> > >>> | particular browser and leveraging it? Doesn’t that also qualify
> > >>> | as browser sniffing? If you are looking for some flaw in a
> > >>> | browser to determine a course of action, wouldn’t it be easier
> > >>> | to just read the User Agent and work from there? You can
> > >>> | process that info one time and use it everywhere.
>
> > >> Yes, that is thoroughly laughable (like the example by Zakas).  As is
> > >> his comment about IE being "off by 2".
>
> > [...]
>
> > > The punch-line is that the million-dollar question has a two-cent
> > > answer.  From My Library:-
>
> > > if (ce.clientTop) { y -= ce.clientTop; }
> > > if (ce.clientLeft) { x -= ce.clientLeft; }
>
> > > Why subtract the border?
>
> > Can't really say without knowing whose border is being subtracted. Is
> > `ce` the "containing element" or the root element or something entirely
> > different?
>
> > (The identifier "ce" isn't clear)
>
> > Presumably because the coordinates will be
>
> > > used to position an element.  And as the dated MS documentation
> > > indicates, this answer has been valid since 1999 (and unlikely to ever
> > > be invalid).
>
> > > If you can manage to avoid quirks mode and don't mind some degradation
> > > in IE5, then add this:-
>
> > > var ce = document.documentElement;
>
> > > But if writing a GP script, add one more line:-
>
> > > if (!ce.clientWidth) { ce = document.body; }
>
> > > Not very complicated.
>
> > That will fail when there is css width applied to the documentElement
> > and it will fail in browsers where the documentElement has a clientWidth
> > but is not acting as root.
>
> > You can check to see if compatMode exists and if it does, use it. Its
> > missing from versions of webkit, including Safari 3 an below and
> > probably a good number of mobile devices such as NOkias, so to provide a
> > check to see what the root element is, you can use that.
>
> Boy you really made a mess of a clean explanation.  Hard to tell what
> you are claiming to be missing.  I'll assume you mean
> documentElement.clientWidth.  If there really is an agent that
> supports getBoundingClientRect, but not the clientWidth property for
> the HTML element, then use this:-
>
> ce.clientWidth === 0
>
> That's what My Library uses, but I don't think it is strictly
> necessary.  For example, Safari 3 and below do not support
> getBoundingClientRect.  Furthermore, Safari 3 *does* feature
> documentElement.clientWidth.
>
> As to using compatMode, you are simply confusing the issue with other
> tasks where a "root" or "acting root" may come into play due to the
> mistakes that browser developers made when they copied the client*
> properties from MS.  For instance, measuring the viewport:-
>
> http://www.cinsoft.net/viewport.html
>

Also note that the outdated and ineffective compatMode strategy has
been superseded by feature tests. I'll go as far as to say that the
compatMode property can be written right out of the playbook.

We've been over this before, but apparently there is still confusion.
For viewport measurement, using compatMode as a first option and then
falling back to checking the clientWidth of the HTML element has been
proven incorrect. And as I've repeatedly pointed out, the example in
the FAQ, which only checks the clientWidth, is wrong as well (and
really needs to be fixed!)

But the main point is that none of this has anything to do with the
topic at hand. The non-MSHTML browsers do not store the left/top
borders of the viewport in the clientLeft/Top properties of the BODY
element. Granted, doing so wouldn't be any less silly than what they
did to the body's clientWidth/Height in quirks mode.

As an aside, I'm working on a sequel to the above article that factors
in the "viewfinder" found in many recent mobile devices. The browser
developers (as well as PPK) have made a royal mess of that too, but my
initial testing indicates it is mostly workable.
From: Garrett Smith on
On 2010-07-12 04:13 PM, David Mark wrote:
> On Jul 11, 5:11 pm, Garrett Smith<dhtmlkitc...(a)gmail.com> wrote:
>> On 2010-07-11 12:36 PM, David Mark wrote:> On Jul 6, 5:38 pm, Garrett Smith<dhtmlkitc...(a)gmail.com> wrote:
>>>> On 2010-07-06 02:00 PM, khinester wrote:
>>
>>>>> On Jul 6, 10:19 pm, Stefan Weiss<krewech...(a)gmail.com> wrote:
>>>>>> On 06/07/10 21:23, khinester wrote:
>>
>> [...]
>>
>>> var temp = document.createElement("div");
>>> temp.style.cssText = "position:absolute;top:0;left:0";
>>> document.body.appendChild(temp);
>>> arguments.callee.offset = -temp.getBoundingClientRect().top;
>>> document.body.removeChild(temp);
>>> temp = null;
>>
>>> Hmm. Create a DIV, set its style, append, measure, remove and
>>> "destroy" (quotes indicate setting to null is unneeded). I do wish I
>>> had never put that last step in,
>>
>> Setting to null is totally pointless there.
>
> Exactly my point.
>
>>
>> but I didn't realize this pattern
>>
>>> would eventually end up in every script on the planet. Too bad most
>>> of them use it wrong (as is the case here). See also jQuery.
>>
>> Yeah, it got popular,
>
> Of course. Most of the world was still sniffing the UA string when I
> first started posting examples (and apparently ome nut-cases are still
> doing it).
>
>> though appendChild is wrong (operation aborted),
>
> Odd that in ten years I've never seen an Operation Aborted outside of
> test documents demonstrating Operation Aborted. The trick is to avoid
> mutating the DOM before it is ready.

Well they happen.

They happened with jQuery's ready and it caused a lot of problems.

I've had the problem happen in my own code a long time ago and I when I
wrote that position function, I vaguely remembered it and addressed the
issue by using insertBefore.

Basically, you don't want to be doing appending when the document loading.


But where does insertBefore cause a problem? If it does, I want to know
about it.

>
>> insertBefore(node, body.firstChild) is right to avoid operation aborted.
>
> Apparently you haven't grasped the basic problem.


I've grasped the problem, alright.

Using insertBefore
> during parsing is just as wrong as using appendChild.
>

That is not true.

The problem is caused by appending to an element that has a subtree open.

<body>
<div> <!-- don't append to body when parsing here! -->


The problem is explained well enough on IE blog:

<http://blogs.msdn.com/b/ie/archive/2008/04/23/what-happened-to-operation-aborted.aspx>

I've taken the example on IE blog which uses invalid HTML and cleaned it
up to use valid HTML. If you run the example, you'll see an Operation
Aborted error. However, if you comment out the call to appendChild and
uncomment the call to insertBefore, you'll see it works!

<!doctype html>
<html>
<head>
<title>operation appendChild</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<div>
<script type="text/javascript">
var newElem = document.createElement("h1");
newElem.innerHTML = "it works!";
// This one works:
// document.body.insertBefore(newElem, document.body.firstChild);
// This one throws Operation aborted:
document.body.appendChild(newElem);
</script>
</div>
</body>
</html>

The MSDN blog states:

| Note that if I removed the highlighted DIV element, then this problem
| would not occur because the script block's immediate parent would be
| BODY, and the script block's immediate parent is immune to this
| problem.

Read further down "Interoperability observations and feedback request".
That should answer it all.

Funny, they never once mentioned insertBefore, not in that whole entry.
--
Garrett
From: Garrett Smith on
On 2010-07-12 05:38 PM, David Mark wrote:
> On Jul 12, 7:33 pm, David Mark<dmark.cins...(a)gmail.com> wrote:
>> On Jul 11, 5:00 pm, Garrett Smith<dhtmlkitc...(a)gmail.com> wrote:
>>
>>
>>
>>
>>
>>> On 2010-07-10 11:51 PM, David Mark wrote:
>>
>>>> On Jul 10, 11:31 pm, David Mark<dmark.cins...(a)gmail.com> wrote:
>>>>> On Jul 7, 8:54 am, Richard Cornford<Rich...(a)litotes.demon.co.uk>
>>>>> wrote:
>>
>>>>>> On Jul 6, 10:38 pm, Garrett Smith wrote:
>>>>>> <snip>> <http://blog.davglass.com/2009/01/browser-sniffing-vs-object-detection/>
>>
[...]
>> http://www.cinsoft.net/viewport.html
>>
>
The system cannot find the file specified.
[...]
--
Garrett
From: David Mark on
On Jul 13, 1:40 am, Garrett Smith <dhtmlkitc...(a)gmail.com> wrote:
> On 2010-07-12 05:38 PM, David Mark wrote:
>
>
>
> > On Jul 12, 7:33 pm, David Mark<dmark.cins...(a)gmail.com>  wrote:
> >> On Jul 11, 5:00 pm, Garrett Smith<dhtmlkitc...(a)gmail.com>  wrote:
>
> >>> On 2010-07-10 11:51 PM, David Mark wrote:
>
> >>>> On Jul 10, 11:31 pm, David Mark<dmark.cins...(a)gmail.com>    wrote:
> >>>>> On Jul 7, 8:54 am, Richard Cornford<Rich...(a)litotes.demon.co.uk>
> >>>>> wrote:
>
> >>>>>> On Jul 6, 10:38 pm, Garrett Smith wrote:
> >>>>>> <snip>>    <http://blog.davglass.com/2009/01/browser-sniffing-vs-object-detection/>
>
> [...]
> >>http://www.cinsoft.net/viewport.html
>
> The system cannot find the file specified.

Typo.

http://www.cinsoft.net/viewport.asp
From: David Mark on
On Jul 12, 10:00 pm, Garrett Smith <dhtmlkitc...(a)gmail.com> wrote:
> On 2010-07-12 04:13 PM, David Mark wrote:
>
>
>
>
>
> > On Jul 11, 5:11 pm, Garrett Smith<dhtmlkitc...(a)gmail.com>  wrote:
> >> On 2010-07-11 12:36 PM, David Mark wrote:>  On Jul 6, 5:38 pm, Garrett Smith<dhtmlkitc...(a)gmail.com>    wrote:
> >>>> On 2010-07-06 02:00 PM, khinester wrote:
>
> >>>>> On Jul 6, 10:19 pm, Stefan Weiss<krewech...(a)gmail.com>      wrote:
> >>>>>> On 06/07/10 21:23, khinester wrote:
>
> >> [...]
>
> >>> var temp = document.createElement("div");
> >>> temp.style.cssText = "position:absolute;top:0;left:0";
> >>> document.body.appendChild(temp);
> >>> arguments.callee.offset = -temp.getBoundingClientRect().top;
> >>> document.body.removeChild(temp);
> >>> temp = null;
>
> >>> Hmm.  Create a DIV, set its style, append, measure, remove and
> >>> "destroy" (quotes indicate setting to null is unneeded).  I do wish I
> >>> had never put that last step in,
>
> >> Setting to null is totally pointless there.
>
> > Exactly my point.
>
> >> but I didn't realize this pattern
>
> >>> would eventually end up in every script on the planet.  Too bad most
> >>> of them use it wrong (as is the case here).  See also jQuery.
>
> >> Yeah, it got popular,
>
> > Of course.  Most of the world was still sniffing the UA string when I
> > first started posting examples (and apparently ome nut-cases are still
> > doing it).
>
> >> though appendChild is wrong (operation aborted),
>
> > Odd that in ten years I've never seen an Operation Aborted outside of
> > test documents demonstrating Operation Aborted.  The trick is to avoid
> > mutating the DOM before it is ready.
>
> Well they happen.

Not to me. :)

>
> They happened with jQuery's ready and it caused a lot of problems.

What a shock. They were using the ill-advised Dean Edwards hack to
try to simulate DOMContentLoaded. Same thing happened to Dojo for the
exact same reason.

>
> I've had the problem happen in my own code a long time ago and I when I
> wrote that position function, I vaguely remembered it and addressed the
> issue by using insertBefore.

Why didn't you just wait until the document was "ready" (i.e. loaded
if you want cross-browser compatibility) before doing your tests.
Problem solved.

>
> Basically, you don't want to be doing appending when the document loading..

Exactly.

>
> But where does insertBefore cause a problem? If it does, I want to know
> about it.

If Microsoft's explanation can be believed then insertBefore isn't any
better than appendChild.

http://blogs.msdn.com/b/ie/archive/2008/04/23/what-happened-to-operation-aborted.aspx

"What caused the operation aborted error?

The operation aborted dialog in Internet Explorer 7 is triggered by an
HTML parsing exception that occurs when all the following specific
conditions are met:

* The HTML file is being parsed
Script is executing

* The executing script attempts to add, or remove an element from an
unclosed ancestor in the markup tree (not including the script block's
immediate parent element)."

That's been my experience. Certainly I've seen it happen on other
people's sites (as well as the previously mentioned demonstration that
I put together a few years ago). It's definitely a problem, but one
that is easily avoided by refraining from mutating the DOM before the
page has finished loading.

>
>
>
> >> insertBefore(node, body.firstChild) is right to avoid operation aborted.
>
> > Apparently you haven't grasped the basic problem.
>
> I've grasped the problem, alright.
>
> Using insertBefore

Have you?

>
> > during parsing is just as wrong as using appendChild.
>
> That is not true.
>
> The problem is caused by appending to an element that has a subtree open.

Per the MS explanation, "adding or removing" an element.

And what makes you think that using insertBefore does not add an
element? It just puts it in a different place than appendChild. It's
still mutating an "open" element during the parse, which is ill-
advised, period (regardless of the browser in use).

>
> <body>
>    <div> <!-- don't append to body when parsing here! -->
>
> The problem is explained well enough on IE blog:
>
> <http://blogs.msdn.com/b/ie/archive/2008/04/23/what-happened-to-operat...>

But apparently you didn't read it carefully (or read your own
preconceived notions into it). No shock there.

>
> I've taken the example on IE blog which uses invalid HTML and cleaned it
> up to use valid HTML. If you run the example, you'll see an Operation
> Aborted error. However, if you comment out the call to appendChild and
> uncomment the call to insertBefore, you'll see it works!

Seeing it work doesn't cut any ice with me. If the only
rationalization you have for writing a line of code is that it appears
to work (in one installed browser/configuration), you've got nothing.
Certainly such empirical evidence is not proof that an approach is
"right".

In contrast, if you understand the abstraction that mutating the DOM
(any part of it) before the document is fully loaded is a bad idea,
you can avoid all such evidence gathering and know that you will never
encounter such problems. You say show me; I say use your brain. ;)

>
> <!doctype html>

Oh God.

> <html>
> <head>
>    <title>operation appendChild</title>
>    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
> </head>
> <body>
>    <div>
>     <script type="text/javascript">
>      var newElem = document.createElement("h1");
>      newElem.innerHTML = "it works!";
> // This one works:
> //    document.body.insertBefore(newElem, document.body.firstChild);
> // This one throws Operation aborted:
>      document.body.appendChild(newElem);
>     </script>
>    </div>
> </body>
> </html>
>
> The MSDN blog states:
>
> | Note that if I removed the highlighted DIV element, then this problem
> | would not occur because the script block's immediate parent would be
> | BODY, and the script block's immediate parent is immune to this
> | problem.

So? I don't nest scripts in DIV's either.

>
> Read further down "Interoperability observations and feedback request".
> That should answer it all.

I'm not asking.

>
> Funny, they never once mentioned insertBefore, not in that whole entry.

What's funny is I knew you would say that. :)

Funny that Microsoft's documentation is notoriously vague. Just
because they used appendChild in their example doesn't mean that "add"
in their accompanying explanation refers exclusively to the use of
appendChild. I had never read that article prior to today and having
read it am glad that I don't have to rely on Microsoft to explain
anything to me.