views:

2038

answers:

1

No matter what I try, I can't seem to fire the click event on the "default" button in an Alert control in a Flex 3.4 application.

Alert.show(
    'Are you sure you want to delete the selected link?',
    'Confirm Delete',
    Alert.YES | Alert.CANCEL,
    null, 
    confirmDelete, 
    null, 
    Alert.YES
);

In the above code sample, the final argument: Alert.YES is specifying that the "default" option (from the bitwise list in the 3rd argument) is the "Yes" button. In theory, and based on my experience designing Windows applications, "default button" means that hitting the enter key (or sometimes the space bar) fires the click event for that button.

If it matters, the Alert in question is modal.

I can see that the button is styled as the default: it gets a bit of a halo or extra border when compared to the Cancel button or when compared to itself when passing null as the last argument.

However, hitting the enter and space keys seem to have no affect. Am I doing something wrong, or missing some crucial step in getting this functionality to work?


Update 2010-02-17:

Based on my 2nd comment on @rhtx's answer:

Ok, finally got around to trying this. Since the Alert class uses lots of static methods, I essentially just copied the Alert and AlertForm classes into my project (and fixed some relative paths for includes), and what I ended up with was an uglier alert box that works (or doesn't, depending on your perspective) the same way as the vanilla Alert class. I did realize, however, that if you hit TAB it will focus the alert buttons, at which point hitting Escape/Enter will have the desired effect... So how do I eliminate the need to hit TAB?

I tried a few more things and didn't get anywhere.

I tried faking a TAB keypress after opening the alert (with both KEY_DOWN and KEY_UP event types):

var a:Alert = Alert.show(msg, title, Alert.YES | Alert.CANCEL, null, fnCb);
var tabEvent:KeyboardEvent = new KeyboardEvent(
    KeyboardEvent.KEY_DOWN,
    true,
    false, 
    0,
    Keyboard.TAB
);
a.dispatchEvent(tabEvent);

I also found this blog post and tried doing this to focus the alertForm:

var a:Alert = Alert.show(msg, title, Alert.YES | Alert.CANCEL, null, fnCb);
a.mx_internal::alertForm.setFocus();

Neither of these threw errors, but neither produced the desired result, either.

A: 

I would approach this by extending the Alert class to include functionality that listens for keyUp events from the Enter and Space keys.

In the createChildren method of your subclass:

override public function createChildren():void
{
    super.createChildren();
    this.addEventListener(KeyboardEvent.KEY_UP, keyUpListener);
    this.stage.addEventListener(KeyboardEvent.KEY_UP, keyUpListener);
}

private function keyUpListener(e:KeyboardEvent):void
{
    if(e.keyCode == Keyboard.ENTER || e.keyCode == Keyboard.SPACE)
    {
        //Trigger the Alert.YES functionality...
    }
}

I'm having some issues with my set up this morning and can't get into the Alert class to provide info on how to "Trigger the Alert.YES functionality", but I'll try to post some more on this later on. Hope this little bit helps.

Also - I'm not 100% on this - but I think you will need to manually remove the event listeners when the Alert popup is removed.

Aaand... you may not need both of those listeners. Can't test right now to make sure.

UPDATE: -----------------

After a little more looking, maybe the best way to go about this is to extend the AlertForm class (which manages the Alert's buttons), and then extend the Alert class to use your extended AlertForm class.

The AlertForm class has a keyDownHandler method, which it defines like this:

override protected function keyDownHandler(event:KeyboardEvent):void
{
    var buttonFlags:uint = Alert(parent).buttonFlags;

    if (event.keyCode == Keyboard.ESCAPE)
    {
        if ((buttonFlags & Alert.CANCEL) || !(buttonFlags & Alert.NO))
            removeAlert("CANCEL");
        else if (buttonFlags & Alert.NO)
            removeAlert("NO");
    }
}

You can see that it is setting up the 'close' behavior in response to pressing the Escape key. You add a little logic, based on the code in the above 'keyUpListener' function to make a call to the AlertForm's removeAlert method, passing in the appropriate String value for the Yes button.

For reference, the removeAlert method looks like this:

private function removeAlert(buttonPressed:String):void
{
    var alert:Alert = Alert(parent);

    alert.visible = false;

    var closeEvent:CloseEvent = new CloseEvent(CloseEvent.CLOSE);
    if (buttonPressed == "YES")
        closeEvent.detail = Alert.YES;
    else if (buttonPressed == "NO")
        closeEvent.detail = Alert.NO;
    else if (buttonPressed == "OK")
        closeEvent.detail = Alert.OK;
    else if (buttonPressed == "CANCEL")
        closeEvent.detail = Alert.CANCEL;
    alert.dispatchEvent(closeEvent);

    mx.managers.PopUpManager.removePopUp(alert);

}
Ross Henderson
Sorry for taking so long to get back to you. This seems like it should work, but it's lower on the priority list than fixing functionality bugs. Hopefully I'll get to it this week. :)
Adam Tuttle
Ok, finally got around to trying this. Since the Alert class uses lots of static methods, I essentially just copied the Alert and AlertForm classes into my project (and fixed some relative paths for includes), and what I ended up with was an uglier alert box that works (or doesn't, depending on your perspective) the same way as the vanilla Alert class. I did realize, however, that if you hit TAB it will focus the alert buttons, at which point hitting Escape/Enter will have the desired effect... So how do I eliminate the need to hit TAB?
Adam Tuttle