Dynamically adding onclick to element

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

    Dynamically adding onclick to element

    I am trying to dynamically add an onclick to an element,
    however I just can't get the syntax right. consider the
    following function:

    function doClick (evt,x) {
    // do things with evt and x
    }

    Which is called statically by:
    <button onclick="doClic k(event,this);" >Click me</button>

    evt should be a reference to the onclick event, and x to the
    element clicked on. But I can't get the syntax right for adding
    the element dynamically. The closest I can get is:

    ele.onclick = function (){doClick('eve nt','this')};

    But when I click on the element, 'event' and 'this' have been
    passed is literal strings (i.e. e and x are 'event' and 'this',
    literally).

    What is the correct syntax?

    *Extra comment*

    I have tried adding the function this way:

    ele.onclick = doClick;

    And then use e/window.event to get the event and use
    e.target/e.srcElement to get the element clicked on, but that is
    not reliable with some browsers. For example, in Safari if you
    have an onclick on a TD with text in it and the user clicks on
    the text, e.target points to the text node, not the TD. If they
    click in the TD but not over the text e.target points to the TD.

    This is avoided if the onclick passes 'this', which
    unequivocally (I think) gives a reference to the element that
    the onclick fired from.

    Of course I can climb the DOM tree to find the first onclick and
    hope that was the one that fired, but that's messy. It also
    creates an issue if there's a link in the cell. Other browsers
    will follow the link and not execute the onclick - Safari does
    the onclick. Again, I can look to see if target was an A and
    follow the link by changing the window.location , but again,
    that's messy.

    Play code below.

    <html><head><ti tle>DynFunc</title>
    <script type="text/javascript">
    function initButton() {
    var ele = document.getEle mentById('theBu tton');
    ele.onclick = function (){doClick('eve nt','this')};
    }

    function doClick(evt,x) {
    alert('evt is: ' + typeof(evt)
    + '\nx is: ' + typeof(x));
    }
    </script>
    </head><body>
    <button onclick="initBu tton();">Initia lise theButton</button>
    &nbsp;
    <button id="theButton"> theButton</button>
    &nbsp;
    <button onclick="doClic k(event,this);" >Static onclick</button>
    </body></html>

    --
    Rob
    --
    Rob
  • Richard Cornford

    #2
    Re: Dynamically adding onclick to element

    RobG wrote:[color=blue]
    > I am trying to dynamically add an onclick to an element,
    > however I just can't get the syntax right. consider the
    > following function:
    >
    > function doClick (evt,x) {
    > // do things with evt and x
    > }
    >
    > Which is called statically by:
    > <button onclick="doClic k(event,this);" >Click me</button>[/color]

    Disregarding the custom scope chain code, specifying event handler code
    in the string value of an attribute results in the browser creating an
    event handling function and assigning it as a method of the DOM element
    in question. In IE it is equivalent to:-

    buttonRef.oncli ck = function(){
    doClick (event,x);
    };

    While in Mozilla/Gecko and other browsers that follow the Netscape style
    you get a function like:-

    buttonRef.oncli ck = function(event) {
    doClick (event,x);
    };

    - created and assigned. Notice that the Netscape style has a function
    with a formal p0arameter called - event -. So the Netscape style event
    handler passes whatever value is passed as an argument to the event
    handler function on to your doClick function, while the IE version
    resolves the unqualified Identifier - event - against the scope chain
    and finds the - window.event - object in the global scope. This allows
    attribute code to use the same identifier to pass on the event object.


    <snip>[color=blue]
    > ele.onclick = function (){doClick('eve nt','this')};
    >
    > But when I click on the element, 'event' and 'this' have been
    > passed is literal strings (i.e. e and x are 'event' and 'this',
    > literally).[/color]

    If you put quotes around the identifiers/keywords they will be string
    literals.
    [color=blue]
    > What is the correct syntax?[/color]

    ele.onclick = function (e){doClick((e| |window.event), 'this')};

    - will do.
    [color=blue]
    > *Extra comment*
    >
    > I have tried adding the function this way:
    >
    > ele.onclick = doClick;[/color]

    With:-

    function doClick(e){
    e = e || window.event;
    // do things with e and this,
    // as - this - will refer to whichever element this function
    // is assigned to as a method (- ele - in that case).
    }

    - that would work fine.
    [color=blue]
    > And then use e/window.event to get the event and use
    > e.target/e.srcElement to get the element clicked on, but that is
    > not reliable with some browsers.[/color]

    The actual event handling function (either created by the browser or
    assigned as a property of the element with a script) is executed as a
    method of the DOM element and under those circumstances the - this -
    keyword is a reference to that object (the DOM element).
    [color=blue]
    > For example, in Safari if you
    > have an onclick on a TD with text in it and the user clicks on
    > the text, e.target points to the text node, not the TD. If they
    > click in the TD but not over the text e.target points to the TD.
    >
    > This is avoided if the onclick passes 'this', which
    > unequivocally (I think) gives a reference to the element that
    > the onclick fired from.[/color]
    <snip>

    Depends on what you mean by 'fired from'. If you mean the source of an
    event that is processed when captured or bubbling (rather than at its
    target) then no it doesn't necessarily refer to the target. It refers to
    the element with which the handler function is associated (as a method).

    Richard.


    Comment

    • RobG

      #3
      Re: Dynamically adding onclick to element

      Richard Cornford wrote:
      [...][color=blue]
      > <snip>[color=green]
      > > ele.onclick = function (){doClick('eve nt','this')};
      > >
      > > But when I click on the element, 'event' and 'this' have been
      > > passed is literal strings (i.e. e and x are 'event' and 'this',
      > > literally).[/color]
      >
      > If you put quotes around the identifiers/keywords they will be string
      > literals.
      >[color=green]
      > > What is the correct syntax?[/color]
      >
      > ele.onclick = function (e){doClick((e| |window.event), 'this')};
      >
      > - will do.[/color]

      Yuck, not for me! I think I can work out what is going on, but it
      makes my brain hurt. For my purpose the simplicity of:

      ele.onclick = doClick;

      is very appealing. e & this are then handled in the function with:

      function doClick(e,x) {
      e = e || window.event;
      x = x || this;

      doClick can now be called from either dynamic or static onclicks
      quite happily (only tested in IE & Firefox, Safari will have to
      wait...)
      Thanks for the shorthand "OR" method, I was using:

      if (!e && window.event) var e=window.event;
      if (!x && this) var x = this;
      [color=blue]
      >[color=green]
      > > *Extra comment*[/color][/color]
      [...][color=blue]
      > function doClick(e){
      > e = e || window.event;
      > // do things with e and this,
      > // as - this - will refer to whichever element this function
      > // is assigned to as a method (- ele - in that case).
      > }
      >
      > - that would work fine.[/color]

      I actually worked that out after posting - funny how you can struggle
      with something for ages, then as soon as you post...

      I still have an awful lot to learn about JavaScript and functions in
      particular (DOM stuff is a snap by comparison), thank you for the
      excellent tutorial. Hopefully some of it will sink in...

      --
      Rob

      Comment

      Working...