9

I have the following Code which I know doesn't work correctly. Yes I know how to do this in jQuery but in this case I cannot use jQuery. Please no jQuery answers.

<form>
  <input type="text" name="input1" onclick="alert('hello')">
  <input type="text" name="input2">
  <input type="text" name="input3">
</form>


<script type="text\javascript">
  window.onload = function () {
    var currentOnClick;
    for (var i = 0; i < document.forms[0].elements.length; i++) {
      currentOnClick = document.forms[0].elements[i].onclick;
      document.forms[0].elements[i].onclick = function () {
        if (currentOnClick) {
          currentOnClick();
        }
        alert("hello2");
      }
    }
  }
</script>

What I'm trying to do is iterate through the form's elements and add to the onclick function. But due to the fact that in my last iteration currentOnClick is null this does not run as expected. I want to preserve each of the elements onclick methods and play them back in the new function I'm creating.

What I want:

  • When input1 is clicked, alert "hello" then alert "hello2"

  • When Input2 is clicked, alert "hello2"

  • When Input3 is clicked, alert "hello2"

2
  • What is it doing now that you didn't expect? Commented May 7, 2010 at 17:56
  • When any input is clicked it alerts hello2. For input1 I want it to preserve the current onclick method and run inside my newly created onclick method Commented May 7, 2010 at 18:01

2 Answers 2

8

the way you have it, your elements all refer to the same instance of currentOnClick. each time you assign currentOnClick to the current element's existing onclick function, it loses the reference to the previous function. you need to create the new event handler function in a separate scope for each element.

function addClickProxy(element) {
    var currentOnClick = element.onclick;
    element.onclick = function() {
        if (currentOnClick) {
            currentOnClick();
        }
        alert("hello2");
    }
}

window.onload = function() {
    for (var i = 0; i < document.forms[0].elements.length; i++) {
        addClickProxy(document.forms[0].elements[i]);
    }
}

this way, there are 3 different instances of currentOnClick floating around, each sealed from the others by the function scope.

Sign up to request clarification or add additional context in comments.

Comments

6

This helps:

window.onload = function () {
    for (var i = 0, element; element = document.forms[0].elements[i]; i++) {
        element.onclick = (function (onclick) {
            return function(oEvent) {
                // reference to event to pass argument properly
                oEvent  = oEvent || event;
                if (onclick)
                    onclick(oEvent);
                // new code "injection"
                alert("hello2");
            }
        })(element.onclick);
    }
}

Or this:

window.onload = function () {
    for (var i = 0, element; element = document.forms[0].elements[i]; i++) {
        element.exonclick = element.onclick;
        element.onclick = function (oEvent) {
            if (this.exonclick) {
                this.exonclick(oEvent);
            }
            //
            alert("hello2");
        }
    }
}

Please be warned, the technique will not work if event handlers were added with DOM-Events API.

2 Comments

Thanks the first method works like i would expect but I need some help understanding the syntax. you seem to call element.onclick = (somefunction)(element.onclick). I appologize but I just dont understand.
Both work in fact. The JavaScript technique used in the first solution is called "closure".

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.