Hi James,

I'm trying to understand waypoint by going through your code. I must say it is not self explanatory so let me try to explain it my own words so you can correct it.

1) If the immediate parent is already a waypoint exit

2) If parent is canvas exit

3) Waypoint creates a "name registry" to first of it's ancestors (excluding parent) to which applies:
- It already is a "name registry"
- it has id attribute defined
- it's nodeLeve == 0 (= canvas)

To this "name registry" it adds the mapping
"named attribute value" --> parent

4) It also creates a "name registry" to it's parent and to this registry it only creates mapping
"parent" --> reference to the ancestor mentioned in the previous point

So applying these steps to your example it would seem that the first waypoint tag creates the "name registry" to the parent of the class foo instead to the root node of class foo.

So there must be some mistake in my understanding.

<class name="foo">

    <waypoint/>

    <handler name="oninit">
        Debug.write("this._.one", this._.one);
    </handler>

    <view>
        <view>
            <view>
                <waypoint named="one"/>
            </view>
        </view>
    </view>
</class>

jamesr wrote:
Welll, after receiving the excellent news that Henry will be promoting mixins to a first class laszlo construct, wherein after completion i'll be able to rewrite and share the enabling concepts i currently have in the officially sanctioned format. I'm loving that, however, since I have to wait a week or so before mixins can support what i currently do without them, rather then waiting i would like to start discussing the mixins i will offer, one by one, and hopefully have a nice discussion about why, when, and how to use these new techniques while not presenting too much info at once.

In that spirit, here are a list of the most important traits (mixins) i'll be introducing; some of the names might change before the official release:

waypoint
interesting
interested
multiclickable
dragmatchable
registerDropzone
dropable
moveble
resizeable
verticallysizeable
frontmost
hindmost
openable
selectable
upperShadow
shadowed

Some of these are truly new areas of study, while some (like, say, selectable) are more obvious exercises and I expect to add many more traits for UI paradigms. I've not scratched the surface of useful traits and what you see was more or less what was required of me by contract work.

For our first discussion, i'd like to introduce something special, waypoints.

Waypoints are a major new approach to navigating deeply nested hierarchies and it is both a good example of a mixin while and adds a feature that i think many will come to use every day and in every project. It removes the nesscessity to have typical "parent.parent.parent" calls and allows a programmer to refactor code for appearance and containment without damaging references, as would be the case, for instance, if a new view was wrapped around an existing view, which either requires using an ID, or altering every reference in the program with every change, resulting in "brittle" code. No longer.

Below is a complete code listing of the waypoint trait as-it-exists, preceded by a short but complete example. it's not a big piece of code, just a very powerful piece, as you'll see. I'll be happy to answer all questions anyone has about it - which will also help me to see how much the community in general understands the approach. I developed this class over two years ago, and i would absolutely *refuse* to develop without it now, but this is it's first public release. Although it might take time to fully understand the ramifications this class brings to the laszlo world it is very worth it. Enjoy!

Waypoint code listing:

<!-- Author: James Robey, [email protected]. Licensed under the MPL .
          see http://code.google.com/p/viewablegroup for more.

        Waypoints:
A very useful namespace mechanism. The waypoint class allows for "deep" navigation of nested namespaces by causing an entry specified by the "named" attribute to be added to the first waypoint encoutered above it. A waypoint will attach itself to the first valid recipientm which is the canvas, a node with an ID, or another waypoint anointed node.
               Example:
               <class name="foo">
           <waypoint/>
                     <handler name="oninit">
               Debug.write("this._.one", this._.one);
           </handler>
                     <view>
               <view>
                   <view>
                       <waypoint named="one"/>
                   </view>
               </view>
           </view>
        </class>
          -->
      <class name="waypoint" extends="node" initstage="early">
<!-- if this attribute is specified, then a waypoint by this name will be added to the waypoint parent -->
       <attribute name="named" type="string"/>

<!-- at construct time, determine the waypoint parent and add references, as/if needed -->
       <method name="construct" args="p, a">
           <![CDATA[
               super.construct(p, a);
                             //retrieve values from the tag
               var named = a['named'];
               var np = p.parent;
//is this object already a way point? do no more.
               if(!p['_'])
                   p['_'] = new Object;
else return; //we need do no more for the canvas element
               if(p == canvas)
                   return;
//find out which node will receive the new waypoint
               while(1){
//have we found a potential parent waypoint? We either find it above or use the topmost node.
                   if((np['_'] || np['id'] || np.nodeLevel == 0)){
//initialize space ('_') to hold waypoints if this is a new waypoint parent.
                       if(np['_'] == undefined) np._ = {};

//if no name given make a name based on the number of other nameless waypoints //otherwise ensure the name doesn't overwrite anything in the target waypoint space.
                       if(!named){

// if __waypointCount is not defined initialize it to zero, otherwise increment np.__waypointcount = np['__waypointcount'] != undefined ? np.__waypointcount + 1 : 0; // and use value that to generate a unique name
                           named = "unnammed_waypoint"+np.__waypointcount;
}else if(np._[named] != undefined){ Debug.warn('waypoint overwritten:', np, 'name', named);
                       }

//Add this node to a waypoint parent, add the waypoint to this node ("parent"), then break
                       np._[named] = p;
//record the parent waypoint to this tag
                       p._.parent = np;
                       break;
                   }

//...or just keep looking up the tree until we find a good target.
                   np = np.parent;
               }
//we don't need the this anymore, it's done it's job (cyclic GC? investigate)
           ]]>
       </method>
   </class>

what do you think? Thanks for reading,

Sincerely,     James

Reply via email to