Dynamically building objects

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • sirsean@gmail.com

    Dynamically building objects

    Hi all. I'm trying to dynamically build menus and objects after my page
    loads. Data is stored in an XML file and is parsed at runtime into
    Javascript objects. At the moment, I'm working on creating menu items
    from these objects. The parsing works fine (using Sarissa), and Firefox
    builds the menu no problem. IE, however, does not. The functionality of
    the menu will be a single onclick event. It seems that Firefox allows
    me to set the onclick event handler for something built dynamically,
    but IE won't.

    Does anyone have any information on this, or a possible alternate
    solution? Thanks.

  • Richard Cornford

    #2
    Re: Dynamically building objects

    sirsean@gmail.c om wrote:[color=blue]
    > Hi all. I'm trying to dynamically build menus and objects
    > after my page loads. Data is stored in an XML file and is
    > parsed at runtime into Javascript objects.[/color]

    That is a bad idea. XML is sub-optimal as a vehicle for transmitting
    data to an ECMAScript enabled client. JSON is much better as the
    ECMAScript interpreter can parse that directly to JS objects.
    [color=blue]
    > At the moment, I'm working on creating menu items from
    > these objects. The parsing works fine (using Sarissa), and
    > Firefox builds the menu no problem. IE, however, does not. The
    > functionality of the menu will be a single onclick event. It
    > seems that Firefox allows me to set the onclick event handler
    > for something built dynamically, but IE won't.[/color]

    IE provides two independent mechanisms for attaching event handlers to
    dynamically created DOM elements.
    [color=blue]
    > Does anyone have any information on this, or a possible alternate
    > solution? Thanks.[/color]

    Stop using the - setAttribute - method to attach event handlers as when
    that works it is just an unspecified side effect. Attach event handlers
    by assigning function references to the event handling properties of the
    DOM elements, or use a branching W3C - addEventListene r -/ IE -
    attachEvent - approach.

    Richard.


    Comment

    • sirsean@gmail.com

      #3
      Re: Dynamically building objects

      Interesting. I hadn't thought of using addEventListene r. However, I
      have now tried it, and am using the "click" event for these menu items,
      but it does not work. It fires off the event immediately (the function
      gets called as the page loads), which it shouldn't do, and then
      clicking on the item does nothing. Is there some trick to using
      addEventListene r? Haven't tried attachEvent yet for IE, and won't until
      I get it working in Firefox first.

      As for XML and JSON, I'm afraid I have to use XML for this particular
      project. It's a contract with another software company, and they want
      to use XML.

      Thanks.

      Comment

      • Matt Kruse

        #4
        Re: Dynamically building objects

        Richard Cornford wrote:[color=blue]
        > That is a bad idea.[/color]

        That is a ridiculously unjustified conclusion.
        [color=blue]
        > XML is sub-optimal as a vehicle for transmitting
        > data to an ECMAScript enabled client.[/color]

        Perhaps if you define sub-optimal by only considering the size of the data
        delivered.

        Other factors which may contribute to picking the "optimal" solution
        include:
        1) Ease of interacting with an existing system
        2) Ease of interacting with other developers/companies
        3) Use of company-approved technologies or components
        4) The requirement to validate the structure of the data using a DTD

        Most developers are probably familiar with XML and the tools used to
        manipulate it.
        Most developers have probably never heard of JSON (non of my co-workers had
        when I suggested it recently).

        Therefore, saving an extra few kb of data transmission by using JSON might
        not be worth it when you consider all the other real-world factors.
        [color=blue]
        > JSON is much better as the
        > ECMAScript interpreter can parse that directly to JS objects.[/color]

        Which may not be the desired functionality, in which case you need to write
        code to parse the objects.

        --
        Matt Kruse



        Comment

        • Richard Cornford

          #5
          Re: Dynamically building objects

          sirsean@gmail.c om wrote:[color=blue]
          > Interesting. I hadn't thought of using addEventListene r.
          > However, I have now tried it, and am using the "click"
          > event for these menu items, but it does not work. It
          > fires off the event immediately (the function gets
          > called as the page loads), which it shouldn't do, and
          > then clicking on the item does nothing. Is there some
          > trick to using addEventListene r?[/color]

          You are using a CallExpression for the assignment where you should be
          using a MemberExpressio n.

          (
          CallExpression production (ECMA 262 3rd edition; section 11.2.3):-

          CallExpression : MemberExpressio n Arguments

          MemberExpressio n production (ECMA 262 3rd edition; section 11.2):-

          MemberExpressio n:
          PrimaryExpressi on
          FunctionExpress ion
          MemberExpressio n [ Expression ]
          MemberExpressio n . Identifier
          new MemberExpressio n Arguments
          )
          [color=blue]
          > Haven't tried attachEvent yet for IE, and won't
          > until I get it working in Firefox first.
          >
          > As for XML and JSON, I'm afraid I have to use XML for this
          > particular project. It's a contract with another software
          > company, and they want to use XML.[/color]

          A pity you couldn't involve anyone with pertinent technical skills in
          the negotiation of the contract. That is a very risky approach to
          contracts because you may find yourself contracted to do the impossible,
          and so unable to deliver.

          Richard.


          Comment

          • sirsean@gmail.com

            #6
            Re: Dynamically building objects

            Well, I've fixed the problem I was just having with addEventListene r
            (that being that I was attempting, foolishly, to test it out using
            "alert" and it wasn't working because I had to write a separate
            function that is called when the event is fired).

            Unfortunately, now the problem I've come across is that when the event
            is fired, it is passed exactly one argument, which is an object (do you
            perchance know what that object is and what's in it?). I need to know
            the id of the menu item that is clicked, so I tried to use this.id in
            the event function. This works fine in Firefox, but in IE, this.id is
            apparently undefined. What is some way to get around that?

            And I've read into JSON a bit, and it doesn't seem that it's perfect
            for every scenario. We get the data out of a database (that we the
            developers know nothing about) in the form of an XML file that is
            validated against a well-formed XML Schema definition. JSON doesn't do
            that, nor can the database in question easily output data in JSON
            format. The parsing is either on the server or the client, and we don't
            get to know anything about the server in this case. So XML it is.

            Thanks,
            SEAN

            Comment

            • Richard Cornford

              #7
              Re: Dynamically building objects

              Matt Kruse wrote:[color=blue]
              > Richard Cornford wrote:[color=green]
              >> That is a bad idea.[/color]
              >
              > That is a ridiculously unjustified conclusion.
              >[color=green]
              >> XML is sub-optimal as a vehicle for transmitting
              >> data to an ECMAScript enabled client.[/color]
              >
              > Perhaps if you define sub-optimal by only considering
              > the size of the data delivered.[/color]

              Who is only considering the size of the download? The processing of that
              XML on the client into a form that can be employed is a significant
              factor. With JSON you are 100% guaranteed to have a native-code
              client-side parser available whenever you are going to be in a position
              to do something with the data.
              [color=blue]
              > Other factors which may contribute to picking the
              > "optimal" solution include:[/color]

              Is this you usual marketing-speak employment of the term 'solution' or
              its normal English meaning? (it is difficult to tell with you)
              [color=blue]
              > 1) Ease of interacting with an existing system
              > 2) Ease of interacting with other developers/companies[/color]

              XML sent to a client has to satisfy same origin policy so the output
              format for the client is not limited by data interchange formats. The
              only exception that I can think of pre-existing web services using SOAP,
              as a reason for preferring XML.
              [color=blue]
              > 3) Use of company-approved technologies or components[/color]

              Only significant if the person doing the approving doesn't have the
              sense to see through the buzzwords and understand why they are choosing
              technologies.
              [color=blue]
              > 4) The requirement to validate the structure of the[/color]
              data using a DTD

              And how often are you going to be doing that on the client? And if you
              were you would be better off validating against a Schema as that avoids
              having yet another client-side parser to interpret the DTD.
              [color=blue]
              > Most developers are probably familiar with XML and the
              > tools used to manipulate it.[/color]

              Such as writing an XSLT to output JSON from it.
              [color=blue]
              > Most developers have probably never heard of JSON
              > (non of my co-workers had when I suggested it recently).[/color]

              Server-side programmers in other languages have no reason to know about
              JSON. That doesn't mean they cannot be persuaded that it is the best
              format for sending date to client-side ECMAScript. If they understand
              XML they are not going to have much trouble understanding comma
              separated name value pairs wrapped in braces.
              [color=blue]
              > Therefore, saving an extra few kb of data transmission
              > by using JSON might not be worth it when you consider
              > all the other real-world factors.[/color]

              You are only considering the size of the download. Once downloaded it is
              still necessary to process the data into a useable form. The tools for
              that with JSON are native to all ECMAScript interpreters, for XML the
              browser may or may not provide some (and if it does they will likely
              differ between browsers) and if it does not you have to download and
              execute an XML parser implemented in client-side code.
              [color=blue][color=green]
              >> JSON is much better as the ECMAScript
              >> interpreter can parse that directly to JS objects.[/color]
              >
              > Which may not be the desired functionality, in which case
              > you need to write code to parse the objects.[/color]

              What are you talking about? If the objects are not already in the
              desired form (and with JSON they can be in exactly the required form,
              which is unlikely to ever be true of an XLM DOM) all you have to do is
              read the pertinent data from the JS objects. That is no worse than
              extracting the data from XML nodes, and potentially much better.

              Richard.


              Comment

              • Richard Cornford

                #8
                Re: Dynamically building objects

                sirsean@gmail.c om wrote:[color=blue]
                > Well, I've fixed the problem I was just having with
                > addEventListene r (that being that I was attempting,
                > foolishly, to test it out using "alert" and it wasn't
                > working because I had to write a separate
                > function that is called when the event is fired).[/color]

                At some point it might occur to you that if you post some code people
                might have some idea of what you are talking about, and you might get
                responses a little more specific to the situation.
                [color=blue]
                > Unfortunately, now the problem I've come across is that
                > when the event is fired, it is passed exactly one argument,
                > which is an object (do you perchance know what that object
                > is and what's in it?).[/color]

                It is the event object.
                [color=blue]
                > I need to know the id of the menu item that is clicked,
                > so I tried to use this.id in the event function.[/color]

                Please don't tell us that you are going to use the ID with
                getElementById to look up a reference to the Element.
                [color=blue]
                > This works fine in Firefox, but in IE,
                > this.id is apparently undefined.[/color]
                <snip>

                In what sense do you mean 'in IE'? IE doesn't support -
                addEventListene r - at all.
                [color=blue]
                > What is some way to get around that?[/color]

                Almost certainly.

                I bet the best solution will be my first suggestion of assigning a
                function reference to the onclick property of the dynamically created
                DOM element. That gives (near [1]) identical behaviour on the two
                browsers you appear to be interested in (and many others) .

                Richard.

                [1] The difference being that Mozilla passes the event object to the
                event handler, while IE makes it available as a global variable.


                Comment

                • sirsean@gmail.com

                  #9
                  Re: Dynamically building objects

                  Maybe you should have read the rest of the thread before you got pissy.
                  The whole issue was that your suggestion of using the DOM onclick
                  property *doesn't work*. So I was looking for alternate ways to do it.

                  Here's some code:
                  ....
                  var a = document.create Element("A");
                  a.setAttribute( "onclick", "alert(1);" );
                  ....

                  That works fine in Mozilla, but not in IE. The function is never
                  called. It was suggested that I try using addEventListene r (attachEvent
                  in IE, look up a few posts, that's what I "meant" by "in IE").

                  That explanation should catch you up. Too bad I had to waste my time
                  explaining that when you could have read it. If you want to tell me the
                  same thing, point me to where on this page it says a viable alternate
                  solution to this problem. Please. Do it. No?

                  Fine, then I'll tell you why I need the ID. It's not to use
                  getElementById to look up a reference, because that not only is
                  completely unnecessary, but also pretty dumb. Part of the ID is a
                  number that I need to extract and use. It's of the form "button_XXX "
                  where XXX is some number. I simply extract the XXX out and have the
                  number I need. "In IE" it doesn't work ("in IE" meaning "using Internet
                  Explorer as my web browser"), because this.id has no value in the
                  function called by addEventListene r/attachEvent. Mozilla handles it
                  fine.

                  And drop the JSON vs XML crap, it's not relevant.

                  Comment

                  • Richard Cornford

                    #10
                    Re: Dynamically building objects

                    sirsean@gmail.c om wrote:[color=blue]
                    > Maybe you should have read the rest of the thread before
                    > you got pissy. The whole issue was that your suggestion
                    > of using the DOM onclick property *doesn't work*.[/color]

                    Yes it does. It is the most widely supported and reliable approach
                    available.
                    [color=blue]
                    > So I was looking for alternate ways
                    > to do it.
                    >
                    > Here's some code:
                    > ...
                    > var a = document.create Element("A");
                    > a.setAttribute( "onclick", "alert(1);" );
                    > ...[/color]
                    <snip>[color=blue]
                    > Too bad I had to waste my time explaining that when
                    > you could have read it. If you want to tell me the
                    > same thing, point me to where on this page[/color]

                    This page?
                    [color=blue]
                    > it says a viable
                    > alternate solution to this problem.[/color]

                    Perhaps you should go back and re-read the thread.
                    [color=blue]
                    > Please. Do it. No?[/color]
                    <snip>

                    Make me. ;-)

                    Richard.


                    Comment

                    • RobG

                      #11
                      Re: Dynamically building objects

                      sirsean@gmail.c om wrote:[color=blue]
                      > Maybe you should have read the rest of the thread before you got pissy.
                      > The whole issue was that your suggestion of using the DOM onclick
                      > property *doesn't work*. So I was looking for alternate ways to do it.
                      >
                      > Here's some code:
                      > ...
                      > var a = document.create Element("A");
                      > a.setAttribute( "onclick", "alert(1);" );
                      > ...[/color]

                      var a = document.create Element("A");
                      a.onclick = function() {alert('1');};
                      ...

                      Will do the trick, or:

                      function sayHi(el) {
                      alert( ( el.id )? el.id : 'I have no ID' );
                      }

                      ...
                      var a = document.create Element('A');
                      a.onclick = function () {sayHi(this)} ;
                      ...

                      or:

                      function sayHi(e) {
                      e = e || window.event;
                      var el = e.target || e.srcElement;
                      alert( ( el.id )? el.id : 'I have no ID' );
                      }

                      ...
                      var a = document.create Element('A');
                      a.onclick = sayHi;
                      ...

                      Please advise which of the above does not work in both IE and any other
                      common UA?


                      [...]


                      --
                      Rob

                      Comment

                      • VK

                        #12
                        Re: Dynamically building objects

                        There was an extensive discussion on the event matter here:
                        <http://groups-beta.google.com/group/comp.lang.javas cript/browse_frm/thread/083ed9630b81dee 9/cd81fab7ffdfadd 7#cd81fab7ffdfa dd7>

                        They tried so hard, to convince me that there was NO problem of event
                        source traking in programmed handlers, so I almost believed it :-)

                        This works on any nesting deep, even with links inside:

                        function addClickListene r(obj) {
                        if (obj.addEventLi stener) {
                        // To avoid multiple bubbles in FF,
                        // we're capturing events on the up->down (capturing) phase,
                        // so the bubbles history doesn't matter to us.
                        // Also we're using function wrapper to pass the object
                        // to the event handler:
                        obj.addEventLis tener('click', function(){myFu nction(obj);}, true);
                        }
                        else if (obj.attachEven t) {
                        // We're using function wrapper to pass the object
                        // to the event handler:
                        obj.attachEvent ('onclick', function(){myFu nction(obj);});
                        }
                        else {
                        // Some under-done wannabe browser, just skip on it ?
                        }
                        }


                        function myFunction(obj) {
                        // Do what you want with obj, this is the right one - 100% guarantee
                        :-)
                        }

                        If you need to handle the event object as well (say, cancel it), you
                        need to update it as follow:

                        obj.addEventLis tener('click', function(e){myF unction(obj, e);}, true);
                        obj.attachEvent ('onclick', function(){myFu nction(obj, null);});

                        function myFunction(obj, evt) {
                        // Do what you want with obj, this is the right one - 100% guarantee
                        :-)
                        // Do what you want with evt event, just remember that in FF
                        // this event is captured at the downfall phase:
                        // 1. You have to use stopPropagation () instead of cancelBubble to
                        cancel the event
                        // 2. If you do so, any underlaying elements like links will never
                        receive the event
                        }

                        Faced quod potui, faciant meliora potentes...

                        Comment

                        • Richard Cornford

                          #13
                          Re: Dynamically building objects

                          RobG wrote:
                          <snip>[color=blue]
                          > function sayHi(e) {
                          > e = e || window.event;
                          > var el = e.target || e.srcElement;
                          > alert( ( el.id )? el.id : 'I have no ID' );
                          > }
                          >
                          > ...
                          > var a = document.create Element('A');
                          > a.onclick = sayHi;
                          > ...[/color]
                          <snip>

                          As functions assigned to event handling properties of DOM elements are
                          executed as methods of those DOM elements there is no need to worry
                          about the event's target in order to get a reference back to the DOM
                          element to which the handler is attached. That reference will always be
                          available as the - this - keyword. Hence preferring this approach over
                          the IE attachEvent method, where the handler is executed in the global
                          context and so special handling is required for IE.

                          Richard.


                          Comment

                          • VK

                            #14
                            Re: Dynamically building objects

                            an updated variant taking into account the newly discovered array
                            referencing bug... sorry... "closure's feature" of both browsers. The
                            event attacher is moved out of the main loop.


                            <html>
                            <title>Test</title>
                            <meta http-equiv="Content-Type" content="text/html;
                            charset=iso-8859-1">

                            <script type="text/javascript">
                            <!--

                            function init() {
                            var arr = document.getEle mentsByTagName( 'DIV');
                            for (i=0; i<arr.length; i++) {
                            addClickListene r(arr[i]);
                            }
                            }

                            function addClickListene r(obj) {
                            if (obj.addEventLi stener) {
                            obj.addEventLis tener('click', function(e){cli ckHandler(obj,e );},
                            true);
                            }
                            else if (obj.attachEven t) {
                            obj.attachEvent ('onclick', function(){clic kHandler(obj,nu ll);});
                            }
                            else {
                            // Some under-done browser.
                            }
                            }

                            function test(e) {
                            alert(this);
                            }

                            function clickHandler(ob j, evt) {
                            var e = (evt!=null)? evt : event;
                            var t = (evt!=null)? e.target : e.srcElement;

                            // if we need to disable underlaying links / form elements:
                            (evt!=null)? e.preventDefaul t() : e.returnValue=f alse;

                            alert('Click captured by '+ obj.id.toUpperC ase() + '\n\n'+
                            'This click originated from ' + t.id.toUpperCas e());
                            }
                            //-->
                            </script>
                            </head>

                            <body bgcolor="#FFFFF F" onload="init()" >
                            <div id="div1">DIV1 <span id="span1">SPAN 1 <a id="a1"
                            href="bogus1.ht m"> A1 </a></span></div>
                            <div id="div2">DIV2 <span id="span2">SPAN 2 <a id="a2"
                            href="bogus2.ht m"> A2 </a></span></div>
                            <div id="div3">DIV3 <span id="span3">SPAN 3 <a id="a3"
                            href="bogus3.ht m"> A3 </a></span></div>
                            </body>
                            </html>

                            Comment

                            • RobG

                              #15
                              Re: Dynamically building objects

                              Richard Cornford wrote:[color=blue]
                              > RobG wrote:
                              > <snip>
                              >[color=green]
                              >> function sayHi(e) {
                              >> e = e || window.event;
                              >> var el = e.target || e.srcElement;
                              >> alert( ( el.id )? el.id : 'I have no ID' );
                              >> }
                              >>
                              >> ...
                              >> var a = document.create Element('A');
                              >> a.onclick = sayHi;
                              >> ...[/color]
                              >
                              > <snip>
                              >
                              > As functions assigned to event handling properties of DOM elements are
                              > executed as methods of those DOM elements there is no need to worry
                              > about the event's target in order to get a reference back to the DOM
                              > element to which the handler is attached. That reference will always be
                              > available as the - this - keyword. Hence preferring this approach over
                              > the IE attachEvent method, where the handler is executed in the global
                              > context and so special handling is required for IE.
                              >[/color]

                              In other words...

                              function sayHi() {
                              alert( ( this.id )? this.id : 'I have no ID' );
                              }

                              ...
                              var a = document.create Element('A');
                              a.onclick = sayHi;
                              ...


                              will suffice. Thanks.


                              --
                              Rob

                              Comment

                              Working...