Dynamic select lists using optgroups again - without frameworks

Discussion in 'Javascript' started by Pascal Ehlert, Jan 19, 2008.

  1. 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
     
    Pascal Ehlert, Jan 19, 2008
    #1
    1. Advertisements

  2. 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
     
    Pascal Ehlert, Jan 19, 2008
    #2
    1. Advertisements

  3. 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
     
    Pascal Ehlert, Jan 19, 2008
    #3
  4. 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
     
    Thomas 'PointedEars' Lahn, Jan 19, 2008
    #4
  5. Which one of the numerous versions of Microsoft Internet Explorer are you
    referring to? (javascript:navigator.userAgent; menu "?", "About")
    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.
    Use spaces (2 or 4) for indentation, not tabs.
    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
     
    Thomas 'PointedEars' Lahn, Jan 20, 2008
    #5
  6. The variable declaration above may be safely omitted here, because ...
    .... that line would otherwise constitute a redeclaration.


    PointedEars
     
    Thomas 'PointedEars' Lahn, Jan 20, 2008
    #6
  7. 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.
    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
     
    Pascal Ehlert, Jan 20, 2008
    #7
  8. 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 ;-)
     
    The Natural Philosopher, Jan 20, 2008
    #8
  9. 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
     
    Thomas 'PointedEars' Lahn, Jan 20, 2008
    #9
  10. Pascal Ehlert

    RobG Guest

    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.
     
    RobG, Jan 20, 2008
    #10
  11. However, the functionality of this approach is based on mere assumption,
    much in contrast to the intrinsic `onload' event handler attribute.


    PointedEars
     
    Thomas 'PointedEars' Lahn, Jan 20, 2008
    #11
  12. Pascal Ehlert

    RobG Guest

    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.
     
    RobG, Jan 20, 2008
    #12
  13. 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.
    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
     
    Thomas 'PointedEars' Lahn, Jan 20, 2008
    #13
  14. 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
     
    Thomas 'PointedEars' Lahn, Jan 20, 2008
    #14
  15. Pascal Ehlert

    RobG Guest

    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.
    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.
     
    RobG, Jan 21, 2008
    #15
  16. 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, 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
     
    Thomas 'PointedEars' Lahn, Jan 21, 2008
    #16
  17. 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?
    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
     
    Thomas 'PointedEars' Lahn, Jan 21, 2008
    #17
  18. Pascal Ehlert

    RobG Guest

    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.

    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?

    And I suggest that you stop trying to introduce red herrings and take
    your own advice.
     
    RobG, Jan 21, 2008
    #18
  19. 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, 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 ...
    No, you are mistaken. I suggest you get a new logic module.
    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
     
    Thomas 'PointedEars' Lahn, Jan 21, 2008
    #19
  20. I have not imply but said that it is error-prone; I have neither implied nor
    said that it is erroneous.
    You miss the point. The `onload' event handler attribute will never cause
    an error if by any chance it is unsupported.


    PointedEars
     
    Thomas 'PointedEars' Lahn, Jan 21, 2008
    #20
    1. Advertisements

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 (here). After that, you can post your question and our members will help you out.