How to Create Alert Dialog in ActionScript3? - actionscript-3

I'm working on a project with Actionscript 3.0 in Flash Pro (CS5). I want to create a confirmation box. If I were using the Flex SDK I could do this using the Alert class in the mx.controls package. However, it seems that no similar control exists in the standard Flash library and any amount of Googling just leads me to Flex references.

Try this Class
package com.whatever {
//Imports
import flash.display.Shape;
import flash.display.Sprite;
import flash.geom.Rectangle;
import flash.events.MouseEvent;
//Class
public class AlertBox extends Sprite {
//Vars
protected var box:Shape;
protected var yesBtn:Sprite;
//Constructor
public function AlertBox($:Rectangle):void {
//Initialise
box = new Shape()
yesBtn = new Sprite()
addChild(box)
addChild(yesBtn)
//Render
with (box.graphics) {
lineStyle(1)
beginFill(0, 0.4)
drawRect($.x, $.y, $.width, $.height)
endFill()
}
with (yesBtn.graphics) {
lineStyle(1, 0x00FF00)
beginFill(0x00FF00, 0.4)
drawRect($.x+$.width-100, $.y$.height-40, 80, 20)
endFill()
}
//Events
yesBtn.addEventListener(MouseEvent.CLICK, yesClickHandler, false, 0, true)
yesBtn.addEventListener(MouseEvent.MOUSE_OVER, yesOverHandler, false, 0, true)
}
//Handlers
protected function yesClickHandler($):void {}
protected function yesOverHandler($):void {}

You said that you can't import mx.Controls in AS3 but the following should work in a flex 4 project:
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
creationComplete="init()">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.controls.Alert;
private function init():void
{
Alert.show("This is an Alert!!!");
}// end function
]]>
</fx:Script>
</s:Application>
[UPDATE]
After realizing that I misunderstood the question, I looked on the internet for a Alert component for AS3 projects and found the following:
http://developer.yahoo.com/flash/astra-flash/alertmanager/
I'm going try my hand at creating a replica of the flex framework's Alert control and then update my answer again.

If your final swf is going to run in the browser and have script access, you could just use one of the JavaScript PopUp Boxes:
if(ExternalInterface.available) {
if (ExternalInterface.call("confirm", "Should I trace 'Yes'?")) {
trace("Yes"); // user clicked Okay
} else {
trace("User canceled or the call failed");
}
}
I'm pretty sure this will freeze the Flash UI loop until the JavaScript function returns, so make sure you call it when it's all you want to be doing.

I believe that you can continue to use the same Alert class
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/controls/Alert.html

Related

Binding in Flex: How to make a variable automatically update when another variable is changed?

I know that it is possible to make a parameter of a component depend on a variable, provided that variable contains the [Bindable] tag. This means that updating the value of the Bindable variable automatically updates the component.
Is it possible to make another variable depend on a Bindable variable?
In the example below I have a variable btnClicked that is bound. When btnClicked is changed by the function btnClick() being called, the text in the TextArea is updated as expected.
I would like to be able to make another variable, btnText, be updated when btnClicked is updated. I do not know how to communicate this dependency. In the code below the value of btnText is initially "clickMe" as expected. However, when btnClicked changes, the text on the button does not update to "unclickMe".
<fx:Script>
<![CDATA[
[Bindable]
public var btnClicked:Boolean = false;
public function btnClick():void{
btnClicked = !btnClicked;
}
[Bindable]
public function get btnText():String{
return btnClicked?"unclickMe":"clickMe";
}
]]>
</fx:Script>
<s:Button click="btnClick()" label="{btnText}"/>
<s:TextArea y="50" text="{btnClicked?'Button is clicked':'Button is unclicked'}"/>
How can I change the code above so that btnText automatically updates when btnClicked is changed?
Would it be possible to have an arbitrarily long chain of connected variables each of which updates when the previous one updates?
You can also use a ChangeWatcher to detect when your bindable property is updated :
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" creationComplete="init(event)">
<fx:Script>
<![CDATA[
import mx.binding.utils.ChangeWatcher;
import mx.events.FlexEvent;
public var watcher:ChangeWatcher;
[Bindable]
public var btnClicked:Boolean = false;
[Bindable]
public var btnText:String = 'clickMe';
protected function btnClick():void {
btnClicked = !btnClicked;
}
protected function init(event:FlexEvent):void
{
watcher = ChangeWatcher.watch(this, 'btnClicked', watcherListener);
}
protected function watcherListener(event:Event):void {
btnText = btnClicked ? 'unclickMe' : 'clickMe';
}
]]>
</fx:Script>
<s:Button x="303" y="30" label="{btnText}" click="btnClick()"/>
<s:TextArea x="303" id="txt" y="96" text="{btnClicked ? 'Button is clicked' : 'Button is unclicked'}"/>
</s:Application>
Hope that can help.
In this case, all you have to do is update your btnClick function to dispatch a PropertyChangeEvent:
public function btnClick():void{
btnClicked = !btnClicked;
dispatchEvent(new PropertyChangeEvent(PropertyChangeEvent.PROPERTY_CHANGE));
}
This works because of the way [Bindable] works - see What does [Bindable] mean in actionscript? for a nice explanation.
Using the Bindable metadata tag and Binding to functions, Objects, and Arrays are good resources for background reading, too.
Edit: Don't forget the import statement!
import mx.events.PropertyChangeEvent;
Flash Builder will insert the import statement for you if you ctrl-space while typing PropertyChangeEvent.
I have found a solution, but if someone has a cleaner solution that makes use of in built Flex features please post it.
The following code updates the value of btnText each time the value of btnClicked is changed. It does this by having a setter function for btnClicked that explicitly calls function updateBtnText. See this explanation for more information about how getters and setters allow you to call other functions any time a variable is read or written.
<fx:Script>
<![CDATA[
private var _btnClicked:Boolean = false;
[Bindable]
public function get btnClicked():Boolean{
return _btnClicked;
}
public function set btnClicked(newBtnClicked:Boolean):void{
_btnClicked = newBtnClicked;
updateBtnText();
}
private function updateBtnText():void{
btnText = btnClicked?"unclickMe":"clickMe";
}
public function btnClick():void{
btnClicked = !btnClicked;
}
[Bindable]
public var btnText:String = btnClicked?"unclickMe":"clickMe";
]]>
</fx:Script>
<s:Button click="btnClick()" label="{btnText}"/>
<s:TextArea y="50" text="{btnClicked?'Button is clicked':'Button is unclicked'}"/>

Tabbing does not work in mx:TileList component

I am using mx:Tilelist component to display set of textfields on screen, but when i try to traverse the fields through TAB foucs move out of the list. Please provide solution for this problem. Following is the code i am using
<mx:TileList id="tileList"
dataProvider="{collection}"
change="setCurrentIndex(tileList.selectedIndex);"
dataChange="setCurrentIndex(tileList.selectedIndex);"
columnCount="1"
columnWidth="345"
itemRenderer="components.InputParamIR"
rowHeight="30"
verticalScrollPolicy="auto"
horizontalScrollPolicy="auto"
backgroundColor="#EEEEEE"
dragEnabled="false"
dragMoveEnabled="true"
dropEnabled="true"
width="100%" height="100%"
itemClick="chartTileClick(event);"
/>
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.containers.Panel;
[Bindable]
public var index:uint;
[Bindable]
public var collection:ArrayCollection = new ArrayCollection();
[Bindable]
public var isVisible:Boolean ;
public function initEventsLocal(event:Event):void
{
this.initEvents(event);
collection = new ArrayCollection();
isVisible = false;
}
private function chartTileClick(event:ListEvent):void
{
event.currentTarget.tabFocusEnabled=true;
event.currentTarget.tabEnabled=true;
}
]]>
</fx:Script>
In Flex List Itemrenderer may not get the focus since it is non editable and it will not implement the focus manager interface, you need to implement IFocusManagerComponent in your item renderer components.InputParamIR also you have to override your TileList class to enable tab for childrens.
package
{
import mx.controls.TileList;
public class MyTileList extends TileList
{
override protected function createChildren():void {
super.createChildren();
this.listContent.tabChildren = this.tabChildren
this.listContent.tabEnabled = this.tabEnabled
}
}
}
Have a look in to these
Tile list item renderer text focus solved
Issues with keyboard navigation on list with custom renderer
i hope this will help you
happy coding...

Adobe Flex: How to periodically poll HTTP service?

I have an embedded system that serves JSON results via a CGI process. I'm trying to setup a Flex app. to periodically poll the server once per second and update the GUI. I'm trying the approach below using a timer, but I only get the initial result, subsequent updates are not made. What could be going wrong?
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"
creationComplete="application1_creationCompleteHandler(event)">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
<mx:HTTPService id="getPacketCounts" showBusyCursor="true" resultFormat="text"
url="http://10.1.10.28/cgi-bin/getpacketcounts"
requestTimeout="500"
result="getPacketCounts_resultHandler(event)"
fault="faultHandler(event)">
</mx:HTTPService>
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.events.FlexEvent;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
private var timer:Timer = new Timer(1000, 0);
private var counter:int;
protected function application1_creationCompleteHandler(event:FlexEvent):void
{
timer.addEventListener(TimerEvent.TIMER, timerListener);
timer.start();
}
private function timerListener(evt:Event):void {
label.text = "get http://10.1.10.28/cgi-bin/getpacketcounts";
getPacketCounts.send();
}
protected function getPacketCounts_resultHandler(event:ResultEvent):void
{
label.text = event.result.toString().substr(0, 60);
}
protected function faultHandler(event:FaultEvent):void
{
Alert.show("The server returned error code " + event.statusCode + ".", event.fault.faultString);
}
]]>
</fx:Script>
<s:Label id="label" text="v1.0"/>
</s:Application>
I can't see anything glaringly wrong with your code though I suspect the problem lies with your Timer getting out of sync with your HTTPService. Your Timer fires every second but it might take longer for your HTTPService to return a result and the next tick of your Timer tramples over the previous getPacketCounts.send() request. I'm not 100% sure about this though.
If I were writing this app I'd set it up so the Timer fired once, reset the Timer, sent of the HTTPService request, then waiting for a response before restarting the Timer.
// Make the Timer run once.
private var timer:Timer = new Timer(1000, 1);
// ....
// Add listeners to the Timer and start it
protected function application1_creationCompleteHAndler(event:FlexEvent):void
{
timer.addEventListener(TimerEvent.TIMER_COMPLETE, timerListener);
timer.start();
}
// Send the request
private function timerListener(e:TimerEvent):void
{
timer.reset();
// Your other stuff
}
protected function getPacketCounts_resultHandler(event:ResultEvent):void
{
timer.start()
// Your code
}
protected function faultHandler(event:FaultEvent):void
{
timer.start()
// Your code
}

Drag and Drop in Spark tilelist

I am trying to initiate a drag&drop on a spark tilelist so the user can re-order the list manually.
The problem is : each time i drap and drop, the dropped/dragged entry is duplicated.
My main application is :
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"
initialize="initApp()">
<fx:Script source="com/init.as" />
</s:Application>
Included as file is :
import com.Sequence;
import mx.collections.ArrayCollection;
import mx.core.ClassFactory;
import mx.core.FlexGlobals;
import spark.components.List;
import spark.layouts.TileLayout;
public var main:List=new List()
public var ok: ArrayCollection = new ArrayCollection( [
{label:"1-redblue", data:"redblue"},
{label:"2-ncview", data:"ncview"},
{label:"3-greyscale", data:"greyscale"},
{label:"4-alg2", data:"alg2"},
{label:"5-alg", data:"alg"},
{label:"6-occam", data:"occam"},
{label:"7-rainbow", data:"rainbow"},
{label:"8-sst_36", data:"sst_36"},
{label:"9-occam_pastel-30", data:"occam_pastel-30"},
{label:"10-ferret", data:"ferret"}
]);
// ActionScript file
public function initApp(){
var lay:TileLayout=new TileLayout()
var ae:ClassFactory=new ClassFactory(Sequence)
main.layout=lay
main.dataProvider=ok
main.dragEnabled=true
main.dropEnabled=true
main.width=FlexGlobals.topLevelApplication.width
main.height=FlexGlobals.topLevelApplication.height
main.itemRenderer=ae
this.addElement(main);
}
And my item renderer looks like :
package com
{
import mx.controls.TextArea;
import mx.events.FlexEvent;
import spark.components.BorderContainer;
import spark.components.supportClasses.ItemRenderer;
public class Sequence extends ItemRenderer
{
private var borderC:BorderContainer=new BorderContainer()
private var labeli:TextArea=new TextArea()
private var d:Object
public function Sequence()
{
super();
this.addElement(borderC)
this.addEventListener(FlexEvent.CREATION_COMPLETE,doIT)
borderC.width=borderC.height=100
labeli.width=labeli.height=100
borderC.addElement(labeli)
}
override public function set data(d:Object):void{
this.d=d
}
override public function get data():Object{
return d;
}
private function doIT(e:FlexEvent):void{
labeli.text =String(d.label);
}
}
}
The property that allows to drag/drop within the same component (without duplicating) is :
allowDragMove
if set to true, the duplication does not occurs.
#gpasse got me on the right track.
The following fields need to be set to true for a Spark List in Flex 4.6.
dragEnabled="true"
dragMoveEnabled="true"
dropEnabled="true"

Failing to import a class in ActionScript

Here is the error I get:
1046: Type was not found or was not a compile-time constant: fbAPI.
Here is my MXML:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="startGame();">
<mx:Script>
<![CDATA[
import fbAPI;
public function startGame():void {
var fbAPI:fbAPI = new fbAPI(); // breaks on this line
fbAPI.fbLogin();
}
]]>
</mx:Script>
</mx:Application>
And here is my fbAPI.as stub that doesn't seem to get imported:
package {
public class fbAPI {
import mx.controls.Alert;
public function fbLogin():void {
Alert.show('test');
}
}
}
Try putting your import statements above your class and also just rename the instance name of the fbapi in your mxml real quick.
Edit: nevermind, I forgot in AS3 you don't need a constructor.
Make sure you put the fbAPI.as file in the same location as your mxml file.