Dynamic select lists using optgroups again - without frameworks

P

Pascal Ehlert

Hi group!

After my first post a few days ago and your advice not to use the
Prototype Framework (which indeed was a good idea! ;-)) I rewrote my
script for dynamic select lists.
This is what it looks like now: http://pastie.caboo.se/140953 (I know
it's messy, but I don't see another way)

Let me explain how it works in short.
First it get's all select elements with classes dynamic_select and
parent in one array and the related child elements with classes
dynamic_select and child in another.

Then I loop through them and extract the options into
grouped_options_store and store the index as the rel attribute of the
parent element.

When the value now changes it determines the text of the selected
parent item and looks for an optgroup with that text as a label.
If it can find one it inserts thoses options from grouped_options_store
into the second list.

Unfortunately I'm having the exact same problem as with the old
version, it works fine in Firefox and Safari but when I select a parent
item in the first list the second list just doesn't change.
It displays the unformatted optgroups from the markup.

Here is a live example again:
http://pascal.hacksrus.net/dev/sandbox.html

I hope you can help me out this time!


Many thanks in advance

Pascal
 
P

Pascal Ehlert

Okay, sorry, I assume that was a stupid beginner's mistake.
IE apparently doesn't support addEventListener but has attachEvent.

I fixed the problem that the stuff didn't get loaded like this:
if (window.addEventListener) {
window.addEventListener('load', initDynamicSelects, false);
} else {
window.attachEvent('onload', initDynamicSelects);
}

There are some other problems still, but I hope I can sort them out on my own.



Regards

Pascal
 
P

Pascal Ehlert

Okay, I do have one more question.
How can I determine whether to use e.target or e.srcElement (IE)?

This throws an error in IE (target is 'null' or not an object):

if (e.target) {
target = e.target
} else {
target = e.srcElement;
}


Regards

Pascal
 
T

Thomas 'PointedEars' Lahn

Pascal said:
Okay, sorry, I assume that was a stupid beginner's mistake.
IE apparently doesn't support addEventListener but has attachEvent.

I fixed the problem that the stuff didn't get loaded like this:
if (window.addEventListener) {
window.addEventListener('load', initDynamicSelects, false);
} else {
window.attachEvent('onload', initDynamicSelects);
}

First, from the existence of a property or rather its value being
convertible to boolean `true' does not follow necessarily that the property
is a method that can be called. Nor does it follow necessarily from the
non-existence of a property or its value being convertible to boolean
`false' that another property would be available, let alone be a method. So
your feature test is not sufficient, and it makes your code error-prone.
Search the archives for `isMethod' for further information.

Second, both methods are _not_ equivalent. There are a number of problems
with assuming they were, and with attachEvent() itself, see

http://www.quirksmode.org/blog/archives/2005/08/addevent_consid.html

Therefore, I have recently suggested a (probably not so new) approach to use
the proprietary event handler property (here: onload) in case
addEventListener() is not available, also supporting several event listeners
for an event an object by emulating the built-in event handler's behavior.
(see <and
<the thread titled "How do I add to an onchange event?", or search for
"_addEventListener" and my name). The aforementioned Web resource also
provides links to workarounds for this problem that other people have devised.

Third, `window' refers to a host object that is not formally specified to
implement the EventTarget interface of W3C DOM Level 2 Events. If you would
try to define the listener for the load event with scripting, you would
therefore assign a Function object reference to the `onload' property of the
Window object instead.

And finally, as I said before, "Unobtrusive JavaScript", which is what you
are still following with this, is a misguided approach devised by people who
don't know better. Despite the explanation a paragraph above, you really
don't want to use methods or proprietary properties of equally proprietary
Window objects to define what should happen when the document has been
loaded. Use the fully standards compliant and widely (if not even
universally) supported approach instead:

<body onload="initDynamicSelects()">
...
</body>

You will observe that you also don't need any DOM branching for this. So
not only this is far more more efficient than the former, but also you are
not forced to rely on any specific DOM implementation (and work around the
quirks it might have).


HTH

PointedEars
 
T

Thomas 'PointedEars' Lahn

Pascal said:
How can I determine whether to use e.target or e.srcElement (IE)?

This throws an error in IE

Which one of the numerous versions of Microsoft Internet Explorer are you
referring to? (javascript:navigator.userAgent; menu "?", "About")
(target is 'null' or not an object):

You should use the Microsoft Script Debugger and similar software to debug
scripts in IE. IE's error messages are what you can observe with error
messages in other Microsoft software: (most of the time) technically correct
and utterly useless.
if (e.target) {
target = e.target

Use spaces (2 or 4) for indentation, not tabs.
} else {
target = e.srcElement;
}

The reason is probably that this code is part of the following event listener:

function ...(e)
{
var target;

if (e.target) {
target = e.target
} else {
target = e.srcElement;
}

// ...
}

This approach fails with the MSHTML DOM because the reference to the event
object is not passed as the `e' argument there. Since `e' would have the
value `undefined', you would be trying to access a property of `undefined'.
However, `undefined' has no properties, hence the (wrong) error message.

The above code has to be rewritten as follows:

function ...(e)
{
var target;

if (!e)
{
e = window.event;
}

if (e)
{
if (e.target)
{
target = e.target
}
else
{
target = e.srcElement;
}

// ...
}
}

However, it can be optimized when taking into account how logical operators
(in ECMAScript implementations) work:

function ...(e)
{
var target;

if (!e)
{
/*
* The parentheses here are only for better understanding.
* For some people they are part of good code style.
*/
e = (typeof window != "undefined" && window && window.event);
}

if (e)
{
var target = (e.target || e.srcElement);
if (target)
{
// ...
}

// ...
}
}

Nevertheless, with using intrinsic event handler attributes instead, this
can be simplified greatly if event bubbling is not involved:

<... on...="myHandler(this);">

You would then have the reference to the event target right away as the
first argument of the user-defined myHandler() method. This approach is
universally supported and fully standards compliant.

With event bubbling it is similar:

<... on...="if (typeof event != 'undefined') myHandler(event);">

You would then pass a reference to the Event object as first argument.
While this approach relies on a proprietary feature (a locally available
`event' property), it appears to work in all script-enabled user agents.

You will find either approach (optimized or not) in many examples posted
here. Please do a more thorough research before asking your next question.

http://jibbering.com/faq/


PointedEars
 
T

Thomas 'PointedEars' Lahn

Thomas said:
function ...(e)
{
var target; ^^^^^^^^^^^
if (!e)
{
/*
* The parentheses here are only for better understanding.
* For some people they are part of good code style.
*/
e = (typeof window != "undefined" && window && window.event);
}
[...]

The variable declaration above may be safely omitted here, because ...
if (e)
{
var target = (e.target || e.srcElement);

.... that line would otherwise constitute a redeclaration.


PointedEars
 
P

Pascal Ehlert

Thomas said:
First, from the existence of a property or rather its value being
convertible to boolean `true' does not follow necessarily that the property
is a method that can be called. Nor does it follow necessarily from the
non-existence of a property or its value being convertible to boolean
`false' that another property would be available, let alone be a method. So
your feature test is not sufficient, and it makes your code error-prone.
Search the archives for `isMethod' for further information.

Second, both methods are _not_ equivalent. There are a number of problems
with assuming they were, and with attachEvent() itself, see

http://www.quirksmode.org/blog/archives/2005/08/addevent_consid.html

That is indeed an interesting link and stuff that I definitely haven't
been aware of.
I didn't even know that Internet Explorer keeps all previously
registered events in memory, even when you refresh the page. That
explains a few interesting problems I stumbled upon.

Therefore, I have recently suggested a (probably not so new) approach to use
the proprietary event handler property (here: onload) in case
addEventListener() is not available, also supporting several event listeners
for an event an object by emulating the built-in event handler's behavior.
(see <and
<the thread titled "How do I add to an onchange event?", or search for
"_addEventListener" and my name). The aforementioned Web resource also
provides links to workarounds for this problem that other people have devised.

I think I will find time to look at all these solutions this afternoon,
I'm already very curious to see how you have solved it.

Third, `window' refers to a host object that is not formally specified to
implement the EventTarget interface of W3C DOM Level 2 Events. If you would
try to define the listener for the load event with scripting, you would
therefore assign a Function object reference to the `onload' property of the
Window object instead.

And finally, as I said before, "Unobtrusive JavaScript", which is what you
are still following with this, is a misguided approach devised by people who
don't know better. Despite the explanation a paragraph above, you really
don't want to use methods or proprietary properties of equally proprietary
Window objects to define what should happen when the document has been
loaded. Use the fully standards compliant and widely (if not even
universally) supported approach instead:

<body onload="initDynamicSelects()">
...
</body>

You will observe that you also don't need any DOM branching for this. So
not only this is far more more efficient than the former, but also you are
not forced to rely on any specific DOM implementation (and work around the
quirks it might have).

That's indeed nicer than all those strange dom:ready solutions provided
by numerous frameworks and scripts, but unfortunately I haven't decided
to use "unobstrusive" JavaScript because of idealism, but because I
wanted to add and remove certain behaviour just by loading the files or
not.
This has a lot to do with the underlying code.

However, wouldn't it be a step into the right direction to give body an
id and attach the event listener to that element instead of "window"?


Thank you very much for your verbose answer; I can finally see the
reason for your dislike towards those frameworks we talked about
earlier and also understood that JS shouldn't be treated as a way to
quickly add some eyecandy to your page but wants to be understood.
I promise to give my best to understand it! :)


-- Pascal Ehlert
 
T

The Natural Philosopher

Pascal said:
understood that JS shouldn't be treated as a way to quickly add
some eyecandy to your page but wants to be understood.
I promise to give my best to understand it! :)

I understand also that pencils should not be used to clean your ears of
wax, but when wax and pencils is all you have, it works well enough ;-)
 
T

Thomas 'PointedEars' Lahn

Pascal said:
That's indeed nicer than all those strange dom:ready solutions provided
by numerous frameworks and scripts, but unfortunately I haven't decided
to use "unobstrusive" JavaScript because of idealism, but because I
wanted to add and remove certain behaviour just by loading the files or
not.
This has a lot to do with the underlying code.

However, wouldn't it be a step into the right direction to give body an
id and attach the event listener to that element instead of "window"?

It would, but it would still require a user agent that provides a DOM that
allows you to return a reference to the `body' element object using an ID.
document.body should suffice.

However, what would be the point in trying to separate script code and
markup here? Think about it:

For separation, you need to include one or more `script' elements in the
document, in the correct order.

Without separation, you need to include one ore more `script' elements,
in the correct order, and define an attribute value.

What is the same: 1. You have to modify the markup. 2. The script code will
always operate on a specific document structure.

What is different: Without separation you have to define the attribute
value, too. With separation, you are restricted to a certain subset of DOM
implementations; without separation, you are not or at least not this much.

And now, given these facts, you should be able to make a reasonable design
decision.


PointedEars
 
R

RobG

That is indeed an interesting link and stuff that I definitely haven't
been aware of.
I didn't even know that Internet Explorer keeps all previously
registered events in memory, even when you refresh the page. That
explains a few interesting problems I stumbled upon.


I think I will find time to look at all these solutions this afternoon,
I'm already very curious to see how you have solved it.







That's indeed nicer than all those strange dom:ready solutions provided
by numerous frameworks and scripts, but unfortunately I haven't decided
to use "unobstrusive" JavaScript because of idealism, but because I
wanted to add and remove certain behaviour just by loading the files or
not.

It has been mentioned here a number of times that you can achieve the
same effect as a "dom ready" function by inserting all your scripts
just before the closing </body> tab, then calling your initialising
function at the bottom of the last script element, or as the only code
in the last script element.

The DOM will be ready and you don't need to use window.onload (or
document.body or whatever) or DOM ready and it has the pleasant side
effect of loading the page faster.
 
T

Thomas 'PointedEars' Lahn

RobG said:
It has been mentioned here a number of times that you can achieve the
same effect as a "dom ready" function by inserting all your scripts
just before the closing </body> tab, then calling your initialising
function at the bottom of the last script element, or as the only code
in the last script element.

The DOM will be ready and you don't need to use window.onload (or
document.body or whatever) or DOM ready and it has the pleasant side
effect of loading the page faster.

However, the functionality of this approach is based on mere assumption,
much in contrast to the intrinsic `onload' event handler attribute.


PointedEars
 
R

RobG

However, the functionality of this approach is based on mere assumption,
much in contrast to the intrinsic `onload' event handler attribute.

Using onload is also based on the "mere assumption" that the UA
supports onload. If you feature detect for onload and find it's not
supported, what then?

I imagine that scenarios is about as common as finding that the DOM
isn't ready when the very last element is parsed.
 
T

Thomas 'PointedEars' Lahn

RobG said:
Using onload is also based on the "mere assumption" that the UA
supports onload. If you feature detect for onload and find it's not
supported, what then?

You are confusing the proprietary event handler property, and the
standardized intrinsic event handler attribute as specified in HTML 4.01 and
universally supported long before that. (It is easy and appropriate to say
that because for Web developers there were only two user agents to consider
at the time the feature was introduced, Netscape Navigator and Microsoft
Internet Explorer; in order to keep up with the competition, their features
were readily implemented by other vendors, including the `onload' attribute.
Which eventually led to its inclusion in HTML 4 as being an apparently
universally supported feature that therefore deserved to be standardized.)

I recommended using the latter one.
I imagine that scenarios is about as common as finding that the DOM
isn't ready when the very last element is parsed.

Apples, oranges. There is exactly *nothing* in any public specification
that says that the document tree would be fully accessible with all
specified properties and methods before the `load' event of the document
occurs. Your suggestion is (naturally) merely based on observation in a
subset of user agents, and the jump to the conclusion that therefore it must
be so in all user agents. That, however, is a well-known logical fallacy.
Which is why the code that follows that conclusion deserves to be called
error-prone.


PointedEars
 
T

Thomas 'PointedEars' Lahn

Thomas said:
Apples, oranges. There is exactly *nothing* in any public specification
that says that the document tree would be fully accessible with all
specified properties and methods before the `load' event of the document
occurs. Your suggestion is (naturally) merely based on observation in a
subset of user agents, and the jump to the conclusion that therefore it must
be so in all user agents. That, however, is a well-known logical fallacy.
Which is why the code that follows that conclusion deserves to be called
error-prone.

Besides, it should be noted that when the `script' element code is executed
at the bottom of the `body' element (as its last sibling, but maybe only the
penultimate one [there may be a text node following it]), the very last
element of the document has probably not been parsed yet. Because that
would be the root (`html') element of the document that does not end before
its end tag is parsed (required in HTML 4.01/XHTML 1.0 Strict/XHTML 1.1) or
before EOF is reached (possible in HTML 4.01 Transitional).


PointedEars
 
R

RobG

Gosh Thomas, you love to make it personal, don't you? It does not add
any weight to your argument and tends to make others ignore you,
regardless of the value of your suggestions.


Error-prone suggests that it will cause an error with reasonable
certainty in known cases. You have not provided a single real world
case where it fails, so while it is possible it will cause an error,
you have much to do to prove it is error-prone.

To do that, you will have to show me a browser where simply including
scripts at the bottom of the body element causes an erorr. I did not
suggest that the script should run unconditionally nor that either
feature detection or element availability tests should be discarded.

Therefore even if the DOM isn't available, the script should not
error, although it may not run. That is not an error, nor does it
make the technique error-prone.
Besides, it should be noted that when the `script' element code is executed
at the bottom of the `body' element (as its last sibling, but maybe only the
penultimate one [there may be a text node following it]), the very last
element of the document has probably not been parsed yet. Because that
would be the root (`html') element of the document that does not end before
its end tag is parsed (required in HTML 4.01/XHTML 1.0 Strict/XHTML 1.1) or
before EOF is reached (possible in HTML 4.01 Transitional).

Your point seems to be that because late loading of scripts may fail
in a vanishingly small number of cases, it should be entirely excluded
from consideration. If the OP is concerned about that, an onload
handler can be added along with a variable to detect if the
initialising function has successfully completed - a belt and braces
approach. Or it can simply run anyway, provided its logic
accommodates the fact that it may have already run.

I think don't think it's sensible to always delay all scripting in all
browsers until the load event occurs because some obscure browser
somewhere may not make the DOM available for late loading scripts.
 
T

Thomas 'PointedEars' Lahn

RobG said:
Gosh Thomas, you love to make it personal, don't you? It does not add
any weight to your argument and tends to make others ignore you,
regardless of the value of your suggestions.

I assure you there is nothing against you in my analysis above. Maybe your
reaction is caused by a misunderstanding: What I meant is that it is natural
(as in "of course") for *anyone* to observe something only in a subset of
user agents, because it is simply impossible to test with all user agents,
historic, current and future ones.

Nevertheless, the jump to conclusion was done by you here. If you want to
consider me pointing out that error an attack at you, that is your problem.
It was certainly not meant that way.
Error-prone suggests that it will cause an error with reasonable
certainty in known cases. You have not provided a single real world
case where it fails, so while it is possible it will cause an error,
you have much to do to prove it is error-prone.

No, I am not. This is just another logical fallacy you have fallen victim
to: You are trying to shift the burden of proof.

Since you continue to fail to provide conclusive arguments, it makes no
sense to continue the discussion with you regarding this matter, as that
discussion is not going to lead us anywhere.

I suggest you read http://en.wikipedia.org/wiki/Logical_fallacy pp.
thoroughly to see how and where your argumentation went wrong.


PointedEars
 
T

Thomas 'PointedEars' Lahn

Randy said:
Thomas 'PointedEars' Lahn said the following on 1/20/2008 8:14 PM:

It sure reads that way.

Hence my clarification. Isn't it curious that you readily jump to "help"
everyone, even if the supposed attack was obviously only a misunderstanding,
and you are not even involved in the discussion?
No, Thomas, he didn't. You said an approach was error-prone. Can you
prove that by providing the name of a browser where it fails? If you
can, then your argument holds water. Just because something *might*
happen doesn't mean it *will* happen.

That is correct, and I have not said or implied that would be the case (that
would have been a fallacious argument).

However, you will hopefully agree that the specified and well-documented
feature has a lower probability to fail than the undocumented feature,
especially since the (HTML 4.01) Specification in this case defines only
what was supported long ago before it was written.

And you will hopefully also agree that if the `onload' attribute of the body
element is for some reason not supported, exactly nothing will happen.
While there is a good chance that an error message will be displayed when
the document tree is not ready enough when the code at the end of the body
element is executed, following the assumption that this were the case.


PointedEars
 
R

RobG

I assure you there is nothing against you in my analysis above. Maybe your
reaction is caused by a misunderstanding: What I meant is that it is natural
(as in "of course") for *anyone* to observe something only in a subset of
user agents, because it is simply impossible to test with all user agents,
historic, current and future ones.

Nevertheless, the jump to conclusion was done by you here. If you want to
consider me pointing out that error an attack at you, that is your problem.
It was certainly not meant that way.



No, I am not. This is just another logical fallacy you have fallen victim
to: You are trying to shift the burden of proof.

Since you continue to fail to provide conclusive arguments,

What? You are the one who claimed it was error-prone yet refuse to
provide evidence that it is. Your argument in regard to the
theroetical possibility that the script may not run is sound, but that
isn't *proof* that it will error.

it makes no
sense to continue the discussion with you regarding this matter, as that
discussion is not going to lead us anywhere.

So I'll accept that you have no proof of your assetion. Either that
or you are hoist with your own petard, as elsewhere in this thread you
suggest:

"You would then pass a reference to the Event object as first
argument. While this approach relies on a proprietary feature (a
locally available
`event' property), it appears to work in all script-enabled user
agents."

Surely what is good for the goose is good for the gander?

I suggest you readhttp://en.wikipedia.org/wiki/Logical_fallacypp.
thoroughly to see how and where your argumentation went wrong.

And I suggest that you stop trying to introduce red herrings and take
your own advice.
 
T

Thomas 'PointedEars' Lahn

Randy said:
Thomas 'PointedEars' Lahn said the following on 1/20/2008 8:14 PM:

It sure reads that way.

Hence my clarification. Isn't it curious that you readily jump to "help"
everyone, even if the supposed attack was obviously only a misunderstanding,
and you are not even involved in the discussion?
No, Thomas, he didn't. You said an approach was error-prone. Can you
prove that by providing the name of a browser where it fails?

No, and I don't have to. That it is error-prone follows from the false
conclusion made to support it, and I have already explained why that
conclusion is false. It would appear that you, too, read my articles
far too superficially. One can only guess why ...
If you can, then your argument holds water.

No, you are mistaken. I suggest you get a new logic module.
Just because something *might* happen doesn't mean it *will* happen.

That is correct, and I have not said or implied that would be the case (that
would have been a fallacious argument).

However, you will hopefully agree that the specified and well-documented
feature has a lower probability to fail than the undocumented feature,
especially since in this case the (HTML 4.01) Specification defines only
what was already supported long ago before it was written.

And you will hopefully also agree that if the `onload' attribute of the body
element is for some reason not supported, exactly nothing will happen.
While there is a good chance that an error message will be displayed when
the document tree is not ready enough when the code at the end of the body
element is executed, following the assumption that this were the case.


PointedEars
 
T

Thomas 'PointedEars' Lahn

Randy said:
Thomas 'PointedEars' Lahn said the following on 1/20/2008 8:45 PM:

You haven't implied that code right before the closing body tag wouldn't
be error-prone? Where you said that is only 10-12 lines up.

I have not imply but said that it is error-prone; I have neither implied nor
said that it is erroneous.
With proper feature detection, it won't fail. It may not do what you
want it to do, but it won't throw an error.


And with proper feature detection, code just prior to </body> won't
either. But, in the event that the onload attribute of the body element


With proper feature detection, if you get an error message then
something is wrong with your feature detection. That is a flaw in the
design of the script, not in the placement of it.

You miss the point. The `onload' event handler attribute will never cause
an error if by any chance it is unsupported.


PointedEars
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top