AS3: How to dispatch event from actionscript class - apache-flex

I have small chess application which consists of cells and boards. When user moves an item to the board, I want the board cell to dispatch an event so Board can listen to it and call a listener
public class BoardCell extends Canvas
{
public function Sample():void
{
....Some code
var e:Event = new Event("newMove")
dispatchEvent(e);
}
}
However, I can't catch the event in parent chess board class (Not sure that I listen for it correctly)
public class FrontEndBoard extends ChessBoard
{
private var initialPoition:String;
public function FrontEndBoard()
{
//TODO: implement function
this.addEventListener(Event.ADDED_TO_STAGE, addedToStage);
this.addEventListener("newMove", moveEvent);
super();
}

you have 2 options :
1) instead of this.addEventListener("newMove", moveEvent); do BoardCell.addEventListener("newMove", moveEvent);
2) have the event buble up to the parent ( assuming BoardCell is a display child of FrontEndBoard , you set it as a parameter in the event constructor )
var e:Event = new Event("newMove",true) .

I'm not sure how exactly FrontEndBoard and BoardCell are hierarchically in your application, but you may need to tell the "newMove" event that it can bubble.
var e:Event = new Event("newMove", true);

The event you dispatch from the BoardCell class should bubble, so it is caught in any parent classes. Check the constructor arguments of the Event class where you can set the "bubbles" flag to true.

Related

Connecting flex and weborb?

im a newbie in flex. Im have a question :)
I have
[Bindable]
private var model:AlgorithmModel = new AlgorithmModel();
private var serviceProxy:Algorithm = new Algorithm( model );
In MXML
private function Show():void
{
// now model.Solve_SendResult = null
while(i<model.Solve_SendResult.length) //
{
Draw(); //draw cube
}
}
private function Solve_Click():void
{
//request is a array
Request[0] = 2;
Request[1] = 2;
Request[2] = 3;
serviceProxy.Solve_Send(request);
Show();
}
<s:Button x="386" y="477" label="Solve" click="Solve_Click();"/>
And when i call serviceProxy.Solve_Send(request); with request is array and i want use model.Solve_SendResult in my code flex to draw many cubes use papervison3d but in the first time i received model.Solve_SendResult = null . But when I click again then everything OK.
Anyone help me? Thanks?
The model.Solve_SendResult object contains a result of the executed serviceProxy.Solve_Send(request) method. The Solve_Send will be executed asynchronously and as a result, at the moment when you fire the show method the Solve_SendResult object may be still null.
As a solution, you can use the following:
Create a custom event
package foo
{
import flash.events.Event;
public class DrawEvent extends Event
{
public static const DATA_CHANGED:String = "dataChanged";
public function DrawEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false)
{
super(type, bubbles, cancelable);
}
}
}
In your Algorithm class define the following:
[Event(name=DrawEvent.DATA_CHANGED, type="foo.DrawEvent")]
public class Algorithm extends EventDispatcher{
//your code
In the Solve_SendHandler method of the Algorithm class add the following
public virtual function Solve_SendHandler(event:ResultEvent):void
{
dispatchEvent(new DrawEvent(DrawEvent.DATA_CHANGED));
//your code
}
In your MXML class create onLoad method and add an event listener to an instance of the Algorithm class as it shown below:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" initialize="onLoad()">
public function onLoad():void
{
serviceProxy.addEventListener(DrawEvent.DATA_CHANGED, onDataChanged);
}
private function onDataChanged(event:DrawEvent):void{
while(i<model.Solve_SendResult.length) //
{
Draw(); //draw cube
}
}
make the following changes in the Solve_Click() method:
private function Solve_Click():void
{
//request is a array
Request[0] = 2;
Request[1] = 2;
Request[2] = 3;
serviceProxy.Solve_Send(request);
}
That is it! So, basically the code above do the following: you added a listener to your service (algorithm class), and the listener is listening for the DrawEvent.DATA_CHANGED event. The DrawEvent.DATA_CHANGED will be dispatched when your client receive a result of the Solve_Send invocation. Thus, the onDataChanged will draw your cube or do whatever you want :)
The approach above is basic and you have to know how events work in flex and how you can deal with it. Additional information is available here:
http://livedocs.adobe.com/flex/3/html/help.html?content=createevents_3.html
http://livedocs.adobe.com/flex/3/html/help.html?content=events_07.html
Regards,
Cyril

ItemClick Event in a flex Combobox

Does anyone know, is there any way to catch ItemClick Event in a Flex ComboBox (or anything similar). Maybe there's any trick .. :) I do realize, that I can customize it, but this not suits my case.
Thanks for your time :)
As you can see in mx:ComboBox sources, the function, creating the dropdown list, is private, the listener to ITEM_CLICK is private and the list itself is also private:
private var _dropdown:ListBase;
private function getDropdown():ListBase
{
// ...
_dropdown = dropdownFactory.newInstance();
// ...
_dropdown.addEventListener(ListEvent.ITEM_CLICK, dropdown_itemClickHandler);
// ....
}
private function dropdown_itemClickHandler(event:ListEvent):void
{
if (_showingDropdown)
{
close();
}
}
So you can not even extend ComboBox.
The only public thing is dropdownFactory, which theoretically can be overriden to somehow register the created dropdown list or create extended list. But the problem I see is that ComboBox is not the parent of dropdown list - PopupManager is. This can make dispatching (bubble) events quite difficult.
I think the following document will be helpful
ItemClick event in flex List
I found this solution. I just want a spark dropdownlist with itemClick event and without itemselect option (don't show selected item label on button)
[Event(name="itemClick", type="mx.events.ItemClickEvent")]
public class ItemClickDropDownList extends DropDownList
{
public function ItemClickDropDownList()
{
super();
}
override public function closeDropDown(commit:Boolean):void
{
super.closeDropDown(commit);
var e:ItemClickEvent = new ItemClickEvent(ItemClickEvent.ITEM_CLICK, true);
e.item = this.selectedItem;
e.index = this.selectedIndex;
dispatchEvent(e);
//Deselect item
this.selectedIndex = -1;
}

creating submenu's in flex context menu

Is there any workaround to create submenu in a flex context menu other than stopping right click from javascript.
Regards,
Hi Frank,
Yes, I want to create submenus in a context menu. Can you help me here.
Regards,
Hi Frank,
I need the context menu for the application not for datagrid.
In my initial question the phrase "other than stopping right click from javascript" means
"catch the right click in html, call a javascript function and over js call a as function."
The project that you have specified does the above procedure. I don't want to use this
procedure. Is there any other way for achieving submenus in a flex context menu. Could you
please tell me if so..
Regards,
Arvind
Yes, there is.
I don't know, what you exactly mean with this:
other than stopping right click from
javascript.
But, if you want to create a entry in submenu, do this:
//Instance of my own class
private var myContext:myContextMenu = new myContextMenu();
application.contextMenu = myContext.myContextMenu;
//Here is the Class:
package com.my.components
{
/* ////////////////////////////////////////////
///// My Context MenĂ¼ /////////////////////
///////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
//to use: //
// private var myContext:MyContextMenu = new MyContextMenu(); //
// init() in creationComplete //
// application.contextMenu = myContext.myContextMenu; //
////////////////////////////////////////////////////////////////////////////// */
import flash.display.Sprite;
import flash.events.ContextMenuEvent;
import flash.net.URLRequest;
import flash.net.navigateToURL;
import flash.text.TextField;
import flash.ui.ContextMenu;
import flash.ui.ContextMenuBuiltInItems;
import flash.ui.ContextMenuItem;
public class MyContextMenu extends Sprite
{
public var myContextMenu:ContextMenu;
private var menuLabel:String = String.fromCharCode(169)+" My Company GmbH";
public function MyContextMenu()
{
myContextMenu = new ContextMenu;
removeDefaultItems();
addCustomItems();
myContextMenu.addEventListener(ContextMenuEvent.MENU_SELECT, menuSelectHandler);
super();
}
private function removeDefaultItems():void
{
myContextMenu.hideBuiltInItems();
var defaultItems:ContextMenuBuiltInItems = myContextMenu.builtInItems;
defaultItems.print = true;
}
private function addCustomItems():void
{
var item:ContextMenuItem = new ContextMenuItem(menuLabel);
myContextMenu.customItems.push(item);
item.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT,menuItemSelectHandler);
}
private function menuSelectHandler(event:ContextMenuEvent):void
{
}
private function menuItemSelectHandler(event:ContextMenuEvent):void
{
navigateToURL(new URLRequest('http://www.my-company.de'));
}
private function createLabel():TextField
{
var txtField:TextField = new TextField();
//txtField.text = textLabel;
txtField.text = "RightClickHere";
return txtField;
}
}
}
Have fun
EDIT:
There is an interesting project here. They catch the right click in html, call a javascript function and over js call a as function.
Unfortunately, the limitation of FP or NativeMenu APi allowed just on level contextmenu. Read here
Frank

TextField in AS3 - programming a click listener

I want to add a simple piece of text to the stage and add a listener to do something when the user clicks it.
Here's my TextLink class:
package some.package
{
import flash.display.Sprite;
import flash.external.ExternalInterface;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
public class TextLink extends Sprite
{
public var tf:TextField = new TextField();
public var bspr:Sprite = new Sprite();
public function TextLink(tx:int, ty:int, tft:String):void
{
tf.text = tft;
tf.x = tx;
tf.y = ty;
tf.autoSize = TextFieldAutoSize.LEFT;
bspr.addChild(tf);
this.addChild(tf);
}
}
}
And here is the way I am calling it, along with the listener:
public function test_array_of_objects():void
{
var tmp:TextLink = new TextLink(30, 30, "some text");
tmp.addEventListener(MouseEvent.CLICK, roverNotify);
addChild(tmp);
}
protected function roverNotify(e:Event):void
{
ExternalInterface.call("console.log", "got a click");
}
...But I don't get a message for some reason.
I've imported everything successfully. Any thoughts on what else I can try?
Is your TextLink class an event dispatcher? You're trying to add a listener to the TextLink object, but the click listener needs to be attached to the text field that you're using inside TextLink. TextLink needs to be a DisplayObject of some kind to inherit the dispatching capabilities.
Also, constructors should not specify a return type (since they're just returning themselves) -- the :void should not be there where your TextLink constructor is.
Does function TextLink require something like this at the beginning:
var tf:Text = new Text();
Is the problem with clicking the Sprite or getting the event to fire? If it's the former you could try adding the code below.
tmp.mouseChildren = false;
tmp.buttonMode = true;
ExternalInterface.call("console.log", "got a click");
You have a JavaScript function defined like this??:
function console.log(inputString) {
//do something
}
Edit: Nevermind the above, forgot about Firebug.
Also, TextLink doesn't need to be an event dispatcher, though you may want to have TextLink set its mouseChildren property to false (unless you need to be able to select that text), so that you don't inadvertently trigger events on the TextField, and buttonMode to true.
Edit: Also, what's the point of?:
var bspr:Sprite = new Sprite();
bspr.addChild(tf);
Final edit
How about this? http://code.google.com/p/fbug/issues/detail?id=1494
Yes, you are correct, in FF3 the console is injected only when the page has
javascript and uses window.console.
If you put any js that accesses the console before the Flash loads it should work, eg
<script>
var triggerFirebugConsole = window.console;
</script>
Let us know if this works. It's unlikely that we can fix this soon.

possible to display an arrayCollection of Sprites in a List component?

I have an arrayCollection of objects that extend Sprite, and have bitmaps within them.
I want to display these in a list (or some other component that would allow a user to scroll through them, and see their associated data.)
When I do: myList.dataProvider = myArrayCollection
the list just shows a bunch of lines of [Object, Item] instead of the visual sprites.
Here is a simplified version of my Object:
public class myUIC extends UIComponent
{
public var mySprite:Sprite = new Sprite;
[Embed(source="assets/BGimage.png")]
public var BGimage:Class;
public var myBitmap:Bitmap;
public var wordText:TextField = new TextField;
public function myUIC(myWord:String)
{
this.wordText.text = myWord;
this.myBitmap = new BGimage;
this.mySprite.addChild(this.myBitmap);
this.mySprite.addChild(this.wordText);
this.addChild(this.mySprite);
}
}
Tried many different ways to get it to show up in a List, but can't do it.
See this tutorial: Flex Examples - displaying icons in a flex list control
Sounds like you may want to try writing a simple item renderer (perhaps based off UIComponent) that adds the associated sprite the display list of the render using addChild().
try rawChildren.addChild for adding the Sprite
Here, try using an itemRenderer something like this. It ought to work with any generic DisplayObject. It's grabbing the width and height from the assigned data property, so you might need to set variableRowHeight to true in your actual list for it to work as expected.
package
{
import flash.display.DisplayObject;
import mx.controls.listClasses.IListItemRenderer;
import mx.core.UIComponent;
import mx.events.FlexEvent;
/*
Extending UIComponent means we can add Sprites (or any DisplayObject)
with addChild() directly, instead of going through the rawChildren property.
Plus, in this case, we don't need the extra overhead of Canvas's layout code.
IListItemRenderer lets us use it as a List's itemRenderer. UIComponent already
implements all of IListItemRenderer except for the data property
*/
public class SpriteRenderer extends UIComponent implements IListItemRenderer
{
// Implementing the data property for IListItemRenderer is really easy,
// you can find example code in the LiveDocs for IDataRenderer
private var _data:Object;
[Bindable("dataChange")]
public function get data():Object
{
return _data;
}
public function set data(value:Object):void
{
if (value !== _data) {
// We need to make sure to remove any previous data object from the child list
// since itemRenderers are recycled
if (_data is DisplayObject && contains(_data as DisplayObject)) {
removeChild(_data as DisplayObject);
}
_data = value;
// Now we just make sure that the new data object is something we can add
// and add it
if (_data is DisplayObject) {
this.width = (_data as DisplayObject).width;
this.height = (_data as DisplayObject).height;
addChild(_data as DisplayObject);
}
dispatchEvent(new FlexEvent(FlexEvent.DATA_CHANGE));
}
}
public function SpriteRenderer()
{
super();
}
}
}

Resources