>
Blog
Book
Portfolio
Search

6/12/2008

6258 Views // 4 Comments // 5.0 Rating

A Quick Gotcha With JavaScript Function Callbacks

I thought I'd share a quick gotcha when wiring function callbacks with $addHandler in JavaScript. $addHandler takes in a DOM element, the name of the event, and a method to handle it. This looks something like:

Code Listing 1

  1. var button = document.createElement('input');
  2. button.type = 'button';
  3. button.value = 'Click Here Immediately';
  4. $addHandler(button, 'click', ButtonClicked);
  5. ...
  6. function ButtonClicked(e)
  7. {
  8. ...
  9. }

The signature of the delegate $addHandler wants has one parameter, (which from my .NET upbringing is called "e") that acts as event args. This object contains a lot of information, such as a reference to the "sender" (again, from .NET, the control that fired the event), mouse location data, etc. This is passed for free; no additional works needs to be done if this is all you need.

However, if you want to pass additional parameters, you need to create a callback and use that as the third parameter send to $addHander. Using this technique, the above $addHandler call needs to be modified, as follows:

Code Listing 2

  1. var someVariable;
  2. ...
  3. $addHandler(button, 'click', Function.createCallback(ButtonClicked, someVariable));

You can only pass one variable, so if your event handler needs additional parameters, stuff them into an Array first:

Code Listing 3

  1. var args = new Array();
  2. args[0] = someVariable;
  3. args[1] = someOtherVariable;
  4. $addHandler(button, 'click', Function.createCallback(ButtonClicked, args));

Here is the gotcha: since we are explicitly creating a callback method to be used as the delegate for the event handler, you'd assume we are forcing our event handler to match the signature of the callback. So attempting the following:

Code Listing 4

  1. function ButtonClicked(args)
  2. {
  3. var someVariable = args[0];
  4. }

Will actually result in an error, and a very misleading error at that: "someVariable" will be undefined! When I first encountered this, I went down the path of making sure that I correctly declared and populated my array, correctly used "Function.createCallback" instead of something like "function.CreateCallback," etc. But nothing made sense.

The problem is that $addHandler will ALWAYS respect the "e" parameter and pass it along with the callback's argument. Therefore, the correct syntax for our event handler is:

Code Listing 5

  1. function ButtonClicked(e, args)
  2. {
  3. ...
  4. }

If you are manually calling these event handlers, you then still need to supply the "e." I usually do something like:

Code Listing 6

  1. var args = new Array();
  2. args[0] = someVariable;
  3. args[1] = someOtherVariable;
  4. ButtonClicked(null, args);

The works well because if you don't need the "e" then chances are you are really using this event handler more like a normal method that also happens to listen to an event. And if you are using "e," you probably won't be calling this method outside the context of the event. (For example, if your event is mouse driven (like mousemove), and you need the coordinates of the cursor, then how could you fire this off manually anyways?)

So I thought I'd share this. In general, JavaScript lets us bend some of the rules we are used to following with complied languages. Scripts can "workaround" some issues (such as parameter mismatches, as we've seen here) and keep going. Take advantage of this; you can crank out functionality very quickly. However, don't get lazy and start writing sloppy code! Have fun!

2 Tags

No Files

4 Thoughts

silverlight
can you explain how to listen to these callback from silverlight app?
peter, 11/10/2013
silverlight
can you explain how to listen to these callback from silverlight app?
peter, 11/10/2013
silverlight
can you explain how to listen to these callback from silverlight app?
peter, 11/10/2013
silverlight
can you explain how to listen to these callback from silverlight app?
peter, 11/10/2013

Your Thoughts?

You need to login with Twitter to share a Thought on this post.


Loading...