Friday, September 28, 2012

Creating Advanced Alert Window class: Part 26

Today we will add the ability to use the Enter key to "click" buttons in the alert window.

When we will handle the enter key, we're going to need know the close handler function for that alert window to call it. We can do this by storing the handler reference in a variable and then read from that variable, or we could put it as one of the attributes of an element in windows array, next to the window and blur references.

Open AdvAlertManager.as class, go to alert() function and find the line that adds elements to the windows array, where we can add an onclose attribute and store the close handler reference there.

windows.push( {window:w, blur:b, onclose:closeHandler} );

Full alert() function:

public function alert(text:String, title:String = "", buttons:Array = null, closeHandler:Function = null, width:int = 300, height:int = 200, position:Point = null):void {
if (position == null) position = new Point((pWidth / 2) - (width / 2), (pHeight / 2) - (height / 2));
if (buttons == null) buttons = [];
for (var i:int = buttons.length - 1; i >= 0; i--) {
if (!buttons[i] is AdvAlertButton) {
throw new Error("An item in 'buttons' array is not an AdvAlertButton instance. Ignoring...");
buttons.splice(i, 1);
}else {
buttons[i].addEventListener(MouseEvent.CLICK, buttonHandler);
}
}
var w:AdvAlertWindow = new AdvAlertWindow(text, title, width, height, position, skin, buttons, bSkin);
var b:AdvAlertBlur = new AdvAlertBlur(pWidth, pHeight, skin);
var currentIndex:int = windows.length;
windows.push( {window:w, blur:b, onclose:closeHandler} );
defaultContainer.addChild(b);
defaultContainer.addChild(w);

topWindow = w;
focusedButton = -1;
if (tabDisable) {
defaultContainer.tabChildren = false;
defaultContainer.tabEnabled = false;
}

function buttonHandler(evt:MouseEvent):void {
if (closeHandler != null) closeHandler.call(evt.currentTarget, evt.currentTarget.txt);
windows[currentIndex].window.parent.removeChild(windows[currentIndex].window);
windows[currentIndex].blur.parent.removeChild(windows[currentIndex].blur);
windows.splice(currentIndex, 1);
if (windows.length > 0) topWindow = windows[windows.length - 1].w;
if (windows.length == 0) topWindow = null;
if (tabDisable && windows.length==0) {
defaultContainer.tabChildren = true;
defaultContainer.tabEnabled = true;
}
}
}

Now go to the kDown() function, add an if..statemenet that listens for Enter key (keyCode 13). Declare 2 variables - currentIndex (set to windows.length-1 to reference the top window) and closeHandler (set to the onclose attribute of the top window in the windows array).

Then execute the same code that is executed when a button is clicked.

Full kDown() function:

private function kDown(evt:KeyboardEvent):void {
if (evt.keyCode == 9 && topWindow!=null && topWindow.buttons.length>0) {
focusedButton++;
if (focusedButton == topWindow.buttons.length) {
focusedButton = 0;
}
for (var i:int = 0; i < topWindow.buttons.length; i++) {
topWindow.buttons[i].over = false;
topWindow.buttons[i].updateDraw();
}
topWindow.buttons[focusedButton].over = true;
topWindow.buttons[focusedButton].updateDraw();
}
if (evt.keyCode == 13 && topWindow != null && topWindow.buttons.length > 0) {
var currentIndex:int = windows.length - 1;
var closeHandler:Function = windows[currentIndex].onclose;
if (closeHandler != null) closeHandler.call(evt.currentTarget, evt.currentTarget.txt);
windows[currentIndex].window.parent.removeChild(windows[currentIndex].window);
windows[currentIndex].blur.parent.removeChild(windows[currentIndex].blur);
windows.splice(currentIndex, 1);
if (windows.length > 0) topWindow = windows[windows.length - 1].w;
if (windows.length == 0) topWindow = null;
if (tabDisable && windows.length==0) {
defaultContainer.tabChildren = true;
defaultContainer.tabEnabled = true;
}
}
}

And full AdvAlertManager class:

package com.kircode.AdvAlert 
{
import flash.display.DisplayObjectContainer;
import flash.display.MovieClip;
import flash.display.Stage;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.events.KeyboardEvent;
import flash.events.Event;
/**
 * Advanced Alert window manager.
 * @author Kirill Poletaev
 */
public class AdvAlertManager 
{
private var windows:Array;
private var defaultContainer:DisplayObjectContainer;
private var pWidth:int;
private var pHeight:int;
private var skin:AdvAlertSkin;
private var bSkin:AdvAlertButtonSkin;
private var tabDisable:Boolean;
private var topWindow:AdvAlertWindow;
private var focusedButton:int;
private var stg:Stage;

/**
 * AdvAlertManager constructor.
 * @paramdefaultWindowContainer Parent container of alert windows.
 * @paramstage Stage reference.
 * @paramwindowSkin Default skin for alert windows.
 * @parambuttonSkin Default skin for buttons in this window.
 * @paramdisableTab Disable tab focusing on the parent container when an alert window is visible. This also enables tab navigation for the alert window's buttons.
 */

public function AdvAlertManager(defaultWindowContainer:DisplayObjectContainer, stage:Stage, windowSkin:AdvAlertSkin = null, buttonSkin:AdvAlertButtonSkin = null, disableTab:Boolean = true) 
{
trace(": AdvAlertManager instance created.");
skin = windowSkin;
bSkin = buttonSkin;
tabDisable = disableTab;
if (skin == null) skin = new AdvAlertSkin();
if (bSkin == null) bSkin = new AdvAlertButtonSkin();
defaultContainer = defaultWindowContainer;
pWidth = stage.stageWidth;
pHeight = stage.stageHeight;
stg = stage;
windows = [];
if (tabDisable) {
stg.addEventListener(KeyboardEvent.KEY_DOWN, kDown);
}
}

private function kDown(evt:KeyboardEvent):void {
if (evt.keyCode == 9 && topWindow!=null && topWindow.buttons.length>0) {
focusedButton++;
if (focusedButton == topWindow.buttons.length) {
focusedButton = 0;
}
for (var i:int = 0; i < topWindow.buttons.length; i++) {
topWindow.buttons[i].over = false;
topWindow.buttons[i].updateDraw();
}
topWindow.buttons[focusedButton].over = true;
topWindow.buttons[focusedButton].updateDraw();
}
if (evt.keyCode == 13 && topWindow != null && topWindow.buttons.length > 0) {
var currentIndex:int = windows.length - 1;
var closeHandler:Function = windows[currentIndex].onclose;
if (closeHandler != null) closeHandler.call(evt.currentTarget, evt.currentTarget.txt);
windows[currentIndex].window.parent.removeChild(windows[currentIndex].window);
windows[currentIndex].blur.parent.removeChild(windows[currentIndex].blur);
windows.splice(currentIndex, 1);
if (windows.length > 0) topWindow = windows[windows.length - 1].w;
if (windows.length == 0) topWindow = null;
if (tabDisable && windows.length==0) {
defaultContainer.tabChildren = true;
defaultContainer.tabEnabled = true;
}
}
}

/**
 * Set skin of all future created alert windows.
 * @paramwindowSkin Reference to an AdvAlertSkin object.
 */

public function setSkin(windowSkin:AdvAlertSkin):void {
skin = windowSkin;
}

/**
 * Set skin of all buttons of future created alert windows.
 * @parambuttonSkin Reference to an AdvAlertButtonSkin object.
 */

public function setButtonSkin(buttonSkin:AdvAlertButtonSkin):void {
bSkin = buttonSkin;
}

/**
 * Create an alert window.
 * @paramtext Text value of the alert window.
 * @paramtitle Title value of the alert window.
 * @parambuttons (Optional) Array of AdvAlertButton objects that represent buttons in the alert window.
 * @paramcloseHandler (Optional) Close handling function. Must receive a string value as parameter (which will hold the label of the button that was clicked).
 * @paramwidth (Optional) Width of the alert window. 300 by default.
 * @paramheight (Optional) Height of the alert window. 200 by default.
 * @paramposition (Optional) Coordinates of top-left corner of the alert window. If not specified - the window is centered.
 */

public function alert(text:String, title:String = "", buttons:Array = null, closeHandler:Function = null, width:int = 300, height:int = 200, position:Point = null):void {
if (position == null) position = new Point((pWidth / 2) - (width / 2), (pHeight / 2) - (height / 2));
if (buttons == null) buttons = [];
for (var i:int = buttons.length - 1; i >= 0; i--) {
if (!buttons[i] is AdvAlertButton) {
throw new Error("An item in 'buttons' array is not an AdvAlertButton instance. Ignoring...");
buttons.splice(i, 1);
}else {
buttons[i].addEventListener(MouseEvent.CLICK, buttonHandler);
}
}
var w:AdvAlertWindow = new AdvAlertWindow(text, title, width, height, position, skin, buttons, bSkin);
var b:AdvAlertBlur = new AdvAlertBlur(pWidth, pHeight, skin);
var currentIndex:int = windows.length;
windows.push( {window:w, blur:b, onclose:closeHandler} );
defaultContainer.addChild(b);
defaultContainer.addChild(w);

topWindow = w;
focusedButton = -1;
if (tabDisable) {
defaultContainer.tabChildren = false;
defaultContainer.tabEnabled = false;
}

function buttonHandler(evt:MouseEvent):void {
if (closeHandler != null) closeHandler.call(evt.currentTarget, evt.currentTarget.txt);
windows[currentIndex].window.parent.removeChild(windows[currentIndex].window);
windows[currentIndex].blur.parent.removeChild(windows[currentIndex].blur);
windows.splice(currentIndex, 1);
if (windows.length > 0) topWindow = windows[windows.length - 1].w;
if (windows.length == 0) topWindow = null;
if (tabDisable && windows.length==0) {
defaultContainer.tabChildren = true;
defaultContainer.tabEnabled = true;
}
}
}

}

}

Now we can navigate through the alert buttons using tab and press the buttons using enter.

Thanks for reading!

No comments:

Post a Comment