ComboBox in AS3 'eats' last letter - actionscript-3

I have a problem with flash component ComboBox. When i wont to save a name in ComboBox its always without last letter!?
Here is the code:
var input_name:String;
text_field.addEventListener (TextEvent.TEXT_INPUT, text_input);
button.addEventListener (MouseEvent.CLICK, save);
function save (e:MouseEvent):void
{
text_field.visible = true;
text_field.adddEventListener(KeyboardEvent.KEY_DOWN, save_text);
}
function text_input(e:TextEvent):void
{
input_name = text_field.text;
}
function save_text(e:KeyboardEvent):void
{
var keyPressed:String = e.keyCode.toString();
if (keyPressed == "13")
{
combo.addItem({label:input_name, data:input_name});
}
}
So when i enter 'foo' in text field and press ENTER it saves in combobox just 'fo'...
Thx for answers :)

TextEvent.TEXT_INPUT is dispatched before the value has changed.
Event.CHANGE is dispatched after the value has changed.
This will work, including handling the enter key.
import flash.events.MouseEvent;
import flash.events.Event;
var input_name:String;
text_field.addEventListener(Event.CHANGE, text_input);
text_field.addEventListener("enter", save);
button.addEventListener(MouseEvent.CLICK, save);
function text_input(e:Event):void
{
input_name = text_field.text;
}
function save(e:*):void
{
text_field.visible = true;
combo.addItem({label:input_name, data:input_name});
}

Related

AS3 - Buttons do not work upon reentering frame

I've set up three buttons in the first frame which are supposed to switch frames. When the program first runs, there are no errors, and i can click any of the buttons and end up where I want. However, when going back to the first frame, the buttons no longer work. The stage listener still works though. I added the "Clicked" output to check if the function was called, which it wasn't. I know I disable the buttons in the code, but only after that button is clicked, and the task is done. I should mention I don't have the code on the timeline, but on a separate document. Here is my code:
package{
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.display.SimpleButton;
public class DocumentClass extends MovieClip
{
public var matteOppgave:Boolean = false;
public var engelskOppgave:Boolean = false;
public var flaggOppgave:Boolean = false;
public function DocumentClass()
{
stop();
btnBok.addEventListener(MouseEvent.CLICK, matte);
btnFlagg.addEventListener(MouseEvent.CLICK, flagg);
btnPc.addEventListener(MouseEvent.CLICK, engelsk);
stage.addEventListener(Event.ENTER_FRAME, sjekk);
btnBok.enabled = true;
btnPc.enabled = true;
btnFlagg.enabled = true;
function matte(evt:MouseEvent)
{
gotoAndStop(2);
frame2();
trace("Clicked");
}
function engelsk(evt:MouseEvent)
{
gotoAndStop(3);
frame3();
trace("Clicked");
}
function flagg(evt:MouseEvent)
{
gotoAndStop(4);
frame4();
trace("Clicked");
}
function sjekk(evt:Event)
{
if(matteOppgave == true && engelskOppgave == true && flaggOppgave == true)
{
gotoAndStop(5);
}
if(matteOppgave == true)
{
btnBok.alpha = 0.5;
btnBok.enabled = false;
låsEin.alpha = 0;
}
if(engelskOppgave == true)
{
btnPc.alpha = 0.5;
btnPc.enabled = false;
låsTo.alpha = 0;
}
if(flaggOppgave == true)
{
btnFlagg.alpha = 0.5;
btnFlagg.enabled = false;
låsTre.alpha = 0;
}
}
}
I got it working from a solution posted on another forum. I made the five frames i had into movieclips, and changed back and forth using addChild() and removeChild().

Basic AS 3.0 query

What is the best way to navigate through an actionscript swf using arrows?
set the tabIndex property of the TextInput. That should allow you to tab through the form.
It is inadvisable to override the default functionality for arrow keys because they are used to move the text insertion point within the textInput
As for enter, you'll have to listen for the keyUp event and, if you detect an enter key, move to the next field.
//add this eventlistener for each textbox (through a loop or manually)
t.addEventListener(KeyboardEvent.KEY_UP, k);
//The event handler
protected function k(e:KeyboardEvent):void {
if(e.keyCode==Keyboard.ENTER) {
focusManager.getNextFocusManagerComponent().setFocus();
}
}
EDIT
For Flash CS5, this code should work:
import flash.events.KeyboardEvent;
import fl.managers.FocusManager;
import flash.display.InteractiveObject;
import fl.managers.IFocusManagerComponent;
import fl.managers.IFocusManager;
t1.addEventListener(KeyboardEvent.KEY_UP, k);
t1.tabIndex=1;
t2.tabIndex=2;
var fm:FocusManager=new FocusManager(this);
t1.tabEnabled=true;
t2.tabEnabled=true;
function k(e:KeyboardEvent):void {
if(e.keyCode==Keyboard.ENTER) {
var fx:InteractiveObject = fm.getNextFocusManagerComponent();
fm.setFocus(fx);
}
}
important: first drag a component from the "User Interface" group onto the stage and delete it. This should put all the required components in the library ready for you to use
EDIT2
Change
for(var i:int=0; i < textbox.length; i++) {
//textbox[i].buttonMode = true;
//box[i].addEventListener(MouseEvent.CLICK, myclick_ftn);
//box[i].addEventListener(FocusEvent.FOCUS_IN,textInputHandler);
//box[i].addEventListener(FocusEvent.FOCUS_OUT,textInputHandlerOut);
textbox[i].restrict = "0-9";
textbox[i].addEventListener(KeyboardEvent.KEY_UP, k);
textbox[i].tabIndex=i;
//t2.tabIndex=2;
//textbox[i].tabEnabled=true;
var fm:FocusManager=new FocusManager(this);
function k(e:KeyboardEvent):void {
if(e.keyCode==Keyboard.ENTER) {
var fx:InteractiveObject = fm.getNextFocusManagerComponent();
fm.setFocus(fx);
}
}
//t2.tabEnabled=true;
}
in your code to this:
var fm:FocusManager=new FocusManager(this);
function k(e:KeyboardEvent):void {
if(e.keyCode==Keyboard.ENTER) {
var fx:InteractiveObject = fm.getNextFocusManagerComponent();
fm.setFocus(fx);
}
}
for(var i:int=0; i < textbox.length; i++) {
//textbox[i].buttonMode = true;
//box[i].addEventListener(MouseEvent.CLICK, myclick_ftn);
//box[i].addEventListener(FocusEvent.FOCUS_IN,textInputHandler);
//box[i].addEventListener(FocusEvent.FOCUS_OUT,textInputHandlerOut);
textbox[i].restrict = "0-9";
textbox[i].addEventListener(KeyboardEvent.KEY_UP, k);
textbox[i].tabIndex=i;
//t2.tabIndex=2;
//textbox[i].tabEnabled=true;
}

I am trying to test if a text input box has focus

I am fairly new to AS3, so here is my problem.
I have two text input boxes p1 and p2. I want to do a conditional test to see if p1 has the focus. If it does not, then p2 must have the focus. Here is some code I am trying to get to work.
if ((Selection.getFocus()) == (p1totalScore.text)){
p1Score();
} p2Score();
Thanks for your help.
David
Without a FocusManager, you could test what the stage is returning for focus:
(If you have textInput1 and textInput2 on the art-board)
import flash.events.MouseEvent;
import fl.controls.TextInput;
var textInput1:TextInput;
var textInput2:TextInput;
stage.addEventListener(MouseEvent.CLICK, mouseClickHandler);
function mouseClickHandler(event:MouseEvent):void
{
if(stage.focus == textInput1.textField)
trace("text field 1 has focus.");
else if(stage.focus == textInput2.textField)
trace("Text field 2 has focus.");
}
I think a better approach than you're attempting is to add event handlers for focus change:
import fl.controls.TextInput;
import fl.managers.FocusManager;
import flash.events.FocusEvent;
var textInput1:TextInput;
var textInput2:TextInput;
var focusManager:FocusManager = new FocusManager(this);
textInput1.addEventListener(FocusEvent.FOCUS_IN, textInput1FocusHandler);
textInput2.addEventListener(FocusEvent.FOCUS_IN, textInput2FocusHandler);
function textInput1FocusHandler(event:FocusEvent):void
{
trace("textInput1 has focus.");
}
function textInput2FocusHandler(event:FocusEvent):void
{
trace("textInput2 has focus.");
}
Adobe will get you 99% of the way:
'http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/fl/managers/FocusManager.html'
I just changed the function to return the name of the control that has focus, instead of the instance name that their example returns.
private function focusChange(e:FocusEvent):void {
var ti_now:InteractiveObject;
ti_now = fm.getFocus();
trace("Focus now: ", ti_now.name);
}

Resolving a 1069 error between a child object and a parent function

I've shortened the code samples below so that it's more readable. Here's the rub:I create a whole bunch of MovieClips containing the letters a-z. These MovieClips are children of a parent MovieClip called "levelTwo", where levelTwo is a kind of a logic manager for the level.
When they're clicked, they send off some data to levelTwo for evaluation (It's Hangman). Problem is that on click I get a 1069 error. It WAS a 1061 error until I added the event.target.parent bit in LetterButton.
Here's the relevant code:
package {
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.events.Event;
public class LetterButton extends MovieClip {
var buttonText:String;
public function LetterButton(lText:String,objX:int,objY:int)
{
trace ("Creating new button");
x = objX;
y = objY;
buttonText = lText;
letterText.text = buttonText;
this.stop();
addEventListener(MouseEvent.MOUSE_OVER,onMouseOver);
addEventListener(MouseEvent.MOUSE_OUT,onMouseOut);
this.addEventListener(MouseEvent.CLICK,onMouseClick);
}
private function onMouseOver(event:Event):void
{
gotoAndStop(2);
letterText.text = buttonText;
//trace ("You're over me and my text is " + buttonText);
}
private function onMouseOut(event:Event):void
{
gotoAndStop(1);
letterText.text = buttonText;
//trace ("You're out of me and my text is " + buttonText);
}
private function onMouseClick(event:Event):void
{
trace ("I am clicked and I am " + buttonText);
event.target.parent.checkGuess(buttonText);
}
}
}
And the relevant bit from levelTwo:
public function checkGuess(guess:String):void
{ //Check to see if the guess matches the string
trace ("Guess: "+guess);
for(var i:int=0;i<answer.length;i++)
{
if(guess == answer.charAt(i))
{
censoredAnswer[i] = guess;
trace ("Got one right");
answerField.text = answerRedisplay(); //Do it now or it won't update for the check
}
}
if (answerField.text == answer)
{
setWin();
}
}
I see no magic here. You subscribe to LetterButton instance, so you get event.target reference pointing to it.
I think a better approach would be to subscribe to parent clip, that contains all the LetterButton instances. MouseEvent.CLICK is a bubbling event, so you will get your handler triggered on parent every time something is clicked inside it.
See the sample code.
// inside level two class
addEventListener(MouseEvent.CLICK,onMouseClick);
private function onMouseClick(event:MouseEvent):void
{
var target:LetterButton = event.target as LetterButton;
if (target == null) {
return;
}
// here we know, that some LetterButton instance was clicked
// and target var holds it's reference
// either make buttonText public, or create a getter/accessor
// var text:String = target.buttonText;
var text:String = target.getButtonTextSomehow();
checkGuess(text);
}

Why does the button stay selected?

I'm doing a simple 2 button menu. Each button is a movie clip with 3 labels for the states "none" "selected" and "hover". smartBtn needs to be set to "selected" on enter frame. When cinemaBtn gets clicked, smartBtn should go to its "none" state. But I'm not sure why smartBtn keeps on being selected.
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
var smartBtn = menu_mc.smart_mc;
var cinemaBtn = menu_mc.cinema_mc;
smartBtn.buttonMode = true;
cinemaBtn.buttonMode = true;
this.addEventListener(Event.ENTER_FRAME, EnterFrameHandler);
smartBtn.addEventListener(MouseEvent.CLICK, menuSmartClick);
cinemaBtn.addEventListener(MouseEvent.CLICK, menuCinemaClick);
function EnterFrameHandler(event:Event):void {
smartBtn.gotoAndStop("selected");
}
function menuSmartClick(e:MouseEvent) {
smartBtn.gotoAndStop("selected");
smartBtn.buttonMode = false;
cinemaBtn.gotoAndStop("none");
cinemaBtn.buttonMode = true;
}
function menuCinemaClick(e:MouseEvent) {
cinemaBtn.gotoAndStop("selected");
cinemaBtn.buttonMode = false;
smartBtn.gotoAndStop("none");
smartBtn.buttonMode = true;
}
ENTER_FRAME is fired at the begining of each frame, so smartBtn will be set to "selected" state every time even if you set it to "none" state.
Remove EnterFrameHandler call or add a test like this :
function EnterFrameHandler(event:Event):void {
if(cinemaBtn.currentFrameLabel != "selected")
smartBtn.gotoAndStop("selected");
}