Clickable is a hack.  Ideally, there wouldn't even be a clickable attribute; you'd just declare the event handlers you wanted, and other events would bubble up to their parents.  In other words we could make the handling and interception of the different mouse events independent from clickable, we could also make them independent from each other, and then clickable could go away.

Some history:

What we wanted to do was implement this:

Definitions
A mouse event is an event that is triggered in response to a change in the state of the mouse buttons, or in the position of the mouse relative to a view, e.g. onclick, onmouseover.

A view's clickable region is the (possibly non-rectangular) extent of the view for the purpose of computing whether it contains the mouse location.  (Despite the name, the clickable region is used for computation of events other than mouse clicks, such as onmouseover and onfocus.)

The target of a mouse event is is the frontmost visible view whose mouse region contains the event location.

A view A's handler for an event onxxx is a body of code that has been attached to the via an attribute, a <method event="onxxx"> attribute, or the _javascript_ LzDelegate constructor.

A view A's most immediate possibly improper ancestor is whichever comes first of A, and the ancestors of A sorted from most immediate (its immediate parent) to least immediate (the canvas).

Specification
A mouse event results in the invocation of the handler of the most immediate possibly improper ancestor of the event's target.

For example, a view A contains a view B.  A declares handlers for onmouseover and onmouseout.  B declares a handler for onmouseover, but not onmouseout.  An onmouseover event targeted at B will invoke the B's onmouseover handler, and not A's.  An onmouseout event targeted at B will invoke A's onmouseover handler, because B does not have a handler for that event.

(This is the same as event bubbling <http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-flow-bubbling>, with an implicit stopPropogation on every event handler.)

What We Did Instead
Due to a limitation of the Flash runtime (below), LzView has a clickable attribute.  A view doesn't intercept any mouse events (even events that it has declared handlers for) if clickable=false; it intercepts all events (even events that it has not declared handlers for) if clickable=true.

For convenience, clickable defaults to true iff the view declares a handler for a mouse event.  For example, <view width="10" height="10"/> isn't clickable, and therefore doesn't intercept any mouse events, but <view width="10" height="10" /> is clickable because it has an onclick attribute, and therefore intercepts onclick but also onmouseover, onmouseout, etc.

(This defaulting on clickable introduces some obvious problems, which you've run into.  It was deemed better than the problem that onclick etc. just didn't seem to do anything, unless you knew to declare this other attribute which had to be maintained in tandem with the presence or absence of onclick, onmouseover, etc.)

This means that, in the example above, an onmouseout event targeted at B won't do anything, because B has to be clickable in order to receive onmouseover, in which case intercepts onmouseout too.

In code:  Nothing will happen when you click on B in the fragment below.  B masks clicks from A, even though it doesn't declare an onclick.

  <view id="A" width="200" height="200" bgcolor="blue">
    <view id="B" width="100" height="100" bgcolor="green"/>
  </view>

The workaround is this, which manually implements event bubbling for onclick through means of a "trampoline handler" on B.
  <view name="A" width="200" height="200" bgcolor="blue">
    <view name="B" width="100" height="100" bgcolor="green">
      <method event="onclick" args="sd">
        immediateparent.onclick.sendEvent(sd);
      </method>
    </view>
  </view>

Of course, if this fragment occurred inside a view C that intercepted another mouse event (say onmousedown), you'd need to attach trampoline handlers for onmousedown to A and B --- and so on for every other mouse event, depending on where this code ended up.

But Why Not...?
Why not give LaszloView a default onclick handler, that calls its parent's onclick handler, and ditto for every other mouse event?

In other words, why not factor the workaround code out of the fragment above, and into the runtime library?

Dunno.  Adam said it would be too slow, but truth be told it was really because nobody had time to even try it out and see if it would have been too slow.

Doing this now might break apps, but app-breaking changes into The Code Branch Which Will Probably Become 4.0.  So if anyone is interested enough in this change to:
- Propose the change (you can use the language in this message)
- Figure out how to build from sources
- Figure out what code to add to LaszloView.as
- Fix the demos and examples, if they're even broken --- and if they aren't, this means this is small enough that it could go in 3.2 instead of 4..0
- Assess the performance impact
- Write a test case (you can start with the fragment in this message)
then I, at least, would welcome the patch.

The Implementation Details
(You don't actually need to understand this to understand anything above:)

VIews are implemented as Flash movie clips.  The Flash runtime doesn't do anything when the state of the mouse changes relative to the movie clips in the movie object model; there's therefore no practical way to target mouse events.  (There's an impractical way, which is test the mouse location against the view hierarchy.  It's impractical because it would use too much processor.)

A clickable view is therefor implemented as a movie clip that contains an invisible button, in addition to whatever other contents it has for display purposes.  The code for this is in $LPS_HOME/WEB-INF/lps/lfc/views/LaszloView.as.

On Dec 6, 2005, at 5:47 PM, Scott Evans wrote:
Currently, a view will receive onmouseover/out events only if it is 
clickable.  I'd like to see this restriction removed: the two don't 
necessarily have anything to do with one another.

There are cases where you want to simply say "is the mouse in this
area?" and a non-clickable view would be a great way to do that.

Thoughts?  I guess this would break backwards compatiblity, but this 
design quirk has been forcing me to write some weird LZX to do simple 
things.



gse
_______________________________________________
Laszlo-user mailing list

_______________________________________________
Laszlo-user mailing list
[email protected]
http://www.openlaszlo.org/mailman/listinfo/laszlo-user

Reply via email to