Prev: getElementBy...
Next: Ping
From: Randy Webb on
Hallvard B Furuseth said the following on 2/26/2006 11:25 AM:
> About the FAQ's Q 4.15 again -- Thanks for the answers so far - I
> disappeared just at the time you answered:-)

I had disc replacement surgery on Feb 10 so I can totally relate to what
you are saying :)

> Randy Webb wrote on 15 Feb 2006:
>> Hallvard B Furuseth said the following on 2/10/2006 9:30 AM:
>>> Randy Webb writes:
>>>> Hallvard B Furuseth said the following on 2/9/2006 1:28 PM:
>>>>> (..snip..)
>>>>> Also, why does the "Alternative DynWrite function" at
>>>>> <http://www.jibbering.com/faq/faq_notes/alt_dynwrite.html> need
>>>>> such a lot of tests to find out if innerHTML assignment actually
>>>>> works, instead of just inserting <span id="strange name"></span>
>>>>> and checking if the document now contains an element with that ID?
>>>> Because simply checking for that ID doesn't ensure that the element
>>>> was actually added to the page.
>>> I don't understand. Will some browsers parse the HTML, insert the ID
>>> somewhere in the DOM, but not insert the HTML?
>> document.myDiv.chicken = "This is document.myDiv.chicken";
>> alert(document.myDiv.chicken);
>>
>> What you have to check is that the innerHTML property actually got
>> changed instead of just adding a new property to something.
>
> I didn't understand the point of that code until I read the thread you
> referred to (below), but your chicken example at the end of the thread
> is about a test like
>
> tempVar = element.innerHTML;

If the browser doesn't support innerHTML, you will get an error on that
line. Attempting to set it first and then read it won't cause an error
(if the browser supports setting properties that way).

> element.innerHTML = newHTML;
> return (tempVar == element.innerHTML); // .innerHTML is writeable
>
> which would return true if innerHTML was changed to chicken.

The test in the FAQ Notes is such that it uses "non-normalized" HTML and
reads it back and checks to see if it has been normalized by the browser:

<span id = "someID">Some text</span>

It has that extra spaces in it. If the browser supports changing the
innerHTML then it won't have those extra spaces in the normalized HTML
that it returns from reading innerHTML.

> Well, except I've substituted 'element' for the three
> 'document.getElementById(elem)'s, I don't see why I see so much code
> which keeps doing getElementById() of the same ID over and over again
> instead of doing it once and assigning the result to a variable.
>
> Anyway, I see no reason in the thread you quoted why my function below
> might return true if innerHTML is not supported. Note, my "element" is
> an element fetched with getElementById or whatever, it's not the
> "foobar" element.

I saw that in reading it this time, and not last time. You run into a
possible scenario where your function will fail but the browser may
support innerHTML.

If the browser supports innerHTML but it won't read dynamically inserted
ID's, then it will fail, even if it supported changing the innerHTML of
an element.

>>> function testInnerTML(element) {
>>> if (! document.getElementWithId("foobar")) {
>>> element.innerHTML = '<span id="foobar">xyzzy</span>';
>>> if (document.getElementWithId("foobar"))
>>> return true; // Successfully inserted
>>> }
>>> return false; // Insertion failed
>>> }
>> That won't tell you if it changed the document or not. It could very
>> well just be adding a property instead of changing the DOM of the page.
>
> Only if the browser knows that anything assigned to an .innerHTML
> property should be parsed as HTML, so that it will discover that there
> is a HTML element with ID "foobar" in the string. Why would it know
> and do that if it does not support innerHTML?

It could support innerHTML and not support recognizing the dynamically
added ID. The test for innerHTML support in the FAQ Notes was very well
conceived and written, it took a while to come up with it, along with
some very interesting discussions :)

> Of course it'll return false if a "foobar" element already exists, but
> that's OK for me. Just need to give it a weird name.
>
>> <URL:
>> http://groups.google.com/group/comp.lang.javascript/browse_frm/thread/f382c40cb5019628/03a7b9973850cde4?tvc=1&q=+metallusions#03a7b9973850cde4
>> Is a very lengthy thread that you might find interesting reading. It
>> covers a lot of the problems that lead to the semi-solution in the FAQ
>> and its notes.
>
> Snipping document.all stuff.
>

<g>

--
Randy
comp.lang.javascript FAQ - http://jibbering.com/faq & newsgroup weekly
Javascript Best Practices - http://www.JavascriptToolbox.com/bestpractices/
From: Hallvard B Furuseth on
Back to FAQ's Q 4.15... I seem to be coming and going - for more
pleasant reasons than yous, fortunately:-) Off to holiday in a few
days...

Randy Webb writes:
>Hallvard B Furuseth said the following on 2/26/2006 11:25 AM:
>>(blah blah blah)
>>
>> tempVar = element.innerHTML;
>
> If the browser doesn't support innerHTML, you will get an error on
> that line. Attempting to set it first and then read it won't cause an
> error (if the browser supports setting properties that way).

Hm? Firefox, IE and Opera do not fail on 'tempVar = element.urgle;'.
Will some browsers do so? I hope none fail on 'if (document.all)'...

The "Alternative DynWrite()" page does mention a browser which will err
on attempts to test/read/modify HEAD elements. But it wraps those tests
in "if (typeof element.innerHTML == 'string')", maybe that avoids the
problem. Anyway, in my case I'll just avoid .innerHTML for HEAD
elements. And of input elements. And, and, and...

>> element.innerHTML = newHTML;
>> return (tempVar == element.innerHTML); // .innerHTML is writeable
>> which would return true if innerHTML was changed to chicken.
>
> The test in the FAQ Notes is such that it uses "non-normalized" HTML and
> reads it back and checks to see if it has been normalized by the browser:
>
> <span id = "someID">Some text</span>
>
> It has that extra spaces in it. If the browser supports changing the
> innerHTML then it won't have those extra spaces in the normalized HTML
> that it returns from reading innerHTML.

Yup, that part I get, since it is commented in the DynWrite source:-)
I just didn't use that, my above quotes is about someone else's code.

>> (...)
>> Anyway, I see no reason in the thread you quoted why my function below
>> might return true if innerHTML is not supported. Note, my "element" is
>> an element fetched with getElementById or whatever, it's not the
>> "foobar" element.
>
> I saw that in reading it this time, and not last time. You run into a
> possible scenario where your function will fail but the browser may
> support innerHTML.
>
> If the browser supports innerHTML but it won't read dynamically inserted
> ID's, then it will fail, even if it supported changing the innerHTML of
> an element.

Yuck. Looks like one should be even more careful about innerHTML than I
had yet realized.

Yet the "alternative DynWrite" function also includes such a test, and
will also fail then. So that's not reason to include a test for whether
the HTML code was normalized either.

The reason I can think of is still that some browser might do the
opposite - recognize the dynamically inserted IDs, but not insert the
HTML. Or it could simply be that with innerHTML it's best to be as
paranoid as at all possible.

>>>> function testInnerTML(element) {
if (typeof element.innerHTML == 'string')
>>>> if (! document.getElementWithId("foobar")) {
>>>> element.innerHTML = '<span id="foobar">xyzzy</span>';
>>>> if (document.getElementWithId("foobar"))
>>>> return true; // Successfully inserted
>>>> }
>>>> return false; // Insertion failed
>>>> }
>
> (...) The test for innerHTML support in the FAQ Notes was very well
> conceived and written, it took a while to come up with it, along with
> some very interesting discussions :)

Having read far too many threads about innerHTML I'm realizing even more
detail in there than the source discusses - I just don't understand it,
and would still like to.

It does have a bug: The inner if() needs "else el.innerHTML = inH;".
Otherwise, if .innerHTML is partially supported but DynWrite() does not
realize that, the function will insert <sTrOnG Id='tSt' >test</StRoNg >
in the document and leave it there. E.g. if the browser updates the
HTML but not dynamically inserted IDs, like you said above.
The same applies to my function.

BTW, any special reason to use <strong>? I'd think something less
visible would be better for the test, like <span> or <tt>.

--
Hallvard
From: Thomas 'PointedEars' Lahn on
Hallvard B Furuseth wrote:

> Randy Webb writes:
>> Hallvard B Furuseth said the following on 2/26/2006 11:25 AM:
>>> [...]
>>> tempVar = element.innerHTML;
>>
>> If the browser doesn't support innerHTML, you will get an error on
>> that line. Attempting to set it first and then read it won't cause an
>> error (if the browser supports setting properties that way).

There will only be an error if `element' is a null object reference,
throwing a ReferenceError exception then. So far all known DOM
implementations work according to the [[Get]] property access method
of the ECMAScript specification (although they do not have to).
Therefore, if `innerHTML' is not supported, the reference evaluates
to `undefined', and nothing breaks.

Unconditional _write_ ([[Put]] property) access to the `innerHTML'
property is a different thing, though.

> Hm? Firefox, IE and Opera do not fail on 'tempVar = element.urgle;'.

As expected. (However, Firefox's error console would yield a warning here.)

> Will some browsers do so?

I know of none.

> I hope none fail on 'if (document.all)'...

That depends on how you define `fail'. This breaks in no known user agent
breaks, but not all user agents evaluate `document.all' to `true' here.

> The "Alternative DynWrite()" page does mention a browser which will err
> on attempts to test/read/modify HEAD elements. But it wraps those tests
> in "if (typeof element.innerHTML == 'string')", maybe that avoids the
> problem.

If there is a problem, yes. A `typeof' operation only evaluates the type
of its argument, not its value. So there is no [[Get]] property access
then.

> Anyway, in my case I'll just avoid .innerHTML for HEAD elements.

Good man.

> and of input elements.

Pardon?

> And, and, and...

There are good reasons to use `innerHTML' _occasionally_, though. Splitting
text nodes to insert an element for a word, for example, can be a real PITA
with standards compliant DOM access. I posted an example the other day.

>> If the browser supports innerHTML but it won't read dynamically inserted
>> ID's, then it will fail, even if it supported changing the innerHTML of
>> an element.
>
> Yuck. Looks like one should be even more careful about innerHTML than I
> had yet realized.

Yet I wonder if such a user agent even exists or could exist successfully
in the future. I know of none.

> [...]
> The reason I can think of is still that some browser might do the
> opposite - recognize the dynamically inserted IDs, but not insert the
> HTML.

Improbable. Markup has to be parsed into a tree before the respective
element nodes and text nodes can be inserted. (Which is the main
drawback of using innerHTML & Co. compared to W3C DOM methods.)

> Or it could simply be that with innerHTML it's best to be as
> paranoid as at all possible.

Seldom good things come from paranoia, if that.

> BTW, any special reason to use <strong>?

To mark up <strong>very important</strong> text content. Ref. <em>...</em>.

> I'd think something less visible would be better for the test,
> like <span> or <tt>.

<span style="font-weight:bold">foo</span> cannot tell a screen reader that
"foo" is very important and therefore has to be strongly emphasized. And
`strong' elements are usually rendered bold (as being strongly emphasized
compared to the rest of the text), so you can address both visual and aural
user agents with only one element. (I would define a rule with emphasizing
aural CSS properties for `strong', however a screen reader is likely to
have it in its basic stylesheet already.)

The `tt' (teletype) element is for text content that should be marked up
as being typed by the user, such as commands in a manual or tutorial.
Therefore it is often rendered as teletype or monospaced text. See the
specs.


HTH

PointedEars
From: Hallvard B Furuseth on
Thomas 'PointedEars' Lahn writes:
>Hallvard B Furuseth wrote:
>>Randy Webb writes:
>>>Hallvard B Furuseth said the following on 2/26/2006 11:25 AM:
>>>> [...]
>>>> tempVar = element.innerHTML;
>>>
>>> If the browser doesn't support innerHTML, you will get an error on
>>> that line. Attempting to set it first and then read it won't cause an
>>> error (if the browser supports setting properties that way).
>
> There will only be an error if `element' is a null object reference,
> throwing a ReferenceError exception then. (...)

Ah, good. That's easy enough to test.

> Unconditional _write_ ([[Put]] property) access to the `innerHTML'
> property is a different thing, though.
>
>> Hm? Firefox, IE and Opera do not fail on 'tempVar = element.urgle;'.
>
> As expected. (However, Firefox's error console would yield a warning here.)

Mine doesn't. (Still version 1.0.7.)

> (...)
>
>> The "Alternative DynWrite()" page does mention a browser which will err
>> on attempts to test/read/modify HEAD elements. But it wraps those tests
>> in "if (typeof element.innerHTML == 'string')", maybe that avoids the
>> problem.
>
> If there is a problem, yes. A `typeof' operation only evaluates the type
> of its argument, not its value. So there is no [[Get]] property access
> then.

Yes it does, unless typeof(element.innerHTML) is treated specially.
Types belong to values, not variables. The EcmaScript spec says typeof
UnaryExpression does evaluate UnaryExpression. I just tested that it
did, with typeof some_function(). Maybe you are thinking of C/C++.

>> Anyway, in my case I'll just avoid .innerHTML for HEAD elements.
>
> Good man.
>
>> and of input elements.
>
> Pardon?

Just one of the things some site said innerHTML does not work for, with
some web browser. Might have been about IE4 or something equally
ancient, I don't remember.

> (...)

>>> If the browser supports innerHTML but it won't read dynamically inserted
>>> ID's, then it will fail, even if it supported changing the innerHTML of
>>> an element.
>>
>> Yuck. Looks like one should be even more careful about innerHTML than I
>> had yet realized.
>
> Yet I wonder if such a user agent even exists or could exist successfully
> in the future. I know of none.

That doesn't bother me much anyway. If my page incorrectly decides that
innerHTML doesn't work, it just omits some functionality. It would be
worse if it incorrectly decided innerHTML does works.

>> The reason I can think of is still that some browser might do the
>> opposite - recognize the dynamically inserted IDs, but not insert the
>> HTML.
>
> Improbable. Markup has to be parsed into a tree before the respective
> element nodes and text nodes can be inserted.

Yes, I can't imagine why it would fail that way. I was just speculating
about why the alternative DynWrite() function is written as it is.

> (Which is the main
> drawback of using innerHTML & Co. compared to W3C DOM methods.)

Yup. But I'll want to support non-W3C DOM browser for a while yet.
Tried to write a wrapper which tried either, but that got too much
bother pretty fast.

>> Or it could simply be that with innerHTML it's best to be as
>> paranoid as at all possible.
>
> Seldom good things come from paranoia, if that.
>
>> BTW, any special reason to use <strong>?
>
> To mark up <strong>very important</strong> text content. Ref. <em>...</em>.

Um. perhaps I should have clarified that I was talking abotu the
functionality test in the "alternative DynWrite()" at
<http://www.jibbering.com/faq/faq_notes/alt_dynwrite.html>.

This test isn't very important to the user, only to the JavaScript
programmer. For the user, the testing ought to be smooth and mostly
invisible, not a brief <strong> flash with "I'm testing strange things
here".

>> I'd think something less visible would be better for the test,
>> like <span> or <tt>.
>
> <span style="font-weight:bold">foo</span> cannot tell a screen reader that
> "foo" is very important and therefore has to be strongly emphasized. And
> `strong' elements are usually rendered bold (as being strongly emphasized
> compared to the rest of the text), so you can address both visual and aural
> user agents with only one element. (I would define a rule with emphasizing
> aural CSS properties for `strong', however a screen reader is likely to
> have it in its basic stylesheet already.)
>
> The `tt' (teletype) element is for text content that should be marked up
> as being typed by the user, such as commands in a manual or tutorial.
> Therefore it is often rendered as teletype or monospaced text. See the
> specs.

--
Hallvard
From: Randy Webb on
Hallvard B Furuseth said the following on 3/8/2006 12:57 PM:
> Back to FAQ's Q 4.15... I seem to be coming and going - for more
> pleasant reasons than yous, fortunately:-) Off to holiday in a few
> days...

Add two pulled teeth in the last two days and it gets more fun :) Hope
your holiday was good though.

> Randy Webb writes:
>> Hallvard B Furuseth said the following on 2/26/2006 11:25 AM:
>>> (blah blah blah)
>>>
>>> tempVar = element.innerHTML;
>> If the browser doesn't support innerHTML, you will get an error on
>> that line. Attempting to set it first and then read it won't cause an
>> error (if the browser supports setting properties that way).
>
> Hm? Firefox, IE and Opera do not fail on 'tempVar = element.urgle;'.
> Will some browsers do so? I hope none fail on 'if (document.all)'...

No it doesn't, but alerting tempVar will give you undefined. Not a very
good test. Not sure why I said that though, I don't remember to be honest.

> The "Alternative DynWrite()" page does mention a browser which will err
> on attempts to test/read/modify HEAD elements. But it wraps those tests
> in "if (typeof element.innerHTML == 'string')", maybe that avoids the
> problem. Anyway, in my case I'll just avoid .innerHTML for HEAD
> elements. And of input elements. And, and, and...

I never modify the head via innerHTML so I don't know :) And I don't
create forms with innerHTML either.

>>> element.innerHTML = newHTML;
>>> return (tempVar == element.innerHTML); // .innerHTML is writeable
>>> which would return true if innerHTML was changed to chicken.
>> The test in the FAQ Notes is such that it uses "non-normalized" HTML and
>> reads it back and checks to see if it has been normalized by the browser:
>>
>> <span id = "someID">Some text</span>
>>
>> It has that extra spaces in it. If the browser supports changing the
>> innerHTML then it won't have those extra spaces in the normalized HTML
>> that it returns from reading innerHTML.
>
> Yup, that part I get, since it is commented in the DynWrite source:-)
> I just didn't use that, my above quotes is about someone else's code.

Gotcha.

>>> (...)
>>> Anyway, I see no reason in the thread you quoted why my function below
>>> might return true if innerHTML is not supported. Note, my "element" is
>>> an element fetched with getElementById or whatever, it's not the
>>> "foobar" element.
>> I saw that in reading it this time, and not last time. You run into a
>> possible scenario where your function will fail but the browser may
>> support innerHTML.
>>
>> If the browser supports innerHTML but it won't read dynamically inserted
>> ID's, then it will fail, even if it supported changing the innerHTML of
>> an element.
>
> Yuck. Looks like one should be even more careful about innerHTML than I
> had yet realized.

innerHTML is expensive in terms of memory also when compared to DOM
methods, some even in IE.

> Yet the "alternative DynWrite" function also includes such a test, and
> will also fail then. So that's not reason to include a test for whether
> the HTML code was normalized either.



> The reason I can think of is still that some browser might do the
> opposite - recognize the dynamically inserted IDs, but not insert the
> HTML. Or it could simply be that with innerHTML it's best to be as
> paranoid as at all possible.

If it recognized dynamically created/inserted ID's but not innerHTML it
would totally shock me. But, it could happen.

>>>>> function testInnerTML(element) {
> if (typeof element.innerHTML == 'string')
>>>>> if (! document.getElementWithId("foobar")) {
>>>>> element.innerHTML = '<span id="foobar">xyzzy</span>';
>>>>> if (document.getElementWithId("foobar"))
>>>>> return true; // Successfully inserted
>>>>> }
>>>>> return false; // Insertion failed
>>>>> }
>> (...) The test for innerHTML support in the FAQ Notes was very well
>> conceived and written, it took a while to come up with it, along with
>> some very interesting discussions :)
>
> Having read far too many threads about innerHTML I'm realizing even more
> detail in there than the source discusses - I just don't understand it,
> and would still like to.

What parts? (You are trying to make me read all those notes aren't you! :)

> It does have a bug: The inner if() needs "else el.innerHTML = inH;".
> Otherwise, if .innerHTML is partially supported but DynWrite() does not
> realize that, the function will insert <sTrOnG Id='tSt' >test</StRoNg >
> in the document and leave it there. E.g. if the browser updates the
> HTML but not dynamically inserted IDs, like you said above.
> The same applies to my function.

If I were putting a test in DynWrite, or any other function to test
innerHTML, the element I attempted to insert it in would be hidden via
CSS so that the user wouldn't see it.

> BTW, any special reason to use <strong>? I'd think something less
> visible would be better for the test, like <span> or <tt>.

Any reason for Strong versus span? Not that I am aware of. The entire
purpose of that test is to see if the browser normalized it or not, not
necessarily the code it normalized but the normalizing itself.

--
Randy
comp.lang.javascript FAQ - http://jibbering.com/faq & newsgroup weekly
Javascript Best Practices - http://www.JavascriptToolbox.com/bestpractices/
First  |  Prev  | 
Pages: 1 2
Prev: getElementBy...
Next: Ping