I am working on a AS3 only project in Flex....I tried to listen ENTER event when use clicks enter/return in my textinput box....but it seems not working well...I did try using TextEvent.TEXT_INPUT and it worked fine but not Component.ENTER...any help??? Thanks a lot!!
import fl.events.ComponentEvent;
searchInput=new TextField();
searchInput.type=TextFieldType.INPUT;
searchInput.background=true;
searchInput.backgroundColor=0xecffee;
searchInput.defaultTextFormat=TF;
searchInput.width = 200;
searchInput.height=16;
searchInput.x=50;
searchInput.y=180;
addChild(searchInput);
searchInput.addEventListener(ComponentEvent.ENTER, testEnter);
}
private function testEnter(e:ComponentEvent):void{
if(searchInput.text!=null){
beginSearch(searchInput.text);
}
searchInput.selectable = true;
and maybe
searchInput.mouseEnabled = true;
try this then:
searchInput.addEventListener(MouseEvent.CLICK, testEnter);
private function testEnter(event:MouseEvent):void
{
}
sorry, i was bit too quick on that one...
here it is
searchInput=new TextInput();
TextField doesn't extend the UIComponent class , therefore it can't handle ComponentEvent. Instead of telling you to change the event , I should have told you to change the event handler. My understanding is that you write AS3 projects with Flex so I looked at the TextField first!
I'm not sure if you can use the TextInput class in an AS3 project since it's part of the Flex framework...
in which case you may have to revert to the MouseEvent but not triggered by the TextField though but by a simple 'Search' button
The event you're looking for is 'change' / flash.events.Event.CHANGE which is dispatched when the control value is modified. The flex documentation is quite helpful here: Flex 3 TextInput
If you want to listen to the user pressing ENTER you should use the keyDown-event. Otherwise (like also mentioned) you can use the change-event.
As you are using the TextField-component the right documentation is link text
The TextInput-component has also an valueCommit-event, maybe you can use this one...
Related
I'm getting a Flex ArgumentError: Error #2025: The supplied DisplayObject must be a child of the caller.
This is what I've got:
a) I set the variable lastButtonClicked to the last button that was clicked in the main app.
private var lastButtonClicked:DisplayObject;
private function lastButtonClickedFunction(event:MouseEvent):void {
lastButtonClicked = event.currentTarget as DisplayObject;
}
b) I have a TitleWindow open and there is a yes/no option. I have a custom event return the answer to the main app.
c) In the main app, I'm trying to remove lastButtonClicked based on the data sent by the custom event. So, my problem is in this function. For some reason it won't let me remove the button. I get Error 2025 instead.
private function answerHandler( event:AnswerEvent ):void {
if(event.answerCorrect == true){
removeChild(lastButtonClicked);
}
}
Any suggestions on how to debug this problem? The custom event is firing okay. How do I fix this line: removeChild(lastButtonClicked); ?
Edit: I tried hbox1.removeChild(lastButtonClicked) and it worked. The proper button was removed from the main app. The problem is that not all of the buttons are in hBox1. I've got other HBoxes. So, I need to figure out a more generic way instead of using hBox1 in the statement. I tired this.removeChild(lastButtonClicked), but it didn't work. Thank you.
Thank you.
-Laxmidi
From what I understand, it seems like you have the buttons in a TitleWindow and the event handler in the application. You probably want to call removeChild for the instance of TitleWindow (eg: titleWindow.removeChild(lastButtonClicked) ) rather than from the application.
I solved it. I made a variable and set it to the parent of lastButtonClicked.
private var myParent:Object;
myParent = lastButtonClicked.parent;
Then in my answerHandler I wrote:
myParent.removeChild(lastButtonClicked);
Thank you.
-Laxmidi
I have a flex app with lots of nested views and popup windows..
I'd love to catch all the CHANGE events in the application at the top level.. all of them, simply to notify the user that he has changed something (trust me it makes sense in my app).
Now, I tried to add an event listener in the Application creationComplete handler like this:
private function init():void {
this.addEventListener(flash.events.Event.CHANGE, function f():void {...})
}
but it does not work.. why? I read in the docs that event bubbling for the CHANGE event is set to false before dispatching. How can I change that? Is there any other way to achieve my goal?
thanks
Try listening to events on the SystemManager instead of the Application. As far as I understand, SystemManager sits at the very top of the display list, adding the application, popups and other UI entities as children.
In Flex 3 and below, you can retrieve it via Application.application.systemManager.
Read more on the SystemManager on Deepa's blog:
http://iamdeepa.com/blog/?p=11
I am also having trouble with a group of TextArea controls where I would like to listen for the change event on their container (parent) instead.
What I did in the end was to extend the TextArea class and create a listener for the change event. From the listener I would then dispatch a custom event that could bubble.
public class BubblingTextArea extends TextArea
{
public function BubblingTextArea()
{
super();
addEventListener(TextOperationEvent.CHANGE, changeHandler);
}
private function changeHandler(event:TextOperationEvent):void
{
dispatchEvent(new ChangeBubbleEvent(ChangeBubbleEvent.BUBBLE_CHANGE));
}
}
The custom event:
public class ChangeBubbleEvent extends Event
{
public static const BUBBLE_CHANGE:String = "bubbleChange";
public function ChangeBubbleEvent(type:String, bubbles:Boolean=true, cancelable:Boolean=false)
{
super(type, bubbles, cancelable);
}
}
I am sure someone can come up with a more elegant solution since I am still quite new to Flex and AS3 myself.
As far as I know, PopUps happen outside of the Application's main displayList, so that's probably why you're not seeing bubbling. In this case, you'll need to manually add listeners to popups. The Flash change event does bubble according to the docs: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/events/Event.html#CHANGE
I personally like to use a framework such as RobotLegs or Parsley.
The basic idea is that each view and popup gets a mediator. The mediator's job is to communicate between the view and the command/model. Those mediators can listen directly to the view and the view's components.
I am creating a canvas in actionscript like :
private var cvs_preview:Canvas = null;
private function show_preview():void
{
this.cvs_preview = new Canvas();
this.cvs_preview.id = "cvs_preview_1";
this.cvs_preview.setStyle('backgroundColor', 0x000000);
this.cvs_preview.setStyle('backgroundAlpha', 1);
this.cvs_preview.setStyle('borderColor', 0x417FDD);
this.cvs_preview.setStyle('cornerRadius', 10);
this.cvs_preview.setStyle('borderStyle', 'solid');
this.cvs_preview.setStyle('dropShadowEnabled', true);
var pt:Point = image.localToGlobal(new Point(image.x, image.y));
this.cvs_preview.x = pt.x - 50;
this.cvs_preview.y = pt.y - 50;
this.cvs_preview.height = 200;
this.cvs_preview.width = 250;
//this.cvs_preview.addEventListener(FlexEvent.CREATION_COMPLETE, get_focus_on_canvas);
//this.cvs_preview.focusManager.setFocus(
//this.cvs_preview.addEventListener(MouseEvent.CLICK, end_preview_on_focus_change);
this.cvs_preview.addEventListener(FocusEvent.MOUSE_FOCUS_CHANGE, end_preview_on_focus_change);
Application.application.addChild(this.cvs_preview); //add as top-most visible container
btn_mini_preview.enabled = false;
}
So on the focus change i want to run the "end_preview_on_focus_change()"
but this is not working.
As per my understanding, i think the canvas not getting any focus in the first place. I was trying to use focusManager.setFocus to do that after the canvas's creation complete. but even that is giving me an error.
the code i was trying on Creation.Complete is :
private function get_focus_on_canvas(e:FlexEvent)
{
focusManager.setFocus(e.target);
//Alert.show("testing img complete");
}
this is giving me an error "1118: Implicit coercion of a value with static type Object to a possibly unrelated type mx.managers:IFocusManagerComponent."
basically i just want to use the focus out event of the canvas.
Can someone help me with this...
I have been on this issue since a long time.
Regards
Zeeshan
The error is correct. You have an object of type Object which you are trying to use as an IFocusManagerComponent. This will not work. To accomplish that line of code, you need to do something like
focusManager.setFocus( IFocusManagerComponent( e.target ) );
This, of course, assumes that the target implements IFocusManagerComponent. It will give you an error otherwise (and likely will in this case because Canvas is not listed as an IFocusManagerComponent). The good news is that Canvas does have a drawFocus method which will accomplish the same thing.
As to your MOUSE_FOCUS_CHANGE event, that will only be fired if an object already HAS focus and then loses it. I think you are better off using FlexEvent.CREATION_COMPLETE. This will ensure that the component has registered itself with all of the appropriate classes in the Flex SDK so that the FocusManager can even be aware of the new object. Whatever you do, do not try to set focus on something which has not been added to the stage (ie: Event.ADDED has been called).
As another piece of advice -- Event.ADDED bubbles, make sure that event.currentTarget == event.target to make sure that you are listening to the correct object. Otherwise, you might be calling the same function multiple times erroneously.
Only a few classes implement IFocusManagerComponent as others mentioned and Canvas is not one of them. If you really must call FocusManager.setFocus() you will have to extend the canvas class to implement this interface and use that class instead. You don't have to write any methods to implement this interface, all methods have already been implemented by UIComponent itself
//FocusableCanvas.as (include appropriate package and import statements)
public class FocusableCanvas extends Canvas implements IFocusManagerComponent
{
public function FocusableCanvas()
{
super();
}
}
//Now use this class instead of Canvas
this.cvs_preview = new FocusableCanvas();
//setFocus in creation complete handler
FocusManager.setFocus(IFocusManagerComponent(e.target));
But if all you want to do is to set focus on the canvas upon it's creation, you can call canvas.setFocus() from the creationComplete handler instead.
private function get_focus_on_canvas(e:FlexEvent)
{
Canvas(e.currentTarget).setFocus();
trace("done");
}
I see two problems, and no perfect solutions. With any luck, this can help you out.
First of all, e.target returns an object typecast with type Object. This explains your implict coercion error, because Object does not implement IFocusManagerComponent.
Second, iFocusManagerComponent is only implemented by Accordion, AdvancedListBase, Button, ButtonBar, ChartBase, ComboBase, DateChooser, DateField, HTML, ListBase, MenuBar, NumericStepper, TabNavigator, TextArea, TextInput, UIMovieClip as per this entry in the Flex 3.4 AS3 Reference.
This leads me to believe that a Canvas element cannot take focus and has simply inherited access to the FocusManager through inheritance of UIComponent.
The only solutions I can see are to utilize something other than Canvas to handle your focus related concerns, or subclass Canvas and implement iFocusManagerComponent, though that looks fairly complex.
Edit
Apologies for missing drawFocus in the above solution.
Please try;
private function get_focus_on_canvas(e:FlexEvent)
{
this.cvs_preview.setFocus();
}
I have set the itemRollOver and itemRollOut event listeners on a List component, but whenever I roll the mouse over a list item, both the over and out events of the same list item fire in succession right after each other. My list uses a custom itemRenderer.
Any ideas why this might be? The Adobe documentation doesn't provide much insight into this (not surprisingly...).
In my opinion this is a bug. The ListBase.mouseOverHandler now sets a variable called lastHighlightItemRendererAtIndices when it dispatches an ITEM_ROLL_OVER event, which is then used (together with lastHighlightItemIndices) when dispatching an ITEM_ROLL_OUT event in ListBase.clearHighlight (called by the mouseOutHandler).
The problem is that when you mouse from row-to-row the mouseOverHandler is called first, setting the lastHightlight... variables, and then when the mouseOutHandler gets called subsequently, it uses the lastHighlight... values that were just set with the result that you get consecutive 'roll over' and 'roll out' events for the same renderer.
Frankly I don't know why ListBase.clearHighlight just doesn't use the passed in renderer when dispatching the ITEM_ROLL_OUT event (which is how it used to work in SDK 2) as this is the actual renderer that is being 'rolled out of'.
Are they coming from the same object?
If not you will it is likely so that you will get an itemRollOut from the "item" you just left and a itemRollOver from the new one you entered, depending on their spacing and such these may fire very close to each other.
Make sure you are setting super.data in your item renderer if you are overriding set data().
ListBase listens for MOUSE_OVER and then figures out the item underneath it based on coordinates of mouse and the position of the item renderer. You could check ListEvent.itemRenderer to see which renderer's roll over and roll out are firing and in what order.
Worst case, you could listen for rollOver and rollOut inside your item renderer.
Had the same problem. super.data was already being set, and the item is the same for the rollOut and rollOver event. I ended up opting for anirudhsasikumar's worst case scenario, and listened for rollOver and rollOut inside the item renderer. Seems to work fine.
I was having this same issue. I ended up subclassing the mx.controls.List class and overriding the clearHighlight function. As far as I can tell, the lastHighlightItemIndices variable is only ever read in that function. So doing something like the following fixed this issue:
import mx.core.mx_internal;
use namespace mx_internal;
public class List extends mx.controls.List
{
public function List()
{
super();
}
override mx_internal function clearHighlight( item:IListItemRenderer ):void
{
var uid:String = itemToUID( item.data );
drawItem( UIDToItemRenderer( uid ), isItemSelected( item.data ), false, uid == caretUID );
var pt:Point = itemRendererToIndices( item );
if( pt )
{
var listEvent:ListEvent = new ListEvent( ListEvent.ITEM_ROLL_OUT );
listEvent.columnIndex = item.x;
listEvent.rowIndex = item.y;
listEvent.itemRenderer = item;
dispatchEvent( listEvent );
}
}
}
Then just use this List class instead of the Adobe one and you'll have the behavior you expect. I tested this against Flex SDK 3.2 and it works.
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:controls="com.example.controls.*">
[ other code ... ]
<controls:List itemRollOver="onItemRollOver( event )" itemRollOut="onItemRollOut( event )" />
</mx:Canvas>
Thanks to Gino Basso for the idea in the post above. Hope that helps.
Thanks for the solution. That really solved the problem! Small correction, though:
listEvent.columnIndex = item.x;
listEvent.rowIndex = item.y;
should be
listEvent.columnIndex = pt.x;
listEvent.rowIndex = pt.y;
item.x and y hold the coordinate of the renderer in pixels.
I have a DataGridColumn with an ItemRenderer that extends the Box component. The default display is a Text component. When the user clicks on the text component, I change the State to add a PopUpMenuButton child, and make the Text component invisible. This works fine. However, I only want to allow one PopUpMenuButton to be visible in the DataGrid at a time (similar to how an itemEditor works). I don't want to use an itemEditor, because I've run into too many problems trying to get that to work in this instance.
I am implementing IDropInListItemRenderer in my itemRenderer, in order to access the listData property, which will give me the owner (DataGrid), but I don't know how to "turn off" the "editing" state in other itemRenderers in the DataGrid.
How can I accomplish this?
Thanks.
Here we go. I simply added an Listener for Change Events in the listData.owner - if it is triggered, I update the currentState to null. Works like a charm. Much easier than trying to access the itemRenderers in the column and resetting them all. Better on performance too.
private function label_clickHandler():void
{
showEditor();
}
private function showEditor():void
{
this.currentState = "editingMode";
var ownerListBase:ListBase = ListBase(listData.owner);
ownerListBase.addEventListener(ListEvent.CHANGE, ownerListBase_changeHandler);
}
private function ownerListBase_changeHandler(event:ListEvent):void
{
this.currentState = null;
var ownerListBase:ListBase = ListBase(listData.owner);
ownerListBase.removeEventListener(ListEvent.CHANGE, ownerListBase_changeHandler);
}