From: Garrett Smith on
On 2010-07-15 11:00 PM, David Mark wrote:
> 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:
>>
[...]


>
>>
>> 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.
>

Waiting for onload to fire might result in a less desirable U/X. The
consequences might be increased perceived load time, or unresponsiveness
of components, depending on the page, how many images it has, whether or
not there are delegating event handlers and what those handlers do.

[...]

>
>>
>> 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)."
>

An unclosed ancestor, is that what it says?

Is an unclosed parent an unclosed ancestor? Nope.

MSDN never states that appending to an unclosed *parent* triggers
operation aborted. In fact, it indicates that doing does not trigger
operation aborted.

And so from this, it can be concluded that operation aborted can be
simply avoided by doing none other than replacing:

par.appendChild(n);

- with -

par.insertBefore(n, par.firstChild);

The example I posted demonstrates that the theory holds true.

>>
>>>> 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?
>

The explanation should not be difficult to understand.

>>
>>> 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.
>

Any time, under any condition? Ah, no, not any time. The specific
condition was as MS explains it. Aapparently you didn't read it
carefully (or read your own...)

> 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.
>

You are making statements about me that reflect you.

>>
>> 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

The theory was demonstrated by the example. The theory was based on post
hoc observations of the demonstration itself.

I already explained what causes the error to you. Microsoft already did,
too.

This is not a post hoc "it worked" derived principle. The theory that
replacing `par.appendChild(newNode)` with `par.insertBefore(newNode,
par.firstChild)` was based on the analysis of the problem.

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. ;)
>

I see no emprical evidence that using insertBefore as I've proposed
triggers "operation aborted."

Based on the explanation by Microsoft, it shouldn't. My example shows
that it does not and given no reason to believe the contrary, the onus
is on you to show that it does.

The reason for using insertBefore over appendChild is to avoid Operation
Aborted. That is a serious issue for a web page. Avoiding that issue
does not say anyting about other issues that may arise regarding
appending while the document is loading.

>>
>> <!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.
>

What you do is irrelevant.

>>
>> 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. :)
>

That is neither funny nor relevant.

> 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.

Interpreting Microsoft's use of the term "add" to as meaning "uses
appendChild" would not make much sense since they mention innerHTML and
document.write as being causes, would it? The explanation provided by
Microsoft ezplains that Operation aborted happens with an unclosed
ancestor and that it does not happen with an unclosed *parent*.

The Operation aborted dialog is an HTML parser error that is propagated
up to browser UI.

The problem and how to avoid it is explained by Microsoft. If the parser
has parsed up to:

| <body>
| <div> some text <em>blah...

and the script appends to BODY, then the error will occur. The parser is
in a state where it has BODY with an unclosed DIV. Appending a new DIV
to BODY at that point would require the parser to close the subtree at
that point; as:

| <body>
| <div> some text <em>blah...
--> body.appendChild(newDiv);

- would require handling the existing DIV as if it had been closed.

| <body>
| <div>
| </div>
| <div>new div</div>

However, with insertBefore, that situation is avoided.

| <body>
| <div> some text <em>blah...
--> body.insertBefore(body.firstChild, newDiv);

| <body>
| <div>new div</div>
| <div>
--
Garrett
From: David Mark on
On Jul 16, 3:39 am, Garrett Smith <dhtmlkitc...(a)gmail.com> wrote:
> On 2010-07-15 11:00 PM, David Mark wrote:> 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:
>
> [...]
>
>
>
> >> 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.
>
> Waiting for onload to fire might result in a less desirable U/X. The
> consequences might be increased perceived load time, or unresponsiveness
> of components, depending on the page, how many images it has, whether or
> not there are delegating event handlers and what those handlers do.

Of course, when the context demands it, there are sane methods of
running code before the load event fires (as we've been over a million
times). The typical hacks found in JS libraries do not qualify as
such and predictably cause sporadic Operation Aborted errors. In the
case of Dojo, where every document takes ten years to load, they
decided to keep the Operation Aborted errors rather than eliminating
the cause of the problem or using a sane alternative.

>
> [...]
>
>
>
>
>
>
>
> >> 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-operat...
>
> > "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)."
>
> An unclosed ancestor, is that what it says?

Can you read? :) Yes, that's what it says.

>
> Is an unclosed parent an unclosed ancestor? Nope.

Who are you arguing with?

>
> MSDN never states that appending to an unclosed *parent* triggers
> operation aborted. In fact, it indicates that doing does not trigger
> operation aborted.

Again.

>
> And so from this, it can be concluded that operation aborted can be
> simply avoided by doing none other than replacing:
>
> par.appendChild(n);
>
> - with -
>
> par.insertBefore(n, par.firstChild);

None of what you just said makes any sense at all. Whether you use
appendChild or insertBefore does not change the element you are
mutating.

>
> The example I posted demonstrates that the theory holds true.

If all you have to justify a pattern are your observations of success
in a handful of browsers, then you have no justification at all.

>
>
>
> >>>> 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?
>
> The explanation should not be difficult to understand.

I don't need you to explain Operation Aborted. I asserted that I
didn't think you grasped the root of the problem, based on your
proposed workaround. That assertion stands.

>
>
>
> >>> 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.
>
> Any time, under any condition? Ah, no, not any time. The specific
> condition was as MS explains it. Aapparently you didn't read it
> carefully (or read your own...)

What is wrong with you? Again, whether you use appendChild or
insertBefore, you are *adding* to the same element. As the bit I
pasted indicates (and as you should know anyway), there are other
conditions, but they have nothing to do with the appendChild vs.
insertBefore "argument". Perhaps you are just throwing up gorilla
dust at this point?

>
>
>
> > 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.
>
> You are making statements about me that reflect you.

LOL. I'm not the one with the well-known reading comprehension
problem. Your "I know you are but what am I" retort notwithstanding.
I'm the one that you endlessly irritate with your reading
comprehension problem, especially when you bury simple explanations in
tons of unrelated rubbish due to your inability to grasp what has been
said.

>
>
>
> >> 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
>
> The theory was demonstrated by the example. The theory was based on post
> hoc observations of the demonstration itself.
>
> I already explained what causes the error to you. Microsoft already did,
> too.

Do you really believe this BS? As stated, I never asked (or needed)
any explanation about Operation Aborted from you or MS.

>
> This is not a post hoc "it worked" derived principle. The theory that
> replacing `par.appendChild(newNode)` with `par.insertBefore(newNode,
> par.firstChild)` was based on the analysis of the problem.

Nonsense. The "par" element is the same in either case. And if it is
still being parsed...

>
>   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.  ;)
>
> I see no emprical evidence that using insertBefore as I've proposed
> triggers "operation aborted."

Oh God. Show me where it fails?! And on something known to be
sporadic to boot.

>
> Based on the explanation by Microsoft, it shouldn't.

I don't see where you get that, other than your trust that the lack of
insertBefore in their example indicates that it is okay to use.

> My example shows
> that it does not and given no reason to believe the contrary, the onus
> is on you to show that it does.

I'm not the one that is confused. As mentioned, I've never had a
problem as I simply avoid it and therefore have no need to speculate
about it, post test pages, etc.

>
> The reason for using insertBefore over appendChild is to avoid Operation
> Aborted.

But that's just your opinion based on empirical observations. You
have no proof at all. Better to understand the underlying
abstraction. Again, don't mutate the DOM before it is ready, period.

> That is a serious issue for a web page.

Not mine. :)

> Avoiding that issue
> does not say anyting about other issues that may arise regarding
> appending while the document is loading.

If you would just take my advice, you could stop worrying about all of
those issues (as well as the test pages).

>
>
>
> >> <!doctype html>
>
> > Oh God.
>
> ?

Does that look like a standard doctype to you?

>
>
>
>
>
> >> <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.
>
> What you do is irrelevant.

You'd do well to pay attention to what I do. ;)

>
>
>
> >> 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.  :)
>
> That is neither funny nor relevant.

It gave me a laugh when I saw it.

>
> > 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.
>
> Interpreting Microsoft's use of the term "add" to as meaning "uses
> appendChild" would not make much sense since they mention innerHTML and
> document.write as being causes, would it?

That's my line. You seem to think that it excludes "insertBefore".
That doesn't make much sense, does it?

> The explanation provided by
> Microsoft ezplains that Operation aborted happens with an unclosed
> ancestor and that it does not happen with an unclosed *parent*.

You keep repeating the same thing over and over, which is simply a
regurgitation of the bit I pasted from the MSDN site. Odd as it sheds
no light at all on the subject at hand (appendChild vs. insertBefore).

>
> The Operation aborted dialog is an HTML parser error that is propagated
> up to browser UI.

Yes.

>
> The problem and how to avoid it is explained by Microsoft.

A broken record.

> If the parser
> has parsed up to:
>
> | <body>
> |   <div> some text <em>blah...
>
> and the script appends to BODY, then the error will occur.

Yes. The BODY is not closed yet. Get it?

> The parser is
> in a state where it has BODY with an unclosed DIV.

Now I see that you are focusing on scripts that are children of the
body. Of course, that doesn't represent all scripts, nor are they the
norm. For such scripts, the solution is easy: make them the last
element in the body. So whittle down your subset again. If you have
scripts in the body that are not the last element of the body and they
need to add children directly to the body then insertBefore should
help. That's hardly a general rule.

All a waste of time if you ask me. You could simply understand the
general rule that mutating the DOM before it is ready is a bad idea.

And if you must fake DOMContentLoaded for IE, put a SCRIPT at the very
end of the body that then calls functions in other scripts that are
also children of the body. Then you can use appendChild all you like
and not have to wait for the load event.

Now, what if you want to put all of the scripts in the HEAD? For
example, when I tried to explain to the Dojo developers that they
could eliminate their well-known and longstanding Operation Aborted
woes with similar adjustments, one of them asserted that it was "bad"
to put any script in the body and would drive the "progressive
enhancement people" nuts. I don't think I've ever met those people,
but they must have an alternate definition for progressive
enhancement.

You still have to put your "trigger" script (the one that calls your
DOM ready listener) at the very bottom of the body, but use a timeout
if any of the scripts in the head will be mutating the DOM, so as to
let the body finish parsing (just the closing tag is left after the
last script). You should do this because the scripts in the head are
obviously not children of the body, so are not immune to Operation
Aborted. Regardless of whether that is an iron-clad solution or not
(I would recommend the previous one instead where applicable), using
insertBefore in lieu of appendChild wouldn't help any.