onclick behaves differently when defined via javascript

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • yawnmoth

    onclick behaves differently when defined via javascript




    Why, when you click in the black box, do the alert boxes say different
    things? Shouldn't they say the same thing?
  • Jeremy J Starcher

    #2
    Re: onclick behaves differently when defined via javascript

    On Thu, 25 Sep 2008 15:45:50 -0700, yawnmoth wrote:


    >
    Why, when you click in the black box, do the alert boxes say different
    things? Shouldn't they say the same thing?
    Your problem is here:
    <div onclick="test() "</div>

    It is NOT the same as:
    <div onclick=test</div>

    The first form runs the "test()" function within the global context. The
    Global Object does not have a property called tagName.


    The second form (as well as your second example) use a function
    reference, and runs within the context of the div.

    Understanding the environment the script runs in is essential to
    understanding what "this" refers to.

    Comment

    • Henry

      #3
      Re: onclick behaves differently when defined via javascript

      When an intrinsic event attribute is provided for an element (assuming
      it is recognised, etc.), such as:-

      <div onclick="test() "</div>

      - the browser uses the string value (the "text()" in this case) as the
      body text of a function that it creates and assigned to the
      corresponding property of the representation of the element in the
      DOM. So what the browser does here is the equivalent of:-

      divRef.onclick = function(event) {
      test();
      };

      (with or without the - event - formal parameter, depending on the
      browser)

      The difference between the browser doing this and your doing the
      equivalent of:-

      divRef.onclick = test;

      - is that when the browser calls the function it calls the function as
      - divRef.onclick( ); - (with or without an event object as the
      argument, depending on the browser) so the - this - value for the
      execution of the function assigned to - divRef.onclick - is a
      reference to the DIV element, but the function assigned is different.
      One is the function that the browser created (the function that will
      then call - test -) and the other is test itself. In the event that
      the function called is the one created by the browser then when it
      calls - test - it does so in a way that will make the - this - value
      inside that call be a reference to the global object.

      Comment

      • Jorge

        #4
        Re: onclick behaves differently when defined via javascript

        On Sep 26, 12:43 pm, Henry <rcornf...@rain drop.co.ukwrote :
        When an intrinsic event attribute is provided for an element (assuming
        it is recognised, etc.), such as:-
        >
        <div onclick="test() "</div>
        >
        - the browser uses the string value (the "text()" in this case) as the
        body text of a function that it creates and assigned to the
        corresponding property of the representation of the element in the
        DOM. So what the browser does here is the equivalent of:-
        >
        divRef.onclick = function(event) {
            test();
        >
        };
        >
        Correct me if I'm mistaken, but I think I once read somewhere that it
        does an eval() of the text: like (in this case) eval('test()'). .. ?

        --
        Jorge.

        Comment

        • Henry

          #5
          Re: onclick behaves differently when defined via javascript

          On Sep 26, 12:44 pm, Jorge wrote:
          On Sep 26, 12:43 pm, Henry wrote:
          >
          >When an intrinsic event attribute is provided for an element
          >(assuming it is recognised, etc.), such as:-
          >
          ><div onclick="test() "</div>
          >
          >- the browser uses the string value (the "text()" in this case)
          >as the body text of a function that it creates and assigned to
          >the corresponding property of the representation of the element
          >in the DOM. So what the browser does here is the equivalent of:-
          >
          >divRef.oncli ck = function(event) {
          >    test();
          >
          >};
          >
          Correct me if I'm mistaken, but I think I once read somewhere that
          it does an eval() of the text: like (in this case)
          eval('test()'). .. ?
          I cannot tell whether you are mistaken in thinking that you once read
          that somewhere, but it is not the case.

          Comment

          • yawnmoth

            #6
            Re: onclick behaves differently when defined via javascript

            On Sep 25, 6:01 pm, Jeremy J Starcher <r3...@yahoo.co mwrote:
            On Thu, 25 Sep 2008 15:45:50 -0700, yawnmoth wrote:>
            Why, when you click in the black box, do the alert boxes say different
            things?  Shouldn't they say the same thing?
            >
            Your problem is here:
            <div onclick="test() "</div>
            >
            It is NOT the same as:
            <div onclick=test</div>
            >
            The first form runs the "test()" function within the global context.  The
            Global Object does not have a property called tagName.
            >
            The second form (as well as your second example) use a function
            reference, and runs within the context of the div.
            >
            Understanding the environment the script runs in is essential to
            understanding what "this" refers to.
            Why, then, don't any of these work?:





            I can understand the first one. The first one doesn't, presumably,
            work for the same reason that "x=y; y=2;" doesn't result in x equaling
            2 - ie. test hasn't been defined and so onclick is set to undefined.

            But what about the second and third ones? I tried the third one since
            your "It is NOT the same as" didn't include quote marks.

            Comment

            • Jorge

              #7
              Re: onclick behaves differently when defined via javascript

              On Sep 26, 1:58 pm, Henry <rcornf...@rain drop.co.ukwrote :
              >
              I cannot tell whether you are mistaken in thinking that you once read
              that somewhere, but it is not the case.
              :-)

              Still, there's something weird here, something that seems to be
              against your theory, see:

              <html>
              <head>
              </head>
              <body onload= "alert((documen t.body.onload === arguments.calle e)+'\r
              \n'+arguments.c allee)">
              </body>
              </html>

              how do you explain this ?

              --
              Jorge.

              Comment

              • Jorge

                #8
                Re: onclick behaves differently when defined via javascript

                On Sep 26, 9:58 pm, Jorge <jo...@jorgecha morro.comwrote:
                >
                Still, there's something weird here, something that seems to be
                against your theory, see:
                >
                <html>
                <head>
                </head>
                <body onload= "alert((documen t.body.onload === arguments.calle e)+'\r
                \n'+arguments.c allee)">
                </body>
                </html>
                >
                how do you explain this ?
                >
                The link: http://jorgechamorro.com/cljs/018/

                --
                Jorge.

                Comment

                • dhtml

                  #9
                  Re: onclick behaves differently when defined via javascript

                  Jorge wrote:
                  On Sep 26, 9:58 pm, Jorge <jo...@jorgecha morro.comwrote:
                  >Still, there's something weird here, something that seems to be
                  >against your theory, see:
                  >>
                  ><html>
                  ><head>
                  ></head>
                  ><body onload= "alert((documen t.body.onload === arguments.calle e)+'\r
                  >\n'+arguments. callee)">
                  ></body>
                  ></html>
                  >>
                  >how do you explain this ?
                  >>
                  >
                  The body tag's onload attribute is really window onload. window has no
                  tag, so, somebody (probably in Netscape) once had the idea to make the
                  body tag the place to put event handlers from window. Now, event
                  handlers for window and body go in the body tag. It is an idea that
                  seems to be quite popular, even to this day.

                  Ian Hickson has stated that there is a benefit to having window event
                  handlers for body attributes and has included at least one new window
                  event handler as a body attribute (hashchange). Ian could not comment on
                  what that benefit was. I still haven't figured it out...

                  The following thread may help explain some more:


                  Your example's title says:
                  <title>
                  onclick behaves differently when defined via javascript
                  </title>

                  But the code has:
                  <body onload= "alert((documen t.body.onload ===
                  ^^^^^^

                  So I think you might got onload mixed up with onclick.

                  if you would change:
                  <body onload= "alert(window.o nload === arguments.calle e)">

                  Op, FF, Saf (and IE, but I cannot test it).
                  'true'

                  Or,
                  <body onclick= "alert(window.o nclick === arguments.calle e)">

                  FF3
                  "true"

                  Because of the reasons mentioned in the whatwg thread. In firefox, the
                  body content handlers all map to window. I don't see this as being
                  invalid behavior, though it's filed as bug in Firefox.

                  Also, as mentioned in the whatwg thread, the event handler is really on
                  the window. You can trigger the event by clicking outside of the body
                  element (give body style="border: 1px solid" to see this in action).

                  We can also do one better and see that in firefox, the scope chain is
                  not augmented by the body element nor document.

                  <body onclick="alert( typeof getElementsByNa me)" style="border: 1px solid">

                  FF3:
                  undefined

                  Others:
                  function (or similar impl dependent string)

                  As we saw in an earlier thread, event handler attributes get an aug'd
                  scope chain, but this doesn't happen when window "wins" the event
                  handler attribute. In Firefox, window "wins" for all mouse events.

                  An event that applies to both body and window, the handler goes to window:
                  <body onfocus="alert( typeof getElementsByNa me)" style="border: 1px
                  solid" tabindex=1>

                  Best to avoid using event handler attributes in body.

                  For other elements, event handler attributes have the augmented scope
                  chain. To be fair and complete, I should also mention that event
                  handlers that reference other identifiers need those identifiers in the
                  document first (to avoid reference errors). This often means that
                  external script tags have to go in the head, which can slow down page
                  load. (Though loading strategy is a bit off-topic here). Regardless,
                  there are other ways of registering callbacks.

                  Garrett
                  The link: http://jorgechamorro.com/cljs/018/
                  >
                  --
                  Jorge.

                  Comment

                  • Henry

                    #10
                    Re: onclick behaves differently when defined via javascript

                    On Sep 26, 8:58 pm, Jorge wrote:
                    On Sep 26, 1:58 pm, Henry wrote:
                    >I cannot tell whether you are mistaken in thinking that you
                    >once read that somewhere, but it is not the case.
                    >
                    :-)
                    >
                    Still, there's something weird here, something that seems to
                    be against your theory, see:
                    >
                    <html>
                    <head>
                    </head>
                    <body onload= "alert((documen t.body.onload === arguments.calle e)+'\r
                    \n'+arguments.c allee)">
                    </body>
                    </html>
                    >
                    how do you explain this ?
                    How do I explain what exactly? If you want something explaining it is
                    generally a good idea to state what that something is, and given the
                    very inconsistent handling of the 'promotion' of BODY element event
                    handlers and scope chain augmentation across browsers it would be a
                    very good idea to state where you are observing whatever it is you
                    want explaining in addition to what it was you observed.

                    Comment

                    • Jorge

                      #11
                      Re: onclick behaves differently when defined via javascript

                      On Sep 29, 8:06 am, dhtml <dhtmlkitc...@g mail.comwrote:
                      Jorge wrote:
                      On Sep 26, 9:58 pm, Jorge <jo...@jorgecha morro.comwrote:
                      Still, there's something weird here, something that seems to be
                      against your theory, see:
                      >
                      <html>
                      <head>
                      </head>
                      <body onload= "alert((documen t.body.onload === arguments.calle e)+'\r
                      \n'+arguments.c allee)">
                      </body>
                      </html>
                      >
                      how do you explain this ?
                      >
                      The body tag's onload attribute is really window onload. window has no
                      tag, so, somebody (probably in Netscape) once had the idea to make the
                      body tag the place to put event handlers from window. Now, event
                      handlers for window and body go in the body tag. It is an idea that
                      seems to be quite popular, even to this day.
                      >
                      Ian Hickson has stated that there is a benefit to having window event
                      handlers for body attributes and has included at least one new window
                      event handler as a body attribute (hashchange). Ian could not comment on
                      what that benefit was. I still haven't figured it out...
                      >
                      The following thread may help explain some more:http://lists.whatwg.org/htdig.cgi/wh...8-September/01...
                      >
                      Your example's title says:
                      <title>
                         onclick behaves differently when defined via javascript
                      </title>
                      >
                      But the code has:
                      <body onload= "alert((documen t.body.onload ===
                             ^^^^^^
                      >
                      So I think you might got onload mixed up with onclick.
                      >
                      if you would change:
                      <body onload= "alert(window.o nload === arguments.calle e)">
                      >
                      Op, FF, Saf (and IE, but I cannot test it).
                      'true'
                      >
                      Or,
                      <body onclick= "alert(window.o nclick === arguments.calle e)">
                      >
                      FF3
                      "true"
                      >
                      Because of the reasons mentioned in the whatwg thread. In firefox, the
                      body content handlers all map to window. I don't see this as being
                      invalid behavior, though it's filed as bug in Firefox.
                      >
                      Also, as mentioned in the whatwg thread, the event handler is really on
                      the window. You can trigger the event by clicking outside of the body
                      element (give body style="border: 1px solid" to see this in action).
                      >
                      We can also do one better and see that in firefox, the scope chain is
                      not augmented by the body element nor document.
                      >
                      <body onclick="alert( typeof getElementsByNa me)" style="border: 1px solid">
                      >
                      FF3:
                      undefined
                      >
                      Others:
                      function (or similar impl dependent string)
                      >
                      As we saw in an earlier thread, event handler attributes get an aug'd
                      scope chain, but this doesn't happen when window "wins" the event
                      handler attribute. In Firefox, window "wins" for all mouse events.
                      >
                      An event that applies to both body and window, the handler goes to window:
                      <body onfocus="alert( typeof getElementsByNa me)" style="border: 1px
                      solid" tabindex=1>
                      >
                      Best to avoid using event handler attributes in body.
                      >
                      For other elements, event handler attributes have the augmented scope
                      chain. To be fair and complete, I should also mention that event
                      handlers that reference other identifiers need those identifiers in the
                      document first (to avoid reference errors). This often means that
                      external script tags have to go in the head, which can slow down page
                      load. (Though loading strategy is a bit off-topic here). Regardless,
                      there are other ways of registering callbacks.
                      >
                      Garrett
                      >
                      Thanks. Wonderful explanation.
                      I have updated the link, now it can be seen 'this', 'event.target',
                      and where the method has been attached : it certainly a mess, every
                      browser does it in a different way.



                      --
                      Jorge.

                      Comment

                      • Jorge

                        #12
                        Re: onclick behaves differently when defined via javascript

                        On Sep 29, 11:47 am, Henry <rcornf...@rain drop.co.ukwrote :
                        How do I explain what exactly? If you want something explaining it is
                        generally a good idea to state what that something is, and given the
                        very inconsistent handling of the 'promotion' of BODY element event
                        handlers and scope chain augmentation across browsers it would be a
                        very good idea to state where you are observing whatever it is you
                        want explaining in addition to what it was you observed.
                        Garret got it perfectly. Never mind. Thanks anyway.

                        --
                        Jorge.

                        Comment

                        • slebetman

                          #13
                          Re: onclick behaves differently when defined via javascript

                          On Sep 26, 7:44 pm, Jorge <jo...@jorgecha morro.comwrote:
                          On Sep 26, 12:43 pm, Henry <rcornf...@rain drop.co.ukwrote :
                          >
                          When an intrinsic event attribute is provided for an element (assuming
                          it is recognised, etc.), such as:-
                          >
                          <div onclick="test() "</div>
                          >
                          - the browser uses the string value (the "text()" in this case) as the
                          body text of a function that it creates and assigned to the
                          corresponding property of the representation of the element in the
                          DOM. So what the browser does here is the equivalent of:-
                          >
                          divRef.onclick = function(event) {
                              test();
                          >
                          };
                          >
                          Correct me if I'm mistaken, but I think I once read somewhere that it
                          does an eval() of the text: like (in this case) eval('test()'). .. ?

                          Event assignment API is drastically different between javascript and
                          HTML. In HTML it does indeed do an eval of the string text supplied as
                          the event handler, because the event handler is supplied as a string:

                          <div onclick="alert( 'hello')"></div>

                          BUT, (assuming you care about cross browser compatibility, I'm not
                          sure what some weird browser does if you pass it a string in JS), in
                          javascript the API is different. It is specified to accept a function
                          reference instead of a string. In most browsers the following won't
                          work:

                          div.onclick = "alert('hello') ";

                          Again, I'd like to stress that there MAY be a couple of browsers out
                          there that will accept the code above, but in general DON'T DO IT.
                          Instead, in javascript you must pass it a function:

                          function sayHello () {alert('hello') }
                          div.onclick = sayHello;

                          Which means that if you don't want to declare a function then you must
                          wrap your code in an anonymous function.

                          div.onclick = function () {
                          alert('hello');
                          }

                          A word of warning. "this" points to different things depending on
                          weather you use the HTML API or the javascript API. The HTML API
                          magically points "this" to the clicked object while the javascript API
                          points it to the global object. Why is this? I don't know. But if I
                          were to guess I'd say that the people who created and implemented the
                          two different sets of APIs were different people and they have
                          different opinions on what is the right thing to do. As is usual in
                          software engineering, the standard answer to a "why" question tend to
                          be "historical reasons".

                          So, to get the clicked element in the javascript API you usually need
                          to do someting along the lines of:

                          div.onclick = function (evt) {
                          // because IE is different:
                          evt = evt || window.event;
                          // evt now points to the event object

                          // because IE is different:
                          var target = evt.target || evt.srcElement;
                          // target now points to the clicked element
                          }

                          Comment

                          • Henry

                            #14
                            Re: onclick behaves differently when defined via javascript

                            On Sep 30, 11:16 pm, slebetman wrote:
                            On Sep 26, 7:44 pm, Jorge wrote:
                            >On Sep 26, 12:43 pm, Henry wrote:
                            >
                            >>When an intrinsic event attribute is provided for an element
                            >>(assuming it is recognised, etc.), such as:-
                            >
                            >><div onclick="test() "</div>
                            >
                            >>- the browser uses the string value (the "text()" in this
                            >>case) as the body text of a function that it creates and
                            >>assigned to the corresponding property of the representation
                            >>of the element in the DOM. So what the browser does here is
                            >>the equivalent of:-
                            >
                            >>divRef.onclic k = function(event) {
                            >> test();
                            >
                            >>};
                            >
                            >Correct me if I'm mistaken, but I think I once read somewhere
                            >that it does an eval() of the text: like (in this case)
                            >eval('test()') ... ?
                            >
                            Event assignment API is drastically different between javascript
                            and HTML. In HTML it does indeed do an eval of the string text
                            supplied as the event handler, because the event handler is
                            supplied as a string:
                            <snip>

                            This - eval - nonsense needs to be knocked on the head once and for
                            all. Browsers do not - eval - the string values of intrinsic event
                            attributes, they use them as (all or part of) the bodies of function
                            objects that they create internally. This can illustrated by a simple
                            example; the attribute:-

                            onclick="return false;"

                            - is successful, and does what it can be expected to do in whichever
                            context it is used in. However, if you attempt:-

                            eval("return false;")

                            - you will always get an error (a syntax error). For example, IE's
                            error dialog reports "'return' statement outside of function".

                            Applying - eval - to intrinsic event attribute values would not work,
                            so it cannot be what the browser does.
                            A word of warning. "this" points to different things depending
                            on weather you use the HTML API or the javascript API. The
                            HTML API magically points "this" to the clicked object while
                            the javascript API points it to the global object.
                            <snip>

                            Bullshit! With the exception of intrinsic event attributes of the BODY
                            element (as previously mentioned here) the - this - value in code
                            specified as the string value of an intrinsic event attribute is the
                            same vale as the - this - value in functions assigned to the
                            corresponding intrinsic event properties of DOM elements.

                            In javascript the - this - value is determined (only and entirely) by
                            how you call a function and the browser calls the functions it created
                            from intrinsic event attribute string values and assigned to DOM
                            element intrinsic event properties in exactly the same way as it calls
                            the functions programmers my directly assign to DOM element intrinsic
                            event properties.
                            Why is this? I don't know.
                            <snip>

                            No you don't, but what you don't know is the 'what' not the 'why'.

                            <snip>
                            So, to get the clicked element in the javascript API you usually
                            need to do someting along the lines of:
                            >
                            div.onclick = function (evt) {
                            // because IE is different:
                            evt = evt || window.event;
                            // evt now points to the event object
                            >
                            // because IE is different:
                            var target = evt.target || evt.srcElement;
                            // target now points to the clicked element
                            }
                            Whenever the browser triggers this onclick event (and assuming - div -
                            is a reference to a DOM element that is not the BODY element, as its
                            name suggests) within the above function the expression - div === this
                            - would be true.

                            Comment

                            • dhtml

                              #15
                              Re: onclick behaves differently when defined via javascript

                              Henry wrote:
                              On Sep 30, 11:16 pm, slebetman wrote:
                              >On Sep 26, 7:44 pm, Jorge wrote:
                              >>On Sep 26, 12:43 pm, Henry wrote:
                              [snip]
                              >>
                              >div.onclick = function (evt) {
                              > // because IE is different:
                              > evt = evt || window.event;
                              > // evt now points to the event object
                              >>
                              > // because IE is different:
                              > var target = evt.target || evt.srcElement;
                              > // target now points to the clicked element
                              >}
                              >
                              Whenever the browser triggers this onclick event (and assuming - div -
                              is a reference to a DOM element that is not the BODY element, as its
                              name suggests) within the above function the expression - div === this
                              - would be true.
                              In which browser would |div| being the BODY element make any difference?

                              Comment

                              Working...