Create Custom Layouts

First, I must preface that I am new to ECMAScript 5.

I’ve gone through the O’Reilly 6th edition of JavaScript (which was very
helpful), are there any other reference guides which would be good to
read?

The JS class system seems a bit haphazard; I mean, there doesn’t seem to be a single “right way” to implement subclasses.

My desire is to create a custom layout. I believe that we will end up creating multiple layouts to handle the different visualizations we are going to be making.

I settled on using this logic, which sees to be the cleanest way to implement a subclass.

        function CustomLayout() {
            go.Layout.call(this);
        };
        CustomLayout.prototype = Object.create(go.Layout.prototype);
        CustomLayout.prototype.doLayout = function (coll) {
            alert("I am called");
        };
        myDiagram.layout = $(CustomLayout);

This caused the constructor to be called, but the doLayout method is never called.

Perhaps I am missing a basic understanding of how JS subclasses work.

Would it be possible for somebody to post a stub or simple example of a custom layout?

We are not exposing how classes are defined, in the hopes that the vast majority of users will never need it. As you say, subclassing in JavaScript can be hazardous.

For most customization, programmers will be able to set properties, including functional properties. We have added some of these recently to the API.

And in looking at your code I thought that one step was missing, but it actually appeared to work. Until I tried using the layout in a Group – you also need to set the constructor. (We are defining classes in a manner that is slightly different from what you have read about for JavaScript.)

But that’s not all that’s missing – if you add any data members, that state will not be copied when making a copy of the object (the Layout in this case). Doing that would require an override of a method that is not exposed at present.

[code] function VerticalLayout() {
go.Layout.call(this);
};

VerticalLayout.prototype = Object.create(go.Layout.prototype);
VerticalLayout.prototype.constructor = VerticalLayout;

VerticalLayout.prototype.doLayout = function (coll) {
if (!coll) throw new Error(“doLayout must not be passed null or undefined”);
var diagram = this.diagram;
if (diagram !== null) diagram.startTransaction(‘Layout’);
var x = this.arrangementOrigin.x;
var y = this.arrangementOrigin.y;
var it;
if (coll == diagram) it = diagram.nodes.iterator;
else if (coll == this.group) it = this.group.memberParts;
else it = coll.iterator;
while (it.next()) {
var part = it.value;
// only do Nodes or nested Groups
if (!(part instanceof go.Node)) continue;
// only do top-level nodes
if (coll == diagram && !part.isTopLevel) continue;
// place
part.move(new go.Point(x, y));
// and leave extra space for next node
y += 20 + part.actualBounds.height;
}
if (diagram !== null) diagram.commitTransaction(‘Layout’);
this.validLayout = true;
};[/code]
At the moment this code works, but in general users cannot subclass until we publish and document everything that is needed.

Will the “release” version allow access to the method needed to copy the properties?

Or, a better question is if the release version allow for custom layouts?

Yes, it really ought to. We’re still working out the details.

The first goal is to try to put as much extension functionality into properties that we can.
But the code I posted above should work for your purposes.
I intentionally filled out the body of doLayout with some “real” code.