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 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 height="125" width="100%"> 
  <class name="top">
    <attribute name="myfoo" value="bar" type="string"/>
  </class> 
  <class name="middle" extends="top">
    <method name="doit">
      message.addText("\nmyfoo is " + this.myfoo);
    </method>
  </class>
  <class name="bottom" extends="middle">
    <button text="clickme" onclick="parent.doit()"/>
  </class>
  <text id="message" y="30" multiline="true"/>
  <bottom/>
</canvas>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2007, 2008 Laszlo Systems, Inc.  All Rights Reserved.             *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
                  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.
When a subclass defines a method with the same name as the super class, it overrides or replaces the superclass method. If the superclass method's effect is desired the subclass method must invoke it using a super call. You cannot change the arguments when you override a method: they must match.
When a subclass defines a handler with the same name as the superclass, it adds to the superclass handler. Both will be invoked when the named event is sent.
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" width="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>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2007, 2008 Laszlo Systems, Inc.  All Rights Reserved.                   *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
                  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 height="140" width="100%">
  <class name="foo">
    <method name="talk">
      message.addText("\nhello");
    </method>
    <button text="click" onclick="parent.talk()"/>
  </class>
  <class name="bar" extends="foo">
    <method name="talk">
      super.talk();
      message.addText("\ngoodbye");
    </method>
  </class>
  <text id="message" y="30" multiline="true"/>
  <bar/>
</canvas>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2007, 2008 Laszlo Systems, Inc.  All Rights Reserved.                   *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
                  
                  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.debug('new click');
     </method>
Use the <setter> tag to declare or override 
                        attribute setter methods. Note that this functionality is new, and you may have to
                        change your code written for OpenLaszlo 4.1 and earlier. For example, this 4.1.x code:
               
      <method name="setY" args="y" > 
         super.setY( Math.max(parent.arrowbuttonheight-1 , Math.min( y , parent.height - (parent.thumbheight + parent.arrowbuttonheight)))); 
      </method>    
   Would need to be changed to:
      <setter name="y" args="y" >
         super.setAttribute('y', Math.max(parent.arrowbuttonheight-1 , Math.min( y , parent.height - (parent.thumbheight + parent.arrowbuttonheight))));
      </setter>
   Here's another example. If you had this code in OpenLaszlo 4.1 or earlier:
      <text x="${Math.round((parent.width-this.width)/2)}" font="vera_super_bold" fgcolor="0x4d4d4d" datapath="@username" resize="true">
         <method name="setText">
            if (typeof(this.datapath.data) != 'undefined') {
               super.setText(this.datapath.data + "'s information");
            }
         </method>
      </text>
   You would change it to:
      <text x="${Math.round((parent.width-this.width)/2)}" font="vera_super_bold" fgcolor="0x4d4d4d" datapath="@username" resize="true">
         <setter name="text">
            if (typeof(this.datapath.data) != 'undefined') {
               super.setAttribute('text', this.datapath.data + "'s information");
            }
         </setter>
      </text>
   LFC setter methods like setWidth(), setHeight(), 
                        and setBGColor() are now deprecated. They continue to 
                        work but if you use them, a warning message is displayed in the debugging console. 
               
Some LFC components mimic text objects. For example, <edittext> is similar to <inputtext> but it does not extend a text object.
                  
This is what the text attribute used to look like in <edittext>:
                  
      <attribute name="text" type="text" setter="setText(text)"/>
      ...
      <method name="setText" args="t">
         this.text = t;
         if (this._initcomplete) {
            this.setValue(t, true);
            this.field.setAttribute('text', this.value);
            if (this['ontext']) this.ontext.sendEvent();
            } 
         else {
            this._initialtext = t;
         }
      </method>
   As you can see, this allows setting the text object via setAttribute('text',...) and setText(). To make this code run a little faster (by removing a call to setText() from the setter), and follow how the LFC does it, this was rewritten to use the <setter> tag:
                  
      <attribute name="text" type="text"/>
      ...
      <method name="setText" args="t">
         Debug.warn("edittext.setText is deprecated. Use setAttribute instead");
         this.setAttribute('text', t);
      </method>
      
      <setter name="text" args="t">
         this.text = t;
         if (this._initcomplete) {
            this.setValue(t, true);
            this.field.setAttribute('text', this.value);
            if (this['ontext']) this.ontext.sendEvent();
            } 
         else {
            this._initialtext = t;
         }
      </setter>
   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
<canvas height="200" width="100%">
  <class name="deep">
    <attribute name="mytext" value="hello, world" type="string"/>   
    <view bgcolor="red" width="250" 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">
            message.addText("\nclassroot.mytext: " + classroot.mytext);
            message.addText("\nparent.parent.parent.mytext: " + 
            parent.parent.parent.mytext);
          </handler>
        </button>       
      </view>     
    </view>
    <text id="message" y="140" multiline="true"/>
  </class>
  <deep/>
</canvas>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2007, 2008 Laszlo Systems, Inc.  All Rights Reserved.             *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
                  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" width="100%">
  <debug height="175"/> 
  <class name="foo">
    <method name="doit">
      Debug.debug("foo: this is [%w]", this);
      Debug.debug("foo: classroot is [%w]", classroot);
      Debug.debug("foo: classroot.classroot is [%w]", 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.debug("-----");
      Debug.debug("goo: this is [%w]", this);
      // error will be displayed -- there is no classroot
      Debug.debug("goo: classroot is [%w]", classroot);
    </handler>
  </class>
  <!-- Make an instance of goo -->
  <goo name="mygoo"/>
</canvas>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2007, 2008 Laszlo Systems, Inc.  All Rights Reserved.                   *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
                  At the risk of belaboring the topic, here's one more example that demonstrates 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. Classroot and top level instance
<canvas debug="true" width="100%">
  <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.debug("this = %w, and classroot is %w", this, classroot);
    </method>
    <button name="b1" height="30" text="${parent.button_label}" onclick="Debug.debug('classroooot of this button is: %#w', 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.debug("this = %w, and classroot is %w", this, classroot);
      </method>
    </another_class>
  </myclass>
</canvas>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2007, 2008 Laszlo Systems, Inc.  All Rights Reserved.             *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
                  This page describes a basic usage of <mixin>. For a more advanced usage, see the Reference.
            
<mixin> is like <class>
                        but rather than creating something you can instantiate, <mixin> creates a template that can be
                        mixed in (added to) more than one other class. A
                        <mixin> is like an interface, but it is allowed to have
                        state and implementation. 
            
<mixin> is an advanced feature. To add a
                        <mixin> to a class you say: 
            
   <class name="icecream" ... /> 
   <class name="walnuts" ... /> 
   
   <mixin name="toppings"> 
      <attribute name="sauce" type="color" value="lavender" /> 
      <attribute name="whippedcream" type="boolean" value="true" /> 
      <attribute name="cherry" type="boolean" value="true" /> 
      ... 
   </mixin> 
   
   <class name="sundae" extends="icecream" with="toppings /> 
   
   <sundae name="chocfulla" 
      flavor="honeydew" 
      sauce="lemonchiffon"> 
      <walnuts ground="true" /> 
   </sundae> 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 width="100%" 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>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2007, 2008 Laszlo Systems, Inc.  All Rights Reserved.                   *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
                  A user-defined class can also handle text content by defining an
               attribute named text with a type 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" width="100%">
  <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>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2007, 2008 Laszlo Systems, Inc.  All Rights Reserved.                   *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
                  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" width="100%">
  <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>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2007, 2008 Laszlo Systems, Inc.  All Rights Reserved.                   *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
                  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 lz.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 parameters are optional. Not setting any of these arguments (for example, new lz.myclass()) 
                     is equivalent to new lz.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" width="100%">
  <class name="mybox">
    <view bgcolor="${parent.bgcolor}" width="50" height="50"/>
  </class>
  
  <view name="redbox" bgcolor="red" width="100" height="100"/>
  
  <!-- Create new lz.mybox with cyan bgcolor and place it in canvas.redbox. -->
  <button x="110" text="add cyan" onclick="if (canvas.redbox['cyan'] == null) new lz.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>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2008 Laszlo Systems, Inc.  All Rights Reserved.                   *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
                  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.
Be aware that names for tag classes are not the same as their
                  JavaScript counterpart; rather, the JavaScript name is lz[tagname]. For example, you can create and instantiate a class someclass like this:
            
// create the class
<class name="someclass">
   //class definition
</class>
      
// make one
new lz.someclass;
   
//or
new lz['someclass'];You can instantiate a variable class like this:
var theclass = 'someclass'; // make one new lz[theclass];
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" width="100%">
  <debug y="215"/>
  <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.debug('subviews: %w', this.subviews)"/>
</canvas>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2007, 2008 Laszlo Systems, Inc.  All Rights Reserved.             *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
                     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" width="100%">
  <class name="foo">
    <view name="red" bgcolor="red" width="100" height="100"/>
  </class> 
  <foo name="myfoo" oninit="Debug.debug('subviews: %w', this.subviews)">
    <view name="yellow" bgcolor="yellow" width="50" height="50"/>
  </foo>
</canvas>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2008 Laszlo Systems, Inc.  All Rights Reserved.                   *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
                     Notice how view yellow follows view
                  red 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" width="100%">
  <debug x="75" y="115"/>
  <class name="foo">
    <view name="red" bgcolor="red" width="100" height="100"/>
  </class>
  <foo name="myfoo" oninit="Debug.debug('subviews: %w', this.subviews)">
    <simplelayout/>
    <view name="yellow" bgcolor="yellow" width="50" height="50"/>
  </foo>
</canvas>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2007, 2008 Laszlo Systems, Inc.  All Rights Reserved.             *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
                     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" width="100%">
  <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>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2007, 2008 Laszlo Systems, Inc.  All Rights Reserved.                   *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
                     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 the desired subview
<canvas height="50" width="100%">
  <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>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2007, 2008 Laszlo Systems, Inc.  All Rights Reserved.                   *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
                     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="160" width="100%">
  <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>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2008 Laszlo Systems, Inc.  All Rights Reserved.                   *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
                     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 width="100%">
  <!-- 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>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2007, 2008 Laszlo Systems, Inc.  All Rights Reserved.                   *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
                        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. Imediateparent
<canvas debug="true" height="200" width="100%">    
  <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="thetop">
    <view name="yellow" bgcolor="yellow" width="50" height="50">
      <handler name="oninit">
        Debug.debug("parent: %w", this.parent);
        Debug.debug('immediateparent: %w', this.immediateparent);
      </handler>
    </view>
  </container>
</canvas>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2008 Laszlo Systems, Inc.  All Rights Reserved.                   *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
                        There may be instances where 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 reference to the defaultplacment node
<canvas debug="true" height="200" width="100%">
  <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.debug("content view %w", 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="thetop"/>
</canvas>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2008 Laszlo Systems, Inc.  All Rights Reserved.                   *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
                        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" width="100%">
  <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="thetop">
    <view name="yellow" bgcolor="yellow" width="50" height="50">
      <handler name="oninit">
        Debug.debug("parent: %w", this.parent);
        Debug.debug("immediateparent: %w", this.immediateparent);
      </handler>
    </view>
  </container>
</canvas>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2008 Laszlo Systems, Inc.  All Rights Reserved.                   *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
                        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" width="100%">
  <debug height="160"/>
  <class name="container">
    <!-- Don't forget to call super.construct(parent,args)!! -->
    <method name="construct" args="parent,args">
      Debug.debug("container construct %w %w", parent, args);
      super.construct(parent, args);
    </method>
    <!-- The onconstruct event -->
    <handler name="onconstruct" args="v">
      Debug.debug("container onconstruct %w", v);
    </handler>
    <method name="init">
      Debug.debug("container init");
    </method>
    <handler name="oninit">
      Debug.debug("container oninit");
    </handler>
  </class>
  <container>
    <view name="outside" oninit="Debug.debug('outside oninit')">
      <view name="inside" oninit="Debug.debug('inside oninit')"/>
    </view>        
  </container>
</canvas>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2007, 2008 Laszlo Systems, Inc.  All Rights Reserved.             *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
                     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" width="100%">
  <debug height="160"/>  
  <class name="container">
    <handler name="onconstruct" args="v">
      Debug.format("container onconstruct %w", v);
    </handler>   
    <method name="createChildren" args="c">
      Debug.debug("container createChildren", c);
      Debug.debug("    c[0].name: %w", c[0].name);
      Debug.debug("    c[0].attrs: %w", c[0].attrs);
      Debug.debug("    c[0].children: %w", c[0].children);
      super.createChildren(c);
    </method>
  </class>
  <container>
    <view name="outside">
      <view name="inside"/>
    </view>
  </container>
</canvas>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2007, 2008 Laszlo Systems, Inc.  All Rights Reserved.             *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
                     In summary, you can expect the basic timing order of method and event calls to look like:
classroota short-hand that refers to the root node of the instance of a class.
extendsthe 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.
superkeyword 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-2010 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.