Table of Contents
This section assumes you're familiar with basic LZX concepts such as views, methods, and attributes. Familiarity with objected-oriented programming (OOP) concepts is helpful, but not required. For a primer on classes in LZX see Chapter 28, Classes.
Inheritance allows you to create custom classes from other predefined classes. The advantage is that much of the logic doesn't have to be rewritten every time you want to create a class that does something similar, but in a slightly different way.
A subclass is a class derived from another class. The class
from which it is derived is referred to as its superclass. A
subclass is said to inherit methods and attributes from its
superclass. Visual elements of a superclass, such as
<view>
, are also inherited by each subclass. In LZX,
you use the extends
attribute to the <class>
tag to create subclasses.
<class name="myclass" extends="mysuperclass"> ... </class>
Any class that is that you create without using the
extends
attribute is assumed to be a subclass
of <view>
. All methods and properties from
<view>
are inherited by the subclass. These two
declarations are equivalent:
<class name="myclass"/> <class name="myclass" extends="view"/>
You can only extend one class per class declaration, though the inheritance chain can be arbitrarily deep. Multiple inheritance is not supported; that is to say you cannot create a new class that extends more than one existing classes. Methods, handlers, attributes, and views inside a class are inherited down through each level.
Example 33.1. Inheritance chain
<canvas debug="true" height="125"> <debug x="80" y="5" width="170" height="112"/> <class name="top"> <attribute name="myfoo" value="bar" type="string"/> </class> <class name="middle" extends="top"> <method name="doit"> Debug.write("myfoo is " + this.myfoo); </method> </class> <class name="bottom" extends="middle"> <button text="clickme" onclick="parent.doit()"/> </class> <bottom/> </canvas>
Class definitions can include default values for attributes. For example, a class that extends view can have default
width
and height
attributes:
A subclass can override, that is, provide a different implementation from, a
superclass method, but not for a handler. The overriding method can specify a different set of
arguments from the superclass's method. For example, if your superclass's method
has two arguments such as method(arg1, arg2)
, you can choose to have a
third argument for your subclass such as method(arg1, arg2, arg3)
.
LZX does not support overloading methods. That means that you cannot have different methods, within one class, that have the same name. The runtime only "cares about" the name of the calling method. You will receive a compilation warning if you define two or more methods with the same name in a class definition.
You can, however, have more than one handler for an event, as described in Chapter 29, Methods, Events, Handlers, and Attributes
You can modify inherited attributes by defining a new value using
the <attribute>
tag or by declaring it as
an attribute in the <class>
declaration itself.
Example 33.2. Inheriting Properties
<canvas height="100"> <!-- create a simplelayout so embedded views are laid out --> <!-- on top of each other. --> <class name="class1" layout="class: simplelayout; spacing: 2"> <attribute name="label" value="class1 label" type="string"/> <text>from class1</text> <button text="${classroot.label}"/> </class> <!-- overrides class1's label; inherits text and button --> <class name="class2" extends="class1" label="class2 label"> <text>from class2</text> </class> <!-- inherit class1's text and button; inherit class2's text --> <class name="class3" extends="class2"> <text>from class3</text> </class> <class3/> </canvas>
You can use the super
keyword to invoke a superclass's
method. The super
keyword is useful in instances where you want to
extend the superclass's method without rewriting the same logic. A
method can only use super
to call the method that it
overrides. That is, a subclass's myfunc()
can only call super.myfunc()
, super.myotherfunc()
.
Example 33.3. The super keyword
<canvas debug="true" height="140"> <debug x="60"/> <class name="foo"> <method name="talk"> Debug.write("hello"); </method> <button text="click" onclick="parent.talk()"/> </class> <class name="bar" extends="foo"> <method name="talk"> super.talk(); Debug.write("goodbye"); </method> </class> <bar/> </canvas>
In order to override the behavior of an event handler, you would have the handler call a method, and then override the method
in the subclass or instance. For example, let's say that you wanted to write a handler for the onclick
event that you could override in an instance. In your class definition, you would use this syntax:
<handler name="onclick" method="handleClick">
Then in the instance you would define handleClick()
.
Remember, you can call the original click code in the new method by using the super method:
<method name="handleClick"> super.handleClick(); Debug.write('new click'); </method>
The classroot
property is a convenient short-hand that
refers to the root node of a class instance. It's often used by a
deeply nested view or method that needs access to something near the
root of the class. Though you can equivalently use
parent
, parent.parent
,
parent.parent.parent
, etc. (depending on how deep the
view that contains the reference is nested), using classroot is
usually more readable.
Example 33.4. Classroot example
<canvas debug="true" height="160"> <debug x="155" y="10"/> <!-- class deep --> <class name="deep"> <attribute name="mytext" value="hello, world" type="string"/> <view bgcolor="red" width="150" height="150"> <view bgcolor="green" width="75%" height="75%"> <button text="clickme" width="75%" height="75%"> <!-- classroot is a convenient way to access mytext --> <handler name="onclick"> Debug.write("classroot.mytext: " + classroot.mytext); Debug.write("parent.parent.parent.mytext: " + parent.parent.parent.mytext); </handler> </button> </view> </view> </class> <!-- instance of class deep --> <deep/> </canvas>
Be careful when using classroot
from the root of the
class. If there is no surrounding class, classroot
will
be undefined. Use the this
keyword in code attached to
the root of the class. On the other hand, if an instance of a class
appears inside another class, the classroot
for the
instance will be the root of the surrounding class. Use this feature
as a short-cut to refer to the root of outer classes.
Example 33.5. Referring to outer class's root using classroot
<canvas debug="true" height="200"> <debug height="175"/> <class name="foo"> <method name="doit"> Debug.write("foo: this is [" + this + "]"); Debug.write("foo: classroot is [" + classroot + "]"); Debug.write("foo: classroot.classroot is [" + classroot.classroot + "]"); </method> </class> <!-- boo contains a foo --> <class name="boo"> <foo name="myfoo"/> </class> <!-- goo contains a boo --> <class name="goo"> <boo name="myboo"/> <handler name="oninit"> myboo.myfoo.doit(); Debug.write("-----"); Debug.write("goo: this is [" + this + "]"); // warning will be displayed -- there is no classroot Debug.write("goo: classroot is [" + classroot + "]"); </handler> </class> <!-- Make an instance of goo --> <goo name="mygoo"/> </canvas>
At the risk of belaboring the topic, here's one more example that demostrates that top level instances of a class have no defined classroot. Notice that even though "bar" is a child of "foo", it does not have a defined classroot, because it is a toplevel instance of the bar class.
Example 33.6. classroots and toplevel instances
<canvas debug="true"> <class name="myclass" height="40" bgcolor="blue"> <attribute name="button_label" type="text" value="button"/> <handler name="onclick"> this.handleclick() </handler> <method name="handleclick"> Debug.write("this = " + this + "and classroot is" + classroot); </method> <button name="b1" height="30" text="${parent.button_label}" onclick="Debug.write('classroot of this button is: ' + classroot); parent.handleclick()" /> </class> <class name="another_class" extends="myclass"/> <!-- foo and bar views are top-level instances, so their classroots are null. == The buttons are children of the foo and bar views, respectively, so == == their classroots are defined. --> <myclass id="foo"> <another_class id="bar" bgcolor="red" button_label ="another button" y="25"> <method name="handleclick"> Debug.write("this = " + this + "and classroot is " + classroot); </method> </another_class> </myclass> </canvas>
The <text>
and <inputtext>
tags are unique among the built in
classes in that they can hold textual content:
<canvas height="50" layout="y"> <inputtext>plain text</inputtext> <text><i>styled</i> text</text> </canvas>
The text may contain character text, as well as certain XHTML markup tags. The inputtext tag may contain character text.
Classes that extend the text and inputtext classes may contain XHTML and plain text, respectively. The text content is available as the text attribute of such a class.
Example 33.7. Extending text classes
<canvas height="50" layout="axis: y"> <class name="mytext" extends="text"/> <class name="myinputtext" extends="inputtext"/> <myinputtext>plain text</myinputtext> <mytext><i>styled</i> text</mytext> </canvas>
A user-defined class can also handle text content by defining an
attribute named text
with a value of
text
(for plain text) or html
(for XHTML
text), like <attribute name="text"
type="text">
. There is another text type available called
string
which allows you set a text string as an
attribute, but does not allow text content.
Consider these two classes, where the first is defined using
type="string"
and the second with type="text"
:
<class name="stringText"> <attribute name="text" type="string"/> </class> <class name="textText"> <attribute name="text" type="text"/> </class>
Both classes can be used with a text attribute:
<stringText text="some text"/> <textText text="some text"/>
Only textText
can be used with text content. The
use of stringText below is invalid, and will produce a compilation
warning.
<stringText>some text</stringText> <!-- This is invalid --> <textText>some text</textText> <!-- This is valid -->
Using the html
type declares that the class can accept
html text content, or set through the text
attribute. The text may contain XHTML tags such as <b>
and
<a>
, as in the following program:
Example 33.8. Text type: html
<canvas height="50"> <class name="htmlText"> <attribute name="text" type="html"/> <text resize="true" text="${parent.text}"/> </class> <simplelayout/> <htmlText> <b>bold</b> text declared here with <a href="http://www.openlaszlo.org"><i>anchor</i></a> </htmlText> <htmlText text="<b>bold</b> text set here"/> </canvas>
Note that XHTML markup within a class that is declared with
type="text"
, instead of type="html"
, is
invalid:
<textText>some text</textText> <!-- valid --> <textText>some <i>fancy</i> text</textText> <!-- invalid --> <htmlText>some text</htmlText> <!-- valid --> <htmlText>some <i>fancy</i> text</htmlText> <!-- valid -->
Any text content with a class that is declared without a text
attribute whose type is text
or html
is
invalid:
<class name="noText"/> <noText>some text</noText> <!-- invalid --> <noText>some <i>fancy</i> text</noText> <!-- invalid -->
The attribute name must be text
. It is an error to
use text
and html
as the type of any other
attribute:
<class name="invalidClass"> <attribute name="label" type="text"/> <!-- invalid --> </class>
Classes and views enclosed in classes inherit their font and font
properties (such as fontstyle
and
fontsize
) from their superclass. Also, any
class instance will inherit its font from its enclosing view. A font
can be overridden at any point in a view hierarchy and any subview
from there on will inherit that font.
Example 33.9. Inheriting fonts
<canvas height="50"> <font src="helmetr.ttf" name="Helvetica"/> <font src="helmetb.ttf" name="Helvetica" style="bold"/> <class name="foo"> <!-- view overrides inherited fontstyle to plain --> <view fontstyle="plain" bgcolor="yellow"> <!-- text overrides inherited fontsize to 12 --> <text fontsize="12">hello</text> </view> </class> <class name="bar" extends="foo" layout="axis: y"> <text>goodbye</text> </class> <bar font="Helvetica" fontstyle="bold" fontsize="12"/> </canvas>
In general, instantiation of objects happen using tags. For
instance, assuming <class name="myclass">
is
declared, you can create an instance of that class by writing
<myclass/>
. However, there may be times when you
will need to instantiate an object using script. The script
instantiation syntax for classes looks like:
var myobject = new myclass(parent
,attributes
,children
,instcall
)
where:
parent
is where your object will be
placed in the node hierarchy. If it doesn't matter, then you
can pass null
. If you are creating a subclass of
view
and the parent is null
, the
canvas
will be the parent of this object.
attributes
is a hash of attribute values
that get passed into the object. For example, if you wanted to
instantiate a new view
with a different bgcolor,
width, and height, you could pass in {bgcolor: 0xff0000, width:
50, height: 50}
.
children
is the array of child views this object
encapsulates. The OpenLaszlo Runtime instantiator is responsible for passing in the
children of this object
based on the LZX hierarchy. You will
generally set this to null.
instcall
is a boolean value that determines
when this object will be instantiated. If false, the instantiation
of this object will be immediate, otherwise, its instantiation
will be synchronized with the rest of the view system. See Appendix A, Understanding Instantiation.
All these parameters are optional. Not setting any of these arguments (e.g.,
new myclass()
) is equivalent to new myclass(null,
null, null, 0)
.
The following example shows you how to instantiate a new object through script and add it to another view.
Example 33.10. Script instantiation
<canvas height="120"> <class name="mybox"> <view bgcolor="${parent.bgcolor}" width="50" height="50"/> </class> <view name="redbox" bgcolor="red" width="100" height="100"/> <!-- Create new mybox with cyan bgcolor and place it in canvas.redbox. --> <button x="110" text="add cyan" onclick="if (canvas.redbox['cyan'] == null) new mybox(canvas.redbox, { name: 'cyan', bgcolor: 0x00ffff })"/> <!-- Remove cyan view from redbox. --> <button x="110" y="30" text="remove cyan" onclick="if (canvas.redbox['cyan'] != null) canvas.redbox.cyan.destroy()"/> </canvas>
Views that you create procedurally are not the same as "clones" created by data replication. In fact, data replication overrides procedurally created views. For example:
Declare a view.
Add subviews to it (procedurally), and alter its properties.
Set a datapath on the view (from step 1) that would make it replicate.
Changes made in step 2 will be ignored after replication.
All classes are defined in the global namespace. If you wanted to instantiate
a class dynamically, you can write new
global[classString](...)
. Using the previous example, mybox can be
instantiated like new global['mybox'](canvas.redbox, { bgcolor: 0x00ffff
})
.
Be aware that names for tag classes are not the same as their
JavaScript counterpart; rather, the JavaScript name is lz.[tagname]
. For example, to access a <view>
in script, you would use lz.view
. Thus, to instantiate a view through script, you would write
new lz.view(...)
(not new view(...)
).
An approach you can take to writing classes is just to declare the class tags and have an instance of that class on the canvas. This will give you the framework to see what it looks like while you're building up your class, for example:
<canvas> <class name="myclass"> ... </class> <myclass/> </canvas>
Optionally, you can sketch out a class by writing a view first and then
transforming it into a class. The drawbacks of this approach are that you can't use the
classroot
keyword and attributes can't be declared.
Top-level views inherited from a superclass are placed in the top-level of a subclass. The inherited views from the superclass will be placed first in order. This can be verified by examining the subviews array.
Example 33.11. Inheriting views
<canvas debug="true"> <debug y="215" width="435"/> <class name="one"> <view name="r" bgcolor="red" width="200" height="200"/> </class> <class name="two" extends="one"> <view name="g" bgcolor="green" width="100" height="100"/> </class> <class name="three" extends="two"> <view name="t" bgcolor="teal" width="50" height="50"/> <view name="y" bgcolor="yellow" width="25" height="25"/> </class> <three id="mysubclass" oninit="Debug.write('subviews: ' + this.subviews)"/> </canvas>
Views declared in an instance of a class will be placed in the
top-level of the class unless otherwise declared with the
defaultplacement
attribute. Those views will be
placed with a later order in the subviews array. The
defaultplacement
attribute tells a class where
declared views should be placed in the hierarchy of the class and is
explained in more detail in the next section.
Example 33.12. Inherited view order
<canvas debug="true" height="250"> <debug y="115" width="330"/> <class name="foo"> <view name="r" bgcolor="red" width="100" height="100"/> </class> <foo name="myfoo" oninit="Debug.write('subviews: ' + this.subviews)"> <view name="y" bgcolor="yellow" width="50" height="50"/> </foo> </canvas>
Notice how view y
follows view
r
in its subviews array. If a
<simplelayout>
is placed in view
myfoo
, they will be displayed in order of
r
followed by y
.
Example 33.13. Inherited view order with simplelayout
<canvas debug="true" height="250"> <debug x="75" y="115" width="330"/> <class name="foo"> <view name="r" bgcolor="red" width="100" height="100"/> </class> <foo name="myfoo" oninit="Debug.write('subviews: ' + this.subviews)"> <simplelayout/> <view name="y" bgcolor="yellow" width="50" height="50"/> </foo> </canvas>
The internal structure of a class is generally not visible to its hierarchical children. By default, instances which appear inside a class are made children of the top level instance of the class. This is generally not desirable for container classes. For example:
Example 33.14. Undesired placement
<canvas height="50"> <class name="myframe" extends="view"> <attribute name="bgcolor" value="red"/> <view x="5" y="5" width="${parent.width-10}" height="${parent.height-10}" bgcolor="#FFFFCC"/> </class> <!-- make an instance of myframe with text inside it--> <myframe width="220" height="20"> <text>This is some text</text> </myframe> </canvas>
This behavior can be changed using the
defaultplacement
attribute or the
determinePlacement()
method. Using
defaultplacement
is simple — this is a
class attribute that identifies by name the subview where a child
should be attached. The child will be attached to the first subview
with a matching name. If none is found, the child is placed as a
subview in the top-level node of the class, as would have happened if
no defaultplacement
had been specified.
Be aware that the defaultplacement
attribute
should always be declared in an attribute with
type="string"
.
Example 33.15. Placing a child in desired subview
<canvas height="50"> <class name="myframe" extends="view"> <attribute name="bgcolor" value="red"/> <!-- child views of class instances will be placed in the first view called insideview --> <attribute name="defaultplacement" value="insideview" type="string"/> <view x="5" y="5" width="${parent.width-10}" name="insideview" height="${parent.height-10}" bgcolor="#FFFFCC"/> </class> <!-- make an instance of myframe with text inside it--> <myframe width="220" height="50"> <text>This is some text</text> </myframe> </canvas>
Elements declared in a class are not considered for placement, but children in subclasses or class instances will be.
Example 33.16. Defaultplacement
<canvas height="150"> <class name="myframe" extends="view"> <attribute name="bgcolor" value="red"/> <attribute name="defaultplacement" value="'insideview'"/> <view x="5" y="5" width="${parent.width-10}" name="insideview" height="${parent.height-10}" bgcolor="#FFFFCC"/> <!-- this view is not affected by defaultplacement --> <!-- because it's declared in the class. --> <view x="5" y="${parent.height}" name="anotherview" width="${parent.width-10}" height="10" bgcolor="blue"/> </class> <class name="subframe" extends="myframe"> <!-- the layout and text will be placed in insideview of myframe --> <simplelayout axis="y"/> <text bgcolor="teal">subframe text</text> </class> <myframe width="220" height="50"> <!-- this will be placed in insideview --> <text>This is some text</text> </myframe> <subframe width="220" height="50" y="70"> <text bgcolor="green">More subframe text</text> </subframe> </canvas>
A layout declared as an attribute will be considered for
placement. This is often the desired behavior because it makes it easy
for subclasses and class instances to modify the layout for views
inside the default placement. To override this behavior, a
layout
attribute can be set with a non-existing
placement
(e.g., placement: null
). The
placement
attribute tells an element's
container where it should go within the container's internal
hierarchy. If the container has a
defaultplacement
, the placement
value has precedence. Alternatively, you can make sure that a layout
isn't handled by defaultplacement by declaring it as a tag element in
the class.
Example 33.17. Layout placement
<canvas> <!-- the layout attribute will be placed in the red view --> <class name="myplacement" defaultplacement="'red'" layout="axis: x; spacing: 5"> <!-- this layout element applies to views inside of class --> <simplelayout spacing="10"/> <view name="red" bgcolor="red" width="150" height="150"/> <view name="yellow" bgcolor="yellow" width="150" height="150"/> </class> <myplacement> <!-- placement overrides defaultplacement --> <view name="blue" bgcolor="blue" width="50" height="50" placement="yellow"/> <!-- green and teal will be placed in red --> <view name="green" width="50" height="50" bgcolor="green"/> <view name="teal" width="50" height="50" bgcolor="teal"/> </myplacement> </canvas>
A child placed using defaultplacement
or
placement
will often have two parent types. The
parent
is the reference to the node that was passed as
the child's ancestor in the constructor, e.g., new
childClass(parent, args)
. If the child was created by declaring
it in a tag, the parent will be its lexical parent. (Its lexical parent
is the tag that encloses it.)
The immediateparent
refers to the node where the
child is actually placed at runtime. Its value will be the same as
parent
if no value is assigned to the placement
attribute.
Example 33.18. Parent vs. immediateparent
<canvas debug="true" height="200"> <debug x="155"/> <class name="container" defaultplacement="'red'"> <view name="red" bgcolor="red" width="150" height="150"/> </class> <!-- yellow's parent is top and its immediateparent --> <!-- is red, since that's where it's actually placed. --> <container name="top"> <view name="yellow" bgcolor="yellow" width="50" height="50"> <handler name="oninit"> Debug.write('parent: ', this.parent); Debug.write('immediateparent: ', this.immediateparent); </handler> </view> </container> </canvas>
There may be instances a class needs a reference to the default placement node. A good trick is to search the subnodes of the class until it's found.
Example 33.19. Obtaining a reference to the defaultPlacement node
<canvas debug="true" height="200"> <debug x="155"/> <class name="container" defaultplacement="'red'"> <attribute name="contentview" value="null" type="expression"/> <method name="init"> super.init(); // get a reference to the content node if ( this.contentview == null ) { if ( this.defaultplacement != null ){ this.contentview = this.searchSubnodes( "name" , this.defaultplacement ); } else { this.contentview = this; } } Debug.write("content view", this.contentview); </method> <view name="green" bgcolor="green" width="100" height="100"> <view name="yellow" bgcolor="yellow" width="50%" height="50%"> <view name="red" bgcolor="red" width="50%" height="50%"/> </view> </view> </class> <container name="top"/> </canvas>
A node calls its determinePlacement()
method to
determine the immediateparent
of a child. This method
will only be called for subnodes which have a placement attribute, or
for all subnodes if this node has a non-null
defaultplacement
. The
placement
attribute of a subnode overrides a
parent's defaultplacement
. This method looks
for a subnode with the name given in the placement
parameter, and returns that node. If no such named node exists, it
returns this
. The code essentially looks like:
<!-- subnode: the child node to place --> <!-- placement: the node to place the subnode --> <!-- args: init args of the child subnode --> <method name="determinePlacement" args="subnode, placement, args"> // ignore placement if set if ( args.ignoreplacement ){ return this; } if ( placement == null ){ var p = null; } else { var p = this.searchSubnodes( "name" , placement ); } return p == null ? this : p; </method>
A subclass might implement this method to cause the
placement
parameter to have a different behavior or
additional effects. For instance, a subnode could have
parent
and immediateparent
be the
same.
Example 33.20. Overriding determinePlacement
<canvas debug="true" height="200"> <debug x="155"/> <class name="container" defaultplacement="'red'"> <!-- setting subnode's parent to be the same as immediateparent --> <method name="determinePlacement" args="subnode, place, args"> var p = super.determinePlacement(subnode, place, args); subnode.parent = p; return p; </method> <view name="blue" bgcolor="blue" width="100" height="100"> <view name="red" bgcolor="red" width="150" height="150"/> </view> </class> <container name="top"> <view name="yellow" bgcolor="yellow" width="50" height="50"> <handler name="oninit"> Debug.write('parent: ', this.parent); Debug.write('immediateparent: ', this.immediateparent); </handler> </view> </container> </canvas>
When writing complex classes, a deep understanding of how classes are constructed and initialized is essential. Several steps are involved before a class instance is fully initialized. Describing this process is out of the scope of this chapter, but important methods and events that are involved, and the sequence in which they are invoked, will be discussed here. See Appendix A, Understanding Instantiation for a more in-depth discussion.
The construct()
method is called as early as
possible in constructing the view system. It is invoked before any arguments have been applied. This is the method to override
in lieu of writing a
class constructor for your LZX class. If you do override the construct method, be sure to invoke,
the superclass method, or results will be extremely
unpredictable. Among other things, the construct method is the method where the class being constructed places itself in its
container by calling its parent's
determinePlacement()
method. If the superclass
construct method isn't called, the class instance may not be placed
correctly.
Alternatively, you can use the onconstruct
event,
which is sent out by the instantiator after construct()
has been called. The onconstruct
happens right at the end of
the instantiation process, but before any subnodes have been created
or references resolved.
Keep in mind that construction happens top-down (parent to subviews), whereas initialization happens bottom-up (subviews to ancestor).
Example 33.21. Construction and initialization
<canvas debug="true" height="180"> <debug height="160"/> <class name="container"> <!-- Don't forget to call super.construct(parent,args)!! --> <method name="construct" args="parent,args"> Debug.write("container construct", parent, args); super.construct(parent, args); </method> <!-- The onconstruct event --> <handler name="onconstruct" args="v"> Debug.write("container onconstruct", v); </handler> <method name="init"> Debug.write("container init"); </method> <handler name="oninit"> Debug.write("container oninit"); </handler> </class> <container> <view name="outside" oninit="Debug.write('outside oninit')"> <view name="inside" oninit="Debug.write('inside oninit')"/> </view> </container> </canvas>
Following instantiation (i.e., after the onconstruct
is sent) and if there are child nodes, the
createChildren()
method is called. This method takes an
array of child objects as a parameter. Each child object has three
properties:
Example 33.22. createChildren()
<canvas debug="true" height="180"> <debug height="160"/> <class name="container"> <handler name="onconstruct" args="v"> Debug.write("container onconstruct", v); </handler> <method name="createChildren" args="c"> Debug.write("container createChildren", c); Debug.write(" c[0].name:", c[0].name); Debug.write(" c[0].attrs:", c[0].attrs); Debug.write(" c[0].children:", c[0].children); super.createChildren(c); </method> </class> <container> <view name="outside"> <view name="inside"/> </view> </container> </canvas>
In summary, you can expect the basic timing order of method and event calls to look like:
classroot
a short-hand that refers to the root node of the instance of a class.
extends
the keyword used in a class declaration to create a subclass.
the concept of classes automatically containing the variables and methods defined in their superclass.
the action that creates an instance of a class or object.
using one identifier to refer to multiple functions.
to provide a different method implementation in the subclass from its superclass.
the class that derives from another class.
super
keyword operator that allows a subclass to invoke it's superclass's method.
the class that a subclass derives its attributes and methods from.
Copyright © 2002-2007 Laszlo Systems, Inc. All Rights Reserved. Unauthorized use, duplication or distribution is strictly prohibited. This is the proprietary information of Laszlo Systems, Inc. Use is subject to license terms.