I hava a custom component and it contains a child icon. If I add a mouse-click event listener to both component(click-listener1) and icon(click-listener2), the event dispatched sequence is click-listener2, then click-listener1. I can understand it. But if I add a custom event to component (listener1), and mouse-click event to icon(listener2), when icon is clicked, the component will dispatch the custom event. In my test, the event dispatched sequence is listener1, then listener2. It doesn't match with event-bubbles rule.
In my opinion The custom event is dispatched in listener2, which triggers listener1. Why event flow sequence is not listener2, listener1?
In component.
icon.addEventListener(MouseEvent.CLICK, iconClickHandler);
private function iconClickHandler(event:MouseEvent):void
{
trace ("Listener2");
var customEvent:CustomEvent= new CustomEvent(CustomEvent.CUSTOM_EVENT, true, true);
dispatchEvent(customEvent)
trace ("Listener3");
}
In Application, which contains component
component.addEventListener(CustomEvent.CUSTOM_EVENT, customEventHandler);
private function customEventHandler(event:CustomEvent):void {
trace ("Listener1");
}
UPD
You've got:
private function iconClickHandler(event:MouseEvent):void
{
trace("listener2");
var customEvent:CustomEvent= new CustomEvent(CustomEvent.CUSTOM_EVENT, true, true);
dispatchEvent(customEvent);
trace("listener3");
}
private function customEventHandler(event:CustomEvent):void
{
trace("listener1");
}
When MouseEvent.MOUSE_CLICK is dispatched, it triggers first lucky listener - it is your component function iconClickHandler. Here we trace "listener2" and dispatch custom event.
Due to syncronious nature of events, CUSTOM_EVENT listeners are triggered immediatly, that means that dispatching an event is similar to calling listener functions. Events are not stored anywhere, they are not delayed: listeners to events fires immediatly, in the same control flow, in the same thread.
CUSTOM_EVENT was dispatched, its listeners were triggered - we've got a call to customEventHandler and "listener1" in console.
When all the listeners were triggered, control returns to iconClickHandler and "listener3" is traced to console.
That's why we've got output:
listener2
listener1
listener3
Related
I am creating one App in appmaker in which I want to have some code on onHover() event (On Label), I can only see 4 events available
onAttach
onDetach
onDataLoad
onClick
How can I call my methods on onHover event?
App Maker doesn't provide onHover event handler out of the box, however you can add event listener for mouseenter or mouseover event on your own:
// client script
function doMagic(event) {
// do the magic here
}
// onAttach widget's event
widget.getElement().addEventListener('mouseenter', doMagic);
// onDetach widget's event
widget.getElement().removeEventListener('mouseenter', doMagic);
I'd like to avoid that mouse events triggered by the user don't get dispatched to their target objects, effectively "freezing" the GUI for the user.
In a sample application featuring just a single mx.controls.Button I called addEventListener on the button to get notified of mouse events. In the event handler, I called Event::stopImmediatePropagation on the event, assuming that this would "discard" the event. Clicking the button would call my event handler, but yet the button was "clicked" (it animated and triggered an event).
How could I do this?
button.mouseEnabled = false;
button.mouseChildren = false;
should work
Depending on how advanced your interface is, you could just throw an object (s:Rect in an s:Group would work) on top of everything, set width and height to 100%, and disable mouseChildren
USE removeEventListener()
var b:Button = new Button();
function init():void
{
b.addEventListener(MouseEvent.CLICK, onButtonClick);
}
function onButtonClick(event:MourseEvent):void
{
b.removeEventListener(MouseEvent.CLICK, onButtonClick);
}
I want to create a custom event and it will be accessible by any other class.
Suppose I have NavigationMenuClass.as which contains some next, prev buttons, and another class For Page.as which should show a particular page at each next or prev button press.
And I need to create a custom event(will write a EVENTClass.as to manage all these kind of events.) called "showPage", and when this event occures the Page.as class member function need be called.
private function nextPress(event:Event) {
//dispatchEvent(new Event("showPage"));
// this will call the Page class Menmber function page:Page = new Page; page.showNextPage();
}
With out passing the object how can I call a particular member function using Event and Event Dispatcher methods.
You seem kind of confused.
So, you have a display hierarchy in which your Page.as display object is the parent of the NavigationMenuClass.as, correct?
Your NavigationMenuClass should dispatch events for 'next' and 'previous'. The Page class should listen to those events and do something.
Your code kind of already does the dispatching part, although it is commented out. I would put this in the click handler of your button and use it to dispatch a next, or previous, event:
private function nextPress(event:Event) {
// dispatchEvent(new Event("showPage"));
// this will call the Page class Menmber function page:Page = new Page; page.showNextPage();
dispatchEvent(new Event("next"));
}
In your Page.as you just add an event listener:
navigationMenuClassInstance.addEventListener('next', onNext);
public function onNext(event:Event):void{
// write code to change content
}
You can use the same approach to implement the previous event. To address a few of your "odd wordings"
I want to create a custom event and it
will be accessible by any other class
I'm not sure what you mean by accessible.
You can create a custom event class that extends Event and any other class can use it, as long as it imports it. My example above doesn't create a custom event class, but uses the default event class.
In terms of dispatching, the event only dispatches itself up to its' parent. IF the event bubbles, it will go to it's parent parent, then the parent's parent, and so on all the way up the the stage.
With out passing the object how can I
call a particular member function
using Event and Event Dispatcher
methods.
I'm not sure what you mean by "passing the object" here. When you dispatch an event, that event class is always available to the event listener as an argument to that event listener method. That is kind of like passing an object.
Also when following Flextras excellent guide, make sure that NavigationMenuClass extends EventDispatcher, otherwise just calling the dispatchEvent() method won't work!
I've got a class that extends EventDispatcher.
What I want to do is to dispatch the click event when the component is clicked. (The class is essentially some text in a textfield that needs to be able to do certain things, and it needs to be able to respond to a click). Sounds easy enough... I want the event dispatched when that portion of the text is clicked. But uh...how? it's not like a button where I can just go
myButton.addEventListener(MouseEvent.CLICK, myClickHandler);
That's clear, because some component is going to be listening for the Click event dispatched when myButton is clicked. It is built into the AS3 framework that a button knows how to listen for a click event.
After the import statements I've got:
[Event(name="click" type="mx.events.Event")]
How do I dispatch the event when the component is clicked, when the component doesn't yet know how to respond to a click event? I've tried adding an event listener in the textfield which contains this custom class of text, but nothing's happening because the Click event hasn't been dispatched.
You can create your own click event and dispatch it. You can do that also to dispatch clicks on objects where no user ever have clicked :D
Try this:
var mEvent:MouseEvent = new MouseEvent(MouseEvent.CLICK, [HERE MORE PARAMS BY YOU]);
yourObject.dispatchEvent(mEvent);
Now, you will recieve Click Events from yourObject.
Let's say your class consists TextField tf. Then public function YourClass():void { //Constructor
{
//intialize Something
//initialize tf
tf.addEventListener(MouseEvent.CLICK, onClick);
...
}
...
private function onClick(e:MouseEvent):void {
this.dispatchEvent(new MouseEvent(MouseEvent.CLICK));
}
OK, I tried this in the constructor:
var mEvent:MouseEvent = new MouseEvent(MouseEvent.CLICK, true, false);
this.dispatchEvent(mEvent);
Then, in the containing textfield, while iterating through these objects (each of which is called cp), I did this:
cp.addEventListener(MouseEvent.CLICK, mouseClickHandler);
Finally the mouseClickHandler:
private function mouseClickHandler(event:MouseEvent):void
{
trace("Clicked!!!!!!!!!!!");
}
Running in debug mode I get nada. Nunca. Niente. Nuttin'. Which is to say: no trace of being clicked. Did I do something wrong?
Is there a way to write a custom event that gets triggered when the user clicks outside of that custom component instance? Basically anywhere else in the main flex app.
Thanks.
You can use the FlexMouseEvent.MOUSE_DOWN_OUTSIDE event. For example:
myPopup.addEventListener(
FlexMouseEvent.MOUSE_DOWN_OUTSIDE,
function(mouseEvt:FlexMouseEvent):void
{
PopUpManager.removePopUp(myPopup);
}
);
stage.addEventListener( MouseEvent.CLICK, stgMouseListener, false, 0, true );
...
private function stgMouseListener( evt:MouseEvent ):void
{
trace("click on stage");
}
private function yourComponentListener( evt:MouseEvent ):void
{
trace("do your thing");
evt.stopPropagation();
}
Got this from Senocular. I think it applies to this subject, at least it did the trick for me. What jedierikb suggested seems to be the same, but a little incomplete.
Preventing Event Propagation
If you want to prevent an event from propagating further, you can stop it from doing so within an event listener using stopPropagation() (flash.events.Event.stopPropagation()) or stopImmediatePropagation() (flash.events.Event.stopImmediatePropagation()). These methods are called from the Event objects passed into event listeners and essentially stop the event from happening - at least past that point.
stopPropagation prevents any objects beyond the current from recieving the event, and this can be within any phase of the event. stopImmediatePropagation does the same but also takes the extra step of preventing additional events within the current target receiving the event from happening too. So where as stopPropagation would prevent sprite A's parent from receiving the event, stopImmediatePropagation would prevent sprite A's parent as well as any other listeners listening to sprite A from receiving the event.
Example: toggle between using stopPropagation and stopImmediatePropagation
ActionScript Code:
var circle:Sprite = new Sprite();
circle.graphics.beginFill(0x4080A0);
circle.graphics.drawCircle(50, 50, 25);
addChild(circle);
circle.addEventListener(MouseEvent.CLICK, clickCircle1);
circle.addEventListener(MouseEvent.CLICK, clickCircle2);
stage.addEventListener(MouseEvent.CLICK, clickStage);
function clickCircle1(evt:MouseEvent):void {
evt.stopPropagation();
// evt.stopImmediatePropagation();
trace("clickCircle1");
}
function clickCircle2(evt:MouseEvent):void {
trace("clickCircle2");
}
function clickStage(evt:MouseEvent):void {
trace("clickStage");
}
Click the circle and see how the event is stopped with each method. stopPropagation prevented the stage from receiving the event while stopImmediatePropagation also prevented clickCircle2 from recognizing the event
normal output
clickCircle1
clickCircle2
clickStage
stopPropagation output
clickCircle1
clickCircle2
stopImmediatePropagation output
clickCircle1
Flex/Actionscript 3 - close popupanchor on mouse clicked anywhere outside popup anchor
for 4.6 SDK try this..
frmPUA.popUp.addEventListener(FlexMouseEvent.MOUSE_DOWN_OUTSIDE, menuPopOutside, false, 0, true);
Full code is avaiable at
http://saravanakumargn.wordpress.com/2013/12/14/flexactionscript-3-close-popupanchor-on-mouse-clicked-anywhere-outside-popup-anchor-2/