Monday, March 16, 2009

The Button and the Event

So there's a Button that triggers a complex event. In short, it calls a remote object thru Granite to JBoss, and does some neato stuff.

Problem: users have (accidentally) double-clicked (and even triple-clicked) that Button, resulting in multiple event dispatches, bad data, and some server-side exceptions.

Normally, I'd disable the Button.

 button.enabled = false; 

Then, when processing is done, I'll re-enable it. Easy, right?

 button.enabled = true;

But, in this case, that's not fast enough -- the user can click that button five or six times before the Button's disabled! (I didn't think that was possible, but it is).

OK then, I'll cut it off at the source: first, I removed the ActionScript inside the "click" attribute of the MX element:


< id="bntCreateMan">


...and I put the code into an explicit handler, like this:


// this method is triggered ONLY by clicking
// the "Create Manifest" button
private function
handleCreateNewManifest(event:MouseEvent):void
{
this.btnCreateMan.removeEventListener(
MouseEvent.CLICK,handleCreateNewManifest);
...
createNewManifest();
}


Add that handler in the creationComplete() method, and voila!

Note the sneaky call in the handler: as soon as we click the Button, the handler removes itself. Thus, subsequent button clicks fall on deaf ears.

Now to put the handler back. We want it back when the manifest data is handled... we have a handler for that of course. So we have:


private function
handleManifestData(event:ResultEvent):void
{
(...some code...)
this.btnCreateMan.addEventListener(
MouseEvent.CLICK,handleCreateNewManifest);
}


How clever of us.

New Problem: That handler, shown above, is invoked by other processes as well. So what really happens is that the event handler gets attached to that Button multiple times, and only removed when the Button is pressed. Aiigh!

The solution is mundane and so old school: instead of manipulating the event listener, we add a Boolean value that the Button's listener uses. If it's false, we go ahead and kick off a manifest creation. Then, back in the ManifestData handler, if the boolean is true then we re-set it.

It's not pretty, it feels a bit kludgy, but it seems to work best.

1 comment: