How we implement "Please wait ...." screen in flex when app is busy - apache-flex

I have a function that restores all of the default settings of my application. This process can take a bit of time, so I would like to implement a "Please wait..." modal popup to let the user know that everything is alright and the program hasn't frozen. Once the function completes its task, I'd like for it to remove the message, and resume normal behavior.
alt text http://www.freeimagehosting.net/uploads/c5906da30c.jpg

On start:
var waitingpopup:TitleWindow = new TitleWindow()
waitingpopup.title = "Please Wait ..."
PopupManager.addPopup(waitingpopup, this, true)
On complete:
PopupManager.removePopup(waitingpopup)

As long as you don't need to convey anything to the user other than "the app is still running", I think a more elegant method would be to just change the cursor:
mx.managers.CursorManager.setBusyCursor()
//do stuff
mx.managers.CursorManager.removeBusyCursor()
The cursor will change to a clock with spinning hands. I'm not sure if there's a way to override this with your own animation, but it's simple and doesn't require you to design your own window.

You can use the PopUpManager to create a Modal PopUp with an animated spinner. The Alert component does this. You can always reference the Alert source code to see how it works.

For those arriving late to this question, Adobe released a Throbber in 4.5:
http://www.adobe.com/cfusion/exchange/index.cfm?event=extensionDetail&loc=en_us&extid=1283019
http://fusiongrokker.com/post/using-the-flex-4-5-busyindicator
http://flexdevtips.blogspot.com/2011/05/simple-animating-preloader-and.html
For example, run the following from the fusiongrokker link above:
private function busyOn():void
{
throbberId.visible = true;
}
private function busyOff():void
{
throbberId.visible = false;
}
]]>
</fx:Script>
<s:VGroup width="100%"
paddingLeft="10"
paddingRight="10"
paddingTop="10"
paddingBottom="10">
<s:BusyIndicator
id="throbberId"
visible="false"
rotationInterval="{rotationInterval}" />
<s:Button
id="start"
click="busyOn()"
width="100%"
height="50"
label="start" />
<s:Button
id="stop"
click="busyOff()"
width="100%"
height="50"
label="stop" />
</s:VGroup>

Related

Component shows in Design view but not when the application is launched

This is what's happening:
I have a Tabnavigator with the following tab:
<s:NavigatorContent width="100%" height="100%" label="Add a logo" includeIn="loggedin">
<components:LogoSearch />
</s:NavigatorContent>
When I change the state to "loggedin" with following code:
protected function Login_getStateHandler(event:Event):void
{
this.currentState = "loggedin";
}
the navigatorContent shows but not the component "LogoSearch", in design view however it does show when I switch states.
There are no states defined in "LogoSearch" and should show...?
When I include the tabnavigator in "normal" aswell as "loggedin", then change the state to "loggedin", the component "LogoSearch" shows. When I only show the tabnavigator in "loggedin", change the state to "loggedin", the component "LogoSearch" doesn't show.
Any idea why this is happening? I'm no pro in flex at all so feel free to point me on my mistake. Thanks.
Tried working with invalidateDisplayList() and invalidateProperties() as suggested by Tianzhen Lin. Still nothing showing.
<s:NavigatorContent width="100%" height="100%" label="Add a logo" includeIn="loggedin" id="AddLogoTab" >
<s:Label text="test" id="test" />
</s:NavigatorContent>
And :
protected function Login_getStateRegisterHandler(event:Event):void
{
this.currentState = "register";
test.invalidateDisplayList();
test.invalidateProperties();
test.validateNow();
AddLogoTab.invalidateDisplayList();
AddLogoTab.invalidateProperties();
AddLogoTab.validateNow();
}
Whatever I do, the content of the NavigatorContent won't show after statechange.
To narrow down the problems you have, you may start by eliminating includeIn="loggedin" in your code, this would at least ensure that your component is showing properly.
Next, I would put a breakpoint at your Login_getStateHandler function, and see if it is ever called. If not, then it is somewhere in your wiring that the handler is not called. You may post more code here to get help.

Alert is triggered multiple times

The following code works in the following way:
When I enter incorrect values in the txtother.textbox and focuses out, an alert will be displayed as "Please enter a valid Format Mask." .
After pressing the "ok" button in the Alertbox the txtOther.focusout even is triggered again.
i.e. immediately after pressing the OK of alert, the same ALERT is displayed again.
I have added the code for ur reference:
//in mxml File:
<mx:Canvas label="General" >
<mx:VBox>
<mx:Canvas id="cvsGeneral">
<mx:TextInput id="txtOther" focusOut="txtOther_Validate();"/>
</mx:Canvas>
</mx:VBox>
</mx:Canvas>
<mx:Canvas width="100%" height="5%" horizontalScrollPolicy="off" verticalScrollPolicy="off">
<mx:HBox width="80%" height="100%" horizontalAlign="left">
<mx:Button width="64" label="Save" id="btnSave" click="btnSave_Click();" focusIn="txtOther_Validate();"/>
</mx:HBox>
</mx:Canvas>
//Validating action script is as follows:
public function txtOther_Validate():void{
var formatMask: String = null;
if(txtOther.editable && txtOther.enabled){
if(txtOther.text != ""){
formatMask = txtOther.text;
if(conditions to validate){
//some expression
}
if(formatMask.length < 12){
Alert.show("Please enter format mask with minimum 12 digits.");
txtOther.setFocus();
return;
} VariableEditControl.getInstance().validateFormatMask(txtOther.text,validateFormatMask_Result,validateFormatMask_Fault, validateFormatMask_Error);
}
}
}
public function validateFormatMask_Result(event:PLEvent): void {
var result:String = event.getData().toString(); // here lets assume that the result variable is stored as "FAILURE"
if(result == "FAILURE"){
Alert.show("Please enter a valid Format Mask.");
txtOther.setFocus(); //
}
}
I don't want to the alert to come again and again ..
I need it in such a way that when the ok button of alert is pressed. The txtother.text should be in focus, and the alert should not come again and again as before.
it's because you have the focusIn="txtOther_Validate();" on the ok button a second time. just remove the focusIn handler and you should be fine.
I may be in error but I think the alert box won't wait till you close it. So you trigger your validate and immediately set the focus back to the input. Now you click the alert box's ok button which will make the input lose the focus triggering the validation which will raise the alert which will... and so on.
EDIT:
stage.focus = txtOther;
This will works in as3... I don't know about flex.

How to Send Info From a Flex 3 Component?

I need some help with sending info from a component. I'm not sure how to proceed.
I'm using Alex Uhlmann's flip card class (Distortion Effects). I've got a card that has 3 faces. When the user clicks the button, it fires a change event, and in the main application, the change event calls a function, flipTo, that flips the card. The component is below:
<?xml version="1.0" encoding="utf-8"?>
<mx:Panel
xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
width="500"
height="400">
<mx:Metadata>
[Event("change", type="mx.events.Event")]
</mx:Metadata>
<mx:Script>
<![CDATA[
[Bindable]
public var backCaption:String;
]]>
</mx:Script>
<mx:Text id="myAnswer" htmlText="{backCaption}" width="100%" />
<mx:ControlBar height="40" width="100%" >
<mx:Button
x="20" y="400"
label="Flip"
click="dispatchEvent( new Event( Event.CHANGE ) );" />
</mx:ControlBar>
</mx:Panel>
The main application looks like:
<mx:Canvas id="homeStack" >
<mx:ViewStack id="flipViewStack2" x="200" y="150" >
<sides:FlipFace
id="frontFace2"
title="Newport"
change="flipTo(frontFace2, backFace2, DistortionConstants.LEFT, DistortionConstants.RIGHT);" />
<sides:FlipReverse
id="backFace2"
title="Newport: Answer"
change="flipTo(backFace2, anotherFace2, DistortionConstants.LEFT, DistortionConstants.LEFT);" />
<sides:FlipAnotherSide
id="anotherFace2"
title="Other Stuff"
change="flipTo(anotherFace2, frontFace2, DistortionConstants.RIGHT, DistortionConstants.LEFT);"/>
</mx:ViewStack>
</mx:Canvas>
<mx:Canvas id="OtherStack" >
(more code)
</mx:Canvas>
The flipTo function in the main application takes 4 parameters: the starting side, the ending side, and then two parameters that determine the direction of the flip.
Everything works great. If I hit the button, I can flip through all of the sides. But, I'd like to add a comboBox, so that the user can flip directly to the side that they want instead of having to cycle through all of the sides. (This is important as I plan to add more sides).
In the main application, please note that the sides have the number 2 in their ids. For example, frontFace2. I've got multiple sets of cards each with a different number, frontFace3, frontFace4, etc. The number determines which data is pulled from the database. (I've simplified the code for brevity).
How can I add a comboBox in the component that causes the card to flip to the selected side?
Do I need a custom event? (Unfortunately, I don't know anything about custom events). Is there a way to have the comboBox set a public variable and then somehow access that variable in the main application and call flipTo with the comboBox's chosen side? Other possibilities?
Any suggestions?
Thank you.
-Laxmidi
oh, yeah, you will need a custom event.
the custom event is your inheritance to the Event class which on it you can load more data, params, views and more.
in your case, things are a bit more simple but you will need to see what "face" the user selected and flip to it.
steps
1. create a custom event (inherit from event)
2. add a var to the event class that's called face
3. when the user selects the value from the combo, fill the face var with value and dispatch the event
4. listen to the event in the application level and then flipTo the relevant face.

Flex AS3: ComboBox set visible to false doesn't hide

I have a combobox in a view that receives information about application state changes, and then is supposed to show or hide it's children based on the whole application state.
It receives state change messages, it traces the correct values, it does what it's supposed to do, however, it just doesn't seem to work. Essentially, all it needs to do is hide a combobox during one state, and show it again during another state.
Here is the code:
public function updateState(event:* = null):void {
trace("Project Panel Updating State");
switch(ApplicationData.getSelf().currentState) {
case 'login':
this.visible = false;
break;
case 'grid':
this.visible = true;
listProjects.includeInLayout = false;
listProjects.visible = false;
trace("ListProjects: " + listProjects.visible);
listLang.visible = true;
break;
default:
break;
}
}
Here is the MXML:
<mx:HBox>
<mx:Button id="btnLoad" x="422" y="84" label="Load" enabled="true" click="loadProject();"/>
<mx:ComboBox id="listProjects"
x="652"
y="85"
editable="true"
change="listChange()"
color="#050CA8"
fontFamily="Arial" />
<mx:Label x="480" y="86" text="Language:" id="label3" fontFamily="Arial" />
<mx:ComboBox id="listLang"
x="537"
y="84"
editable="true"
dataProvider="{langList}"
color="#050CA8"
fontFamily="Arial"
width="107"
change="listLangChange(event)"/>
<mx:CheckBox x="830" y="84" label="Languages in English" id="langCheckbox" click='toggleLang()'/>
</mx:HBox>
It's not that clear form your code where and how the updateState function gets called, and to get any further into a solution I think I would need to see that. However, I think you may like to consider a different approach.
Have you tried using views instead of manually showing and hiding things and setting properties? I think you would have simpler code if you had a different view state for each of the cases in your switch, e.g. 'login' etc. Then all the showing hiding stuff becomes a design-time activity rather than run-time and all you have to do is set the current state.
If you matched your state names with your ApplicationData currentState values you may even be able to do away with the updateState function completely.
Have you tried changing
updateState(event:* = null):void
to this
updateState(event:Event = null):void
Im still looking into the event:* and everything I have found so far has Event instead of *. Will repost still looking

Waiting for Flex Effects to Finish

I'm a Flex rookie tasked with enhancing an existing application. One of those enhancements is getting the field that currently shows the time to smoothly fade back and forth between showing the time and the date.
I know the proper way to do this is to embed the font file in the application so I can fade the label in and out directly. I'm trying to avoid that if I can, since I'd prefer to make my changes as unobtrusive as possible.
I came up with what I felt was a reasonable workaround: create a "privacy screen" that just so happens to be the exact size, shape, and color of the clock's background; initialize its alpha to 0; then when changing the time/date, fade-in the privacy screen, make the change, and fade the screen back out again.
The code looks something like this:
var targets:Array = new Array();
targets.push(this.privacyScreen);
this.effectFadeIn.play(targets);
this.mylabel.text = "I am a date and/or time";
this.effectFadeOut.play(targets);
... with the key components looking like this:
<mx:Label text="" id="mylabel" width="100%" height="100%" x="0" y="0" color="0xff0000"/>
<mx:Canvas id="privacyScreen" width="100%" height="100%" x="0" y="0" alpha="1" backgroundColor="{myConfiguration.backgroundColor}"/>
<mx:Fade id="effectFadeIn" alphaFrom="0.0" alphaTo="1.0" duration="250"/>
<mx:Fade id="effectFadeOut" alphaFrom="1.0" alphaTo="0.0" duration="250"/>
As I'm sure the experienced Flex designers already know, this code is made from delicious fresh-squeezed FAIL. The basic assumption that execution will wait for the fade-in effect to finish is wrong, and the fade-out effect is apparently ignored while the fade-in is still in progress.
So I guess I have two related questions:
Is it possible to get execution to pause while waiting for an effect to run to completion?
Is this approach even viable, or does it simply reek of Doing It Wrong from top to bottom?
My thanks in advance for any insight anyone can offer.
(And I admit in advance that the more I try to learn this by doing, the more I realize I need to avail myself of some of the online training resources out there.)
I just played a bit with your code, is this what you're looking for?
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute"
creationComplete="onComplete();">
<mx:Script>
<![CDATA[
private var targets:Array = new Array();
private function onComplete():void {
targets.push(canv);
effectFadeOut.play(targets);
}
private function onFadeInEnd():void {
effectFadeOut.play(targets);
}
private function onFadeOutEnd():void {
effectFadeIn.play(targets);
}
]]>
</mx:Script>
<mx:Label text="{(new Date()).toString()}" id="lbl" x="0" y="0" color="0xff0000"/>
<mx:Canvas id="canv" width="100%" height="{lbl.height+5}" x="0" y="0" backgroundColor="#000000"/>
<mx:Fade id="effectFadeIn" alphaFrom="0.0" alphaTo="1.0" duration="250"
effectEnd="onFadeInEnd();" />
<mx:Fade id="effectFadeOut" alphaFrom="1.0" alphaTo="0.0" duration="250"
effectEnd="onFadeOutEnd();" />
</mx:WindowedApplication>
Hope that helps :)
Your code is executed while the label fades. this.effectFadeIn.play () does not wait for it to finish. I would add a setTimeout call to the lines of code you need to call later, or better yet, put them in another function. Then, call the function again after a certain interval.
import flash.utils.*;
private function FadeIn () : void {
var targets:Array = new Array();
targets.push(this.privacyScreen);
this.effectFadeIn.play(targets);
this.mylabel.text = "I am a date and/or time";
setTimeout (function (): void {FadeOut (targets);}, effectFadeIn.duration); // Function and duration
}
private function FadeOut (targets : Array) : void {
this.effectFadeOut.play(targets);
setTimeout (FadeIn (), this.effectFadeOut.duration;
}
I'm pretty sure this should work...

Resources