dispatching from an object not in the display list? - actionscript-3

I have an object that controls another object that is on the display list.
The setup looks like this:
Parent (Main Timeline)
- Child
-- Grandchild --> contains instance of behaviour class that controls the grandchild's movement
I have an event in the "behaviour" that I'd like to reach the parent, but the behavior does not extend Sprite or MovieClip.
How can I get this event to reach the parent?

There are two ways. If the "behavior" object has access to the GrandChild, the GrandChild has a root property (which, conveniently) is the root -- this will only work if there is a path-to-root though. You can't remove a child (or its parents) and then expect to be able to access the root directly. But, if you have a DisplayObject which you know is on the stage, you can use that to communicate to the root directly. (You can also, with proper casting, access all of the parents and grandparents of the Grandchild).
You can also have a centralized EventDispatcher which is listened to by whatever you want to listen to it. Basically, create a Singleton (you'll need to look that up for the AS3 way) which subclasses EventDispatcher and then tell that to dispatch whatever events you need.
It would look something like this:
//on the root
EventDispatcher.getInstance().addEventListener( "myCustomEvent", myEventhandler );
//in behavior
EventDispatcher.getInstance().dispatchEvent( new Event( "myCustomEvent" ) );
//root now acts accordingly.

The "BubblingEventDispatcher" class you are referring to is a bit misleading. It's actually just adding children to the display list in order to enable bubbling:
AS3 Event Bubbling outside of the Scenegraph/DisplayList
In order to relay events without having access to bubbling, you are basically stuck listening for the events on every level and relaying them along manually. It accomplishes the same thing as if you had bubbled the event but it's more of a hassle and it also introduces tighter coupling.

Related

How to bind object throw multi child elements

TLDR: How to define and upward pass a common property throw 3 registered elements?
Assume that you have a parent interface element and call it dashboard, now <dashboard> has a child element called <tree-node> which includes another child element inside it called <tree-node-element> which prompts the user to push some data into an array called chapters.
How to pass chapters object from <tree-node-element> upwards to <dashboard>, should I define chapters property in each element, what flags should I give that property in each definition.
Polymer V1x
Use event bubbling, so fire() the event node-element-foo-changed and listen for it in the dashboard element.
This is probably late stage, but you can also for example use Redux or data mixins for state management in your application.
Define the chapters property on the top node, dashboard. Propagate it down through the tree via polymer data binding. Have the child node (tree-node-element) emit an event to change the value. Have the dashboard element listen for the event and update the value with this.set(). The value will then automatically propagate down to all the child nodes in the tree. That way you only need to implement the logic to update the data in one place.

AS3: bringing an object to front each frame

I have a UI object that, of course, should always be kept in front of all other objects. To do that, I decided to destroy and add it again each frame, like this:
removeChild(UI_Indicator)
addChild(UI_Indicator)
But nevertheless, objects that are created in it’s area still come on top of it. How is this even possible? I also tried the common
UI_Indicator.parent.setChildIndex(UI_Indicator,UI_Indicator.parent.numChildren - 1)
But it doesn’t work too. Any suggestions?
You are not destroying anything with removeChild(), you just stop displaying it. removeChild() isn't even necessary here. addChild() happily takes a DisplayObject that is already a child of the DisplayObjectContainer you called it on and re-adds the child again (to the top)
Instead of doing this readdChild()ing every frame, place your
allways-on-top DisplayObject on the display list once, then create
a DisplayObjectContainer, say a Sprite for example and add it
behind your indicator. Now add all your other DisplayObjects to
that container. This has the disadvantage of requiring you to add
everything to the container. The functionality breaks as soon as you
accidentally addChild() the regular way. This thought process
leads to the second solution below.
In your subclass of DisplayObjectContainer that includes the
indicator, override the methods that interact with the display list
(add/remove children, etc.) All those that could cause something to
get on top of your indicator. This puts you in full control of
what's going on when something is added to this container. You can
either incorporate solution 1 for simplicity's sake: delegate all
method calls to the inner container Sprite or, if you don't like
to have an internal container, do it without it and make sure that
no other child than your indicator is ever assigned the top most
index. You'd create an additional method to add the always-on-top child, like addTopChild() for example.

AS3 - Make ADDED_TO_STAGE Capture/Bubble?

So the *ADDED_TO_STAGE* and *REMOVED_FROM_STAGE* Events do not notify ancestors in any way. I've looked all around and can't find an answer...do I need to build a new class to do it, or is there a way to hack it into using the Capture/Bubble notification phases?
The descendants of a DisplayObject that is removed from the stage dispatches it's own REMOVED_FROM_STAGE and ADDED_FROM_STAGE events when their parent is removed from the display list of the stage.
So you can simply add an event listener to any descendant and have it handle those events directly.
I may be misunderstanding what you are trying to do, but in general events bubble upward from child objects to their parents. So when you say the descendants are not notified, you are correct as they are not upward on the heiarchy. However, if your goal is for a given object to know when it is added/removed to/from the display list of the stage, that can be had by listening to the specific DisplayObject.
So although the added/removed events do not bubble to their ancestors, there is a way to listen for their events directly.
And if you subclassed MovieClip or Sprite, you could have that class listen for the event, and then dispatch an event that does bubble to the ancestors.
However, I think it be better for us to understand better what you are trying to do as your approach might be the real issue.

Calling a Movieclip from the stage from a Class

I'm trying to call a movieclip called mcMain that's already on the stage. I'm calling it from a class and I've tried googling a whole bunch of possible solutions, none of which appear to work. I've tried stage.mcMain, this.stage.mcMain, MovieClip(root).mcMain, but nothing seems to work. Anyone got any ideas? I don't even get an error message. Just nothing happens.
I don't think that the root of your document timeline is actually the stage. However, you shouldn't be doing this. If the "Class," as you call it, is a DisplayObject, it should not know about anything outside its own scope (unless you've exposed properties or methods on it that would allow for this information to be passed in. If the Class is a data class it shouldn't know about the View at all. If it's a controller class, you'll need to pass a reference to it.
However, given the code you said you tried, I'm guessing your Class instance is some sort of DisplayObject. What you should do is dispatch a bubbling event from your Class, and then in your main Document class, listen for that event. In the event handler function, do whatever you need to do with your mcMain instance, such as adding ketchup. This should work just fine, because your main document Class can receive events from anywhere in the display list, and mcMain is its own instance.

Does it make sense to dispatch events from another object?

I'm still trying to get my head around the best way to structure event flows. Someone made a lot of sense by telling me that contained objects should be decoupled from their parent containers so they're reusable between containers. Instead of calling their parent's function, they dispatch an event. Sensible!
I recently myself in the awkward-feeling situation of dispatching an event on a contained object, from its parent. It seems more intuitive for an object to be the one dispatching its own events. Maybe I'm bordering on breaking the Law of Demeter?
Example of what I'm doing:
child.dispatchEvent(new ChildEvent(ChildEvent.IM_BEING_A_CHILD));
Am I correct in feeling strange here, or is it a normal thing for one object to dispatch another object's events?
You are not necessarily breaking any rules here - if dispatchEvent is a public function then you are allowed to call it from anywhere you like.
If you want to keep things cleaner from an encapsulation point of view you could instead expose an explicit function that the parent can call for a particular event to occur - eg:
child.doSomeChildAction();
and on the child class:
public function doSomeChildAction():void
{
dispatchEvent(new ChildEvent(ChildEvent.IM_BEING_A_CHILD));
}
This way if you need to change the way child sends the event, what kind of event is sent, or what actions occur when the child sends the event it is all encapsulated in the child class, and so will be easier to manage.