views:

61

answers:

2

I have some JavaScript/jQuery code that watches for the "changed" event on a checkbox:

$(control).change(function() {
    alert("changed to: " + $(this).is(":checked"));
});

This works fine.

I'd like to create a reference to the change() function on the particular object, and call it indirectly, like so:

var onSomeChange = $(control).change;
onSomeChange(function() {
    alert("changed to: " + $(this).is(":checked"));
});

I need to call it indirectly because I'll want to switch the method I'm assigning to onSomeChange with a different one, depending on the circumstances. (The single assignment to onSomeChange is just here for illustration).

This doesn't work. In Firebug I get this error:

this.bind is not a function

How can I get a reference to an object's method and call it without calling it from the object directly?

Background

The context may be significant; if there's an entirely different way to do what I want, that's fine too.

The behavior of the change event in JavaScript is a bit different for check boxes and radio buttons. A check box fires change whenever its state changes (checked or unchecked). However, radio buttons (in Firefox at least; I think it's even more complicated in other browsers) only fire a change for the radio button group as a whole. That's understandable, but I want to bind different actions to the states of the individual radio buttons. (Specifically, I want to potentially hide or show certain divs depending on the radio button states).

I think I can handle the event discrepancies by binding a custom event to each radio and then triggering it based on a change in the group. So I have extended jQuery to add a radioChange() method. This method

Now, I'd like to swap out this code with something that calls a different event-handling method depending on the type of the control. (Aside: it's because radio button seem to be handled differently than check boxes, so I have a different radio-button-specific event). I've added a radioChanged() extension method to jQuery to support this.

Now I want to have a method that registers a listener to either changed() or radioChanged() depending on the type of the object. Determining that is easy:

var change = $(control).is(":radio") ? $(control).radioChange : $(control).change;

The problem is that I can't actually call the method at the change reference without generating the error above.

Is there something else I should be doing to make this work?

+2  A: 

sounds like you just need to call the bind event and pass it the targeted event string

$(control).bind($(control).is(":radio") ? "radioChange", "change", function () {});
Tom Brothers
That's not a bad idea for my particular case. Still, it would be nice to be able to reference the methods (as I described in my general case). For one, I don't know whether jQuery's change() (or my radioChange() for that matter) adds any additional logic that I'm missing by binding to the event directly. Secondly, I might want to do this for non-event methods eventually. Still, it'll probably work for me here.
Craig Walker
+3  A: 

Answer to original question:

You need to apply it on a object which has bind as prototype. probably enough to just pass $(control) as object in question, or perhaps $ is enough.

var $control = $(control);
var change = $control.change;
change.call( $control, 
    function() {
      alert("changed to: " + $(this).is(":checked"));
    }
);
azatoth
I was wondering about this. I'll give it a try in a bit.
Craig Walker
Yup, this is the ticket. Note that I edited your answer to remove the $ on the control variable; they're not needed. (I didn't even try to run it with them, so it may have worked that way too, but it works fine without them and is simpler to boot).
Craig Walker
Bah, I introduced a bug in my edit. Your version does work fine, so I've reverted back to it. Thanks once again!
Craig Walker
the $ on control was just a marker that it was a jQuery object ($ doesn't have any special meaning in javascript, so you can have an variable called "$foo")
azatoth