views:

57

answers:

2

I have a radio button, containing an inline onclick event:

<input type="radio" class="quantitycheckbox" onclick="alterQuantity(this.form)">

I'm trying to unobtrusively add some more functionality on click, and have this code:

function updateCustomFields( box ) {
    // save current onclick event before assigning new one
    var currEvent = box.onclick;
    box.onclick = function() {
        currEvent();
        // do additional stuff here
    }
}

var boxes = $class('quantitycheckbox');
for( var i = 0; i < boxes.length; i++ ) {
    updateCustomFields( boxes[i] );
}

However, the value of this.form that's passed into the alterQuantity function is undefined, and I get an error. How would I preserver the onclick event as it is and add my functionality?

+2  A: 

You don't need to do anything with the inline onclick event. Simply by attaching another event using attachEvent or addEventListener will solve your problem since the inline onclick event will always fire first:

function updateCustomFields( box ) {
    var myCallback = function(){
      // Do stuff here
    }
    if(window.addEventListener){
      box.addEventListener('click', myCallback, false);
    } else if (window.attachEvent){
      box.attachEvent('onclick', myCallback);
    }
}

The execution order will be:

  1. Inline event
  2. Your new event
Doug Neiner
How is this the *correct* way? And where is it documented that an event handler set via the `onclick` property is guaranteed to fire first in all browsers?
Tim Down
@Tim, events are always executed in order. Since inline `onclick` handlers are "registered" first (you can't add an event to a DOM element until it exists, and as soon as it exists the inline handler is already attached to the element). It is the *correct* way because of how strongly I feel that logic should be kept separate from structure. I think I meant to be in quotes so it reveals my bias... I will edit :)
Doug Neiner
The interaction between inline events and the W3 DOM Events standard (not to mention IE's mess) is not standardised at all. Though when IE, Mozilla, WebKit and Opera all agree on something you're generally onto a winner.
bobince
+1  A: 

Try:

currentEvent.call(box);

to pass box as the value of this into currentEvent();

edit: Doug's solution is actually better. Anyway, the call and apply methods available to all function objects is how you alter the value of this in function calls.

slebetman
I think the problem is that `this.form` is never passed, not the value of `this`. No argument information is retained when he calls `currEvent();`.
Jonathon
This can also be done with `call`: `currentEvent.call(box, box.form)`.
bobince
@Jon: What you're not realising is that currentEvent looks like this:`function(){alterQuantity(this.form)}`. The `alterQuantity()` function is compiled as the body of the event handler, not the event handler itself. So just passing `this` is enough to pass `this.form` to `alterQuantity()`.
slebetman
@slebetman You're absolutely right, I wasn't paying attention.
Jonathon