antun
11-21-2003, 08:34 AM
One problem that developers frequently run into is that a view that is that mouse events can't be captured for a view that is covered by another, clickable view. This is most apparent when dragging one view over another: The draggable view must be clickable in order to receive the first onmousedown event that starts the dragging, which means that it won't allow any mouse events to pass to views beneath it.
The solution is to have the views that are to send the events actively check the absolute mouse position against their own coordinates onidle (all the time).
This is an extremely simple example to illustrate that point. A real world scenario would have logic that decided when to start and stop checking the mouse position, as well as how many times to execute any code when the mouse rolls over the lower views. You may also want to check when the mouse goes up after dragging (for drag and drop) - in that case you would have the location testing code executed when the view named dragger sends the onmouseup event:
<canvas debug="true" height="800" width="800">
<debug height="400" width="400" x="300"/>
<dataset name="myds">
<boxes>
<box name="one" />
<box name="two" />
<box name="three" />
<box name="four" />
<box name="five" />
<box name="six" />
<box name="seven" />
<box name="eight" />
</boxes>
</dataset>
<class name="box" width="140" height="40" bgcolor="0xfea366">
<text name="txt" datapath="@name" x="5" y="5" />
<method event="onidle" reference="LzIdle"><![CDATA[
var minX = this.getAttributeRelative( "x", canvas )
var maxX = minX + this.width;
var minY = this.getAttributeRelative( "y", canvas )
var maxY = minY + this.height;
if ( ((canvas.getMouse("x")>minX)&&(canvas.getMouse("x")<maxX))
&& ((canvas.getMouse("y")>minY)&&(canvas.getMouse("y")<maxY)) ){
debug.write( this.txt.text );
}
]]>
</method>
</class>
<simplelayout axis="y" spacing="10" />
<box x="100" y="20" datapath="myds:/boxes[1]/box" />
<view name="dragger" x="250" y="50" bgcolor="0x33de31"
width="50" height="50"
onmousedown="this.dragger.apply()"
onmouseup="this.dragger.remove()"
clickable="true"
options="ignorelayout">
<text align="center" valign="middle">Drag Me</text>
<dragstate name="dragger" />
</view>
</canvas>
Enjoy!
The solution is to have the views that are to send the events actively check the absolute mouse position against their own coordinates onidle (all the time).
This is an extremely simple example to illustrate that point. A real world scenario would have logic that decided when to start and stop checking the mouse position, as well as how many times to execute any code when the mouse rolls over the lower views. You may also want to check when the mouse goes up after dragging (for drag and drop) - in that case you would have the location testing code executed when the view named dragger sends the onmouseup event:
<canvas debug="true" height="800" width="800">
<debug height="400" width="400" x="300"/>
<dataset name="myds">
<boxes>
<box name="one" />
<box name="two" />
<box name="three" />
<box name="four" />
<box name="five" />
<box name="six" />
<box name="seven" />
<box name="eight" />
</boxes>
</dataset>
<class name="box" width="140" height="40" bgcolor="0xfea366">
<text name="txt" datapath="@name" x="5" y="5" />
<method event="onidle" reference="LzIdle"><![CDATA[
var minX = this.getAttributeRelative( "x", canvas )
var maxX = minX + this.width;
var minY = this.getAttributeRelative( "y", canvas )
var maxY = minY + this.height;
if ( ((canvas.getMouse("x")>minX)&&(canvas.getMouse("x")<maxX))
&& ((canvas.getMouse("y")>minY)&&(canvas.getMouse("y")<maxY)) ){
debug.write( this.txt.text );
}
]]>
</method>
</class>
<simplelayout axis="y" spacing="10" />
<box x="100" y="20" datapath="myds:/boxes[1]/box" />
<view name="dragger" x="250" y="50" bgcolor="0x33de31"
width="50" height="50"
onmousedown="this.dragger.apply()"
onmouseup="this.dragger.remove()"
clickable="true"
options="ignorelayout">
<text align="center" valign="middle">Drag Me</text>
<dragstate name="dragger" />
</view>
</canvas>
Enjoy!