You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@flex.apache.org by yishayw <yi...@hotmail.com> on 2016/08/18 06:25:06 UTC

[FlexJS] ElementWrapper.forwarder() Changes Target

If I listen on a click event on the application I expect to get all click
events bubbled up from contained elements. That works, however the target is
the application rather than the element that was clicked on. This is due to
ElementWrapper.forwarder() re-dispatching the event, where the
ElementWrapper is the application. Is this by design?

The problem I had with the target not being preserved is that
MouseEvent.screenX is wrong, as it relies on the target and on localX for
its calculation. localX pertains to the original target, not the new target.

Any ideas on how to fix this?



--
View this message in context: http://apache-flex-development.2333347.n4.nabble.com/FlexJS-ElementWrapper-forwarder-Changes-Target-tp54537.html
Sent from the Apache Flex Development mailing list archive at Nabble.com.

Re: [FlexJS] ElementWrapper.forwarder() Changes Target

Posted by yishayw <yi...@hotmail.com>.
I should add that in JS the target is the original element, so I would say it
was a bug.



--
View this message in context: http://apache-flex-development.2333347.n4.nabble.com/FlexJS-ElementWrapper-forwarder-Changes-Target-tp54537p54538.html
Sent from the Apache Flex Development mailing list archive at Nabble.com.

Re: [FlexJS] ElementWrapper.forwarder() Changes Target

Posted by Alex Harui <ah...@adobe.com>.

On 8/18/16, 2:37 PM, "Harbs" <ha...@gmail.com> wrote:

>React works by using a Shadow DOM and diffing the DOM to figure out if
>things need to change.
>
>Angular works by running constant checks on the DOM and updating stuff as
>needed.
>
>I think simply wrapping DOM elements by JS ones has WAY less overhead
>than both of these approaches.
>

Agreed.  But that is not, IMO, a clear reason to wrap the Sprite
DisplayObjects.

>
>Re. Events:
>
>I think MouseEvent does not inherit from Event because it inherits from
>Flash MouseEvent (being events are being subclassed rather than wrapped).

IIRC, there is more to it than that, otherwise the FlexJS MouseEvent would
still inherit from flash.event.Event.

>The fact that MouseEvent on the JS side seems to be BrowserEvent instead,
>is just weird. We spent a very long time today on the fact that Mouse
>coordinates on transformed SVG elements were not working correctly. We
>have a partial solution to that, but fixing it “correctly” is a whole
>other topic.

When we get to discussing events, one proposal is to not use Google
Closure's events.

-Alex


Re: [FlexJS] ElementWrapper.forwarder() Changes Target

Posted by Harbs <ha...@gmail.com>.
React works by using a Shadow DOM and diffing the DOM to figure out if things need to change.

Angular works by running constant checks on the DOM and updating stuff as needed.

I think simply wrapping DOM elements by JS ones has WAY less overhead than both of these approaches.


Re. Events:

I think MouseEvent does not inherit from Event because it inherits from Flash MouseEvent (being events are being subclassed rather than wrapped). The fact that MouseEvent on the JS side seems to be BrowserEvent instead, is just weird. We spent a very long time today on the fact that Mouse coordinates on transformed SVG elements were not working correctly. We have a partial solution to that, but fixing it “correctly” is a whole other topic.

On Aug 19, 2016, at 12:30 AM, Alex Harui <ah...@adobe.com> wrote:

> 
> 
> On 8/18/16, 1:34 PM, "Peter Ent" <pe...@adobe.com> wrote:
> 
>> Just to play devil's advocate for moment, ReactJS duplicates the DOM for
>> its own purposes and seems to do quite well. I know it has code in it to
>> do optimization for what to redraw, making it more complex than just a
>> duplicate tree structure.
> 
> What do they get out of duplicating the DOM?
> 
>> 
>> That said, reducing our overhead is a worthy goal and if it can be done
>> without duplication that would be great. I guess a duplicate event system
>> that really brings nothing else to the table would not be worth it if
>> there were alternatives.
> 
> Regarding events, at some point more research needs to be done.  Maybe for
> our purposes we can override event.target.  But I still think this answer
> requires us to first settle on whether we are wrapping DisplayObjects or
> not.  Duplicating Events in FlexJS would bring the API closer to what it
> was in Flex, but there might be other ways, like a different property name
> for target and generating different code to access it.
> 
> We should also revisit and properly document the reason why MouseEvent is
> not inheriting from Event.  Maybe there is another solution there as well,
> which would totally change the set of possible solutions.
> 
> -Alex
> 


Re: [FlexJS] ElementWrapper.forwarder() Changes Target

Posted by Alex Harui <ah...@adobe.com>.

On 8/18/16, 1:34 PM, "Peter Ent" <pe...@adobe.com> wrote:

>Just to play devil's advocate for moment, ReactJS duplicates the DOM for
>its own purposes and seems to do quite well. I know it has code in it to
>do optimization for what to redraw, making it more complex than just a
>duplicate tree structure.

What do they get out of duplicating the DOM?

>
>That said, reducing our overhead is a worthy goal and if it can be done
>without duplication that would be great. I guess a duplicate event system
>that really brings nothing else to the table would not be worth it if
>there were alternatives.

Regarding events, at some point more research needs to be done.  Maybe for
our purposes we can override event.target.  But I still think this answer
requires us to first settle on whether we are wrapping DisplayObjects or
not.  Duplicating Events in FlexJS would bring the API closer to what it
was in Flex, but there might be other ways, like a different property name
for target and generating different code to access it.

We should also revisit and properly document the reason why MouseEvent is
not inheriting from Event.  Maybe there is another solution there as well,
which would totally change the set of possible solutions.

-Alex


Re: [FlexJS] ElementWrapper.forwarder() Changes Target

Posted by Peter Ent <pe...@adobe.com>.
Just to play devil's advocate for moment, ReactJS duplicates the DOM for
its own purposes and seems to do quite well. I know it has code in it to
do optimization for what to redraw, making it more complex than just a
duplicate tree structure.

That said, reducing our overhead is a worthy goal and if it can be done
without duplication that would be great. I guess a duplicate event system
that really brings nothing else to the table would not be worth it if
there were alternatives.

‹peter

On 8/18/16, 2:38 PM, "Alex Harui" <ah...@adobe.com> wrote:

>
>
>On 8/18/16, 10:42 AM, "Peter Ent" <pe...@adobe.com> wrote:
>
>>I think I'm leaning more toward agreeing with you, Harbs, about a Flex
>>event bus. I remember changing MouseEvent because of some issue (have to
>>look at the logs) with it being a subclass of Event. If we make it a rule
>>that every FlexJS component only work with org.apache.flex.events.Event
>>(or a subclass), and have a set of interactive event (mouse, touch,
>>keyboard) classes (which derive from our own Event class), something deep
>>down should be able to translate platform events to our events and put
>>them onto our bus. It is a shame not to take advantage of the platform's
>>own dispatching system, but when trying to put things together from
>>different systems, sometimes you need to go outside the box.
>
>Duplicating the event system is definitely a possibility, but I would like
>to explore other solutions first.
>
>Stepping back, IIRC, the reason we tried wrapping Sprite was to deal with
>code-hinting in the IDEs and issues with property and method names with
>low-level Flash APIs.  It occurred to me that the wrapping solution might
>be attacking this problem incorrectly:  it is adding runtime overhead for
>an author-time problem.  That isn't PAYG.  Further adding a duplicate
>event system will only add more runtime overhead.  The Google event system
>we use on the JS side added 6K to every download.  Not sure how big a
>Flash version will be, but it will double the number of event listener
>arrays and worse, the duplicates will be in ActionScript instead of C
>code.  And when you add overhead, you invite others to undercut you with
>lower-overhead alternatives and fracture the community.
>
>In addition, IMO, it was a goal to try to abstract away the internal
>implementations of the components.  I'm concerned that we will get used to
>wrapping everything.  The CreateJS code and another Canvas framework that
>doesn't have to wrap HTMLElements shouldn't have to wrap elements.  Same
>will be true for any Flash 3D/Starling/Feathers sort of thing for the SWF.
>
>So maybe the answer is to upgrade the tools to solve the original set of
>problems.  Then the runtime is as efficient as it can be for each
>platform.
>
>The separate problem of event classes and their inheritance is, IMO a
>separate problem and the solution is dependent on whether we keep wrapping
>DisplayObjects in the SWF implementation.  I will say, though, that it is
>important to remember that we want the lowest overhead on the JS side, so
>having some additional overhead on the SWF side is ok, but double the
>number of objects may be too much.  Further, 100% compatibility with Flex
>is not a requirement.  So, some old Flex coding patterns and expectation
>may have to change, including whether you have to get the type of your
>events correct because MouseEvent doesn't subclass Event. That might still
>be better fixed with better tooling and debugging.  I can imagine some
>hybrid apps where the app uses more than one library which are dispatching
>different kinds of events.
>
>I am going to go dig up the original thread and respond there with a
>discussion on alternative solutions.
>
>My 2 cents,
>-Alex
>


Re: [FlexJS] ElementWrapper.forwarder() Changes Target

Posted by Harbs <ha...@gmail.com>.
> Stepping back, IIRC, the reason we tried wrapping Sprite was to deal with
> code-hinting in the IDEs and issues with property and method names with
> low-level Flash APIs.

A bigger issue was related to defining properties and methods which collided with Flash ones. That’s not just a tooling issue. It’s not possible to define the properties and methods without overrides, and overrides generally do not work because they are incompatible.

I don’t think wrapping things on the Flash side adds an unacceptible amount of overhead. It’s not worse that classic Flex components (probably a lot better) in that regard.

On Aug 18, 2016, at 9:38 PM, Alex Harui <ah...@adobe.com> wrote:

> 
> 
> On 8/18/16, 10:42 AM, "Peter Ent" <pe...@adobe.com> wrote:
> 
>> I think I'm leaning more toward agreeing with you, Harbs, about a Flex
>> event bus. I remember changing MouseEvent because of some issue (have to
>> look at the logs) with it being a subclass of Event. If we make it a rule
>> that every FlexJS component only work with org.apache.flex.events.Event
>> (or a subclass), and have a set of interactive event (mouse, touch,
>> keyboard) classes (which derive from our own Event class), something deep
>> down should be able to translate platform events to our events and put
>> them onto our bus. It is a shame not to take advantage of the platform's
>> own dispatching system, but when trying to put things together from
>> different systems, sometimes you need to go outside the box.
> 
> Duplicating the event system is definitely a possibility, but I would like
> to explore other solutions first.
> 
> Stepping back, IIRC, the reason we tried wrapping Sprite was to deal with
> code-hinting in the IDEs and issues with property and method names with
> low-level Flash APIs.  It occurred to me that the wrapping solution might
> be attacking this problem incorrectly:  it is adding runtime overhead for
> an author-time problem.  That isn't PAYG.  Further adding a duplicate
> event system will only add more runtime overhead.  The Google event system
> we use on the JS side added 6K to every download.  Not sure how big a
> Flash version will be, but it will double the number of event listener
> arrays and worse, the duplicates will be in ActionScript instead of C
> code.  And when you add overhead, you invite others to undercut you with
> lower-overhead alternatives and fracture the community.
> 
> In addition, IMO, it was a goal to try to abstract away the internal
> implementations of the components.  I'm concerned that we will get used to
> wrapping everything.  The CreateJS code and another Canvas framework that
> doesn't have to wrap HTMLElements shouldn't have to wrap elements.  Same
> will be true for any Flash 3D/Starling/Feathers sort of thing for the SWF.
> 
> So maybe the answer is to upgrade the tools to solve the original set of
> problems.  Then the runtime is as efficient as it can be for each platform.
> 
> The separate problem of event classes and their inheritance is, IMO a
> separate problem and the solution is dependent on whether we keep wrapping
> DisplayObjects in the SWF implementation.  I will say, though, that it is
> important to remember that we want the lowest overhead on the JS side, so
> having some additional overhead on the SWF side is ok, but double the
> number of objects may be too much.  Further, 100% compatibility with Flex
> is not a requirement.  So, some old Flex coding patterns and expectation
> may have to change, including whether you have to get the type of your
> events correct because MouseEvent doesn't subclass Event. That might still
> be better fixed with better tooling and debugging.  I can imagine some
> hybrid apps where the app uses more than one library which are dispatching
> different kinds of events.
> 
> I am going to go dig up the original thread and respond there with a
> discussion on alternative solutions.
> 
> My 2 cents,
> -Alex
> 


Re: [FlexJS] ElementWrapper.forwarder() Changes Target

Posted by Alex Harui <ah...@adobe.com>.

On 8/18/16, 10:42 AM, "Peter Ent" <pe...@adobe.com> wrote:

>I think I'm leaning more toward agreeing with you, Harbs, about a Flex
>event bus. I remember changing MouseEvent because of some issue (have to
>look at the logs) with it being a subclass of Event. If we make it a rule
>that every FlexJS component only work with org.apache.flex.events.Event
>(or a subclass), and have a set of interactive event (mouse, touch,
>keyboard) classes (which derive from our own Event class), something deep
>down should be able to translate platform events to our events and put
>them onto our bus. It is a shame not to take advantage of the platform's
>own dispatching system, but when trying to put things together from
>different systems, sometimes you need to go outside the box.

Duplicating the event system is definitely a possibility, but I would like
to explore other solutions first.

Stepping back, IIRC, the reason we tried wrapping Sprite was to deal with
code-hinting in the IDEs and issues with property and method names with
low-level Flash APIs.  It occurred to me that the wrapping solution might
be attacking this problem incorrectly:  it is adding runtime overhead for
an author-time problem.  That isn't PAYG.  Further adding a duplicate
event system will only add more runtime overhead.  The Google event system
we use on the JS side added 6K to every download.  Not sure how big a
Flash version will be, but it will double the number of event listener
arrays and worse, the duplicates will be in ActionScript instead of C
code.  And when you add overhead, you invite others to undercut you with
lower-overhead alternatives and fracture the community.

In addition, IMO, it was a goal to try to abstract away the internal
implementations of the components.  I'm concerned that we will get used to
wrapping everything.  The CreateJS code and another Canvas framework that
doesn't have to wrap HTMLElements shouldn't have to wrap elements.  Same
will be true for any Flash 3D/Starling/Feathers sort of thing for the SWF.

So maybe the answer is to upgrade the tools to solve the original set of
problems.  Then the runtime is as efficient as it can be for each platform.

The separate problem of event classes and their inheritance is, IMO a
separate problem and the solution is dependent on whether we keep wrapping
DisplayObjects in the SWF implementation.  I will say, though, that it is
important to remember that we want the lowest overhead on the JS side, so
having some additional overhead on the SWF side is ok, but double the
number of objects may be too much.  Further, 100% compatibility with Flex
is not a requirement.  So, some old Flex coding patterns and expectation
may have to change, including whether you have to get the type of your
events correct because MouseEvent doesn't subclass Event. That might still
be better fixed with better tooling and debugging.  I can imagine some
hybrid apps where the app uses more than one library which are dispatching
different kinds of events.

I am going to go dig up the original thread and respond there with a
discussion on alternative solutions.

My 2 cents,
-Alex


Re: [FlexJS] ElementWrapper.forwarder() Changes Target

Posted by Peter Ent <pe...@adobe.com>.
I think I'm leaning more toward agreeing with you, Harbs, about a Flex
event bus. I remember changing MouseEvent because of some issue (have to
look at the logs) with it being a subclass of Event. If we make it a rule
that every FlexJS component only work with org.apache.flex.events.Event
(or a subclass), and have a set of interactive event (mouse, touch,
keyboard) classes (which derive from our own Event class), something deep
down should be able to translate platform events to our events and put
them onto our bus. It is a shame not to take advantage of the platform's
own dispatching system, but when trying to put things together from
different systems, sometimes you need to go outside the box.

For example: <js:TextButton text="Push Me" click="handleEvent(event)" />
where the event will be org.apache.flex.events.InteractiveEvent. I picked
this so that on a mobile device, you might get a TouchEvent and a desktop
would deliver a MouseEvent. If the handleEvent code needed to know Touch
vs Mouse, it could just query the event's data type.

Underneath, Button might be assigned TextButtonMouseController and, in its
Flash platform-specific code, would listen for flash.events.MouseEvent.
Upon receiving it, use MouseUtils to convert the event into our MouseEvent
and then dispatch it onto our bus.

Each interactive type of control component would have a set of device-type
controllers (TextButtonMouseController, TextButtonTouchController, etc)
and their job is to interface between the platform and FlexJS events. App
developers would be told to write their code to accept InteractiveEvents
in their button handlers which would contain basic information (localX,
localY, etc) that were common to all of the touch & mouse events. More
details might be in the subclass (eg, which mouse button was used found
when casting the event to a MouseEvent).

Might be a lot of work, I don't know. This might also be fraught will all
kinds of side-effects which are not occurring to me right now.

‹peter

On 8/18/16, 7:45 AM, "Harbs" <ha...@gmail.com> wrote:

>IMO, the ³right² way to fix this is by dispatching events from the
>flexjs_wrapper and implement event bubbling up the FlexJS element chain.
>
>Yishay did not mention them, but we were having a whole slew of problems
>related to events:
>
>
>1. Event targets being lost (which he mentioned here)
>2. Fixing that seems to mess up bubbling. (again)
>3. clone() and cloneEvent() is a bit weird. You cannot dispatch
>cloneEvent() directly without casting it first (because it¹s the Flash
>EventDispatcher which does the dispatching) and you cannot override
>clone() using a Flex event because it¹s an incompatible override.
>4. BrowserEvents vs. MouseEvent We were actually kind of confused by
>MouseEvent, because in the Browser, only BrowserEvents seem to be used.
>What¹s the point of MouseEvents?
>5. EventDispatcher took a Flash event even though we really need a Flex
>event. See # 3.
>6. EventDispatcher cannot take an IFlexEvent. This kind of defeats the
>point of have an IFlexEvent in the first place.
>7. BrowserEvent was missing localX and localY (maybe fixed)
>8. I really think that MouseEvent should probably subclass event, but it
>can¹t because it subclasses Flash MouseEvent. It it wrapped the events,
>this problem would be solved.
>
>To me, all this points to the fact that we should have a Flex event bus
>which would be completely cross-platform and wrap browser and Flash
>events.
>
>
>
>On Aug 18, 2016, at 10:05 AM, Alex Harui <ah...@adobe.com> wrote:
>
>> 
>> 
>> On 8/17/16, 11:25 PM, "yishayw" <yi...@hotmail.com> wrote:
>> 
>>> If I listen on a click event on the application I expect to get all
>>>click
>>> events bubbled up from contained elements. That works, however the
>>>target
>>> is
>>> the application rather than the element that was clicked on. This is
>>>due
>>> to
>>> ElementWrapper.forwarder() re-dispatching the event, where the
>>> ElementWrapper is the application. Is this by design?
>> 
>> Well yes, for events dispatched from the wrapped element, but you are
>> correct that it won't work for bubbled events.  There is no way to set
>>the
>> target of an event in Flash.  We might have to build our own queue of
>> listeners and call them directly, but even then, the target will be a
>> wrapped element and not its wrapper.
>> 
>> This might be an issue that kills the plan of wrapping Flash
>> DisplayObjects.  We'll see if someone comes up with a "easy" way of
>> getting it to work.  I'll ponder it while I'm sleeping.
>> 
>> -Alex
>> 
>


Re: [FlexJS] ElementWrapper.forwarder() Changes Target

Posted by Harbs <ha...@gmail.com>.
IMO, the “right” way to fix this is by dispatching events from the flexjs_wrapper and implement event bubbling up the FlexJS element chain.

Yishay did not mention them, but we were having a whole slew of problems related to events:


1. Event targets being lost (which he mentioned here)
2. Fixing that seems to mess up bubbling. (again)
3. clone() and cloneEvent() is a bit weird. You cannot dispatch cloneEvent() directly without casting it first (because it’s the Flash EventDispatcher which does the dispatching) and you cannot override clone() using a Flex event because it’s an incompatible override.
4. BrowserEvents vs. MouseEvent We were actually kind of confused by MouseEvent, because in the Browser, only BrowserEvents seem to be used. What’s the point of MouseEvents?
5. EventDispatcher took a Flash event even though we really need a Flex event. See # 3.
6. EventDispatcher cannot take an IFlexEvent. This kind of defeats the point of have an IFlexEvent in the first place.
7. BrowserEvent was missing localX and localY (maybe fixed)
8. I really think that MouseEvent should probably subclass event, but it can’t because it subclasses Flash MouseEvent. It it wrapped the events, this problem would be solved.

To me, all this points to the fact that we should have a Flex event bus which would be completely cross-platform and wrap browser and Flash events.



On Aug 18, 2016, at 10:05 AM, Alex Harui <ah...@adobe.com> wrote:

> 
> 
> On 8/17/16, 11:25 PM, "yishayw" <yi...@hotmail.com> wrote:
> 
>> If I listen on a click event on the application I expect to get all click
>> events bubbled up from contained elements. That works, however the target
>> is
>> the application rather than the element that was clicked on. This is due
>> to
>> ElementWrapper.forwarder() re-dispatching the event, where the
>> ElementWrapper is the application. Is this by design?
> 
> Well yes, for events dispatched from the wrapped element, but you are
> correct that it won't work for bubbled events.  There is no way to set the
> target of an event in Flash.  We might have to build our own queue of
> listeners and call them directly, but even then, the target will be a
> wrapped element and not its wrapper.
> 
> This might be an issue that kills the plan of wrapping Flash
> DisplayObjects.  We'll see if someone comes up with a "easy" way of
> getting it to work.  I'll ponder it while I'm sleeping.
> 
> -Alex
> 


Re: [FlexJS] ElementWrapper.forwarder() Changes Target

Posted by Alex Harui <ah...@adobe.com>.

On 8/17/16, 11:25 PM, "yishayw" <yi...@hotmail.com> wrote:

>If I listen on a click event on the application I expect to get all click
>events bubbled up from contained elements. That works, however the target
>is
>the application rather than the element that was clicked on. This is due
>to
>ElementWrapper.forwarder() re-dispatching the event, where the
>ElementWrapper is the application. Is this by design?

Well yes, for events dispatched from the wrapped element, but you are
correct that it won't work for bubbled events.  There is no way to set the
target of an event in Flash.  We might have to build our own queue of
listeners and call them directly, but even then, the target will be a
wrapped element and not its wrapper.

This might be an issue that kills the plan of wrapping Flash
DisplayObjects.  We'll see if someone comes up with a "easy" way of
getting it to work.  I'll ponder it while I'm sleeping.

-Alex