here is the tree code:
var tree = {
myDiagram: null,
nodeDataArray : null,
init:function () {
if (window.goSamples) goSamples(); // init for these samples -- you don't need to call this
var $ = go.GraphObject.make; // for conciseness in defining templates
tree.myDiagram =
$(go.Diagram, "treeDiv",
{
allowMove: false,
allowCopy: false,
allowDelete: false,
allowHorizontalScroll: false,
maxSelectionCount: 1,
layout:
$(go.TreeLayout,
{
alignment: go.TreeLayout.AlignmentStart,
angle: 0,
compaction: go.TreeLayout.CompactionNone,
layerSpacing: 16,
layerSpacingParentOverlap: 1,
nodeIndent: 2,
nodeIndentPastParent: 0.88,
nodeSpacing: 0,
setsPortSpot: false,
setsChildPortSpot: false
})
});
tree.myDiagram.nodeTemplate =
$(go.Node,
{ // no Adornment: instead change panel background color by binding to Node.isSelected
selectionAdorned: false,
isTreeExpanded: false,
// a custom function to allow expanding/collapsing on double-click
// this uses similar logic to a TreeExpanderButton
doubleClick: function(e, node) {
var cmd = tree.myDiagram.commandHandler;
if (node.isTreeExpanded) {
if (!cmd.canCollapseTree(node)) return;
} else {
if (!cmd.canExpandTree(node)) return;
}
e.handled = true;
if (node.isTreeExpanded) {
cmd.collapseTree(node);
} else {
cmd.expandTree(node);
}
}
},
$("TreeExpanderButton",
{
width: 14,
"ButtonBorder.fill": "whitesmoke",
"ButtonBorder.stroke": null,
"_buttonFillOver": "rgba(0,128,255,0.25)",
"_buttonStrokeOver": null
}),
$(go.Panel, "Horizontal",
{ position: new go.Point(16, 0) },
new go.Binding("background", "isSelected", function (s) { return (s ? "lightblue" : "white"); }).ofObject(),
$(go.Picture,
{
width: 18, height: 18,
margin: new go.Margin(0, 4, 0, 0),
imageStretch: go.GraphObject.Uniform
},
// bind the picture source on two properties of the Node
// to display open folder, closed folder, or document
new go.Binding("source", "isTreeExpanded", tree.imageConverter).ofObject(),
new go.Binding("source", "isTreeLeaf", tree.imageConverter).ofObject()),
$(go.TextBlock,
{ font: '9pt Verdana, sans-serif' },
new go.Binding("text", "title", function(s) { return s; }))
), // end Horizontal Panel
{
toolTip: // define a tooltip for each node that displays the color as text
$(go.Adornment, "Auto",
$(go.Shape, { fill: "#FFFFCC" }),
$(go.TextBlock, { margin: 4, maxSize: new go.Size(300,80), wrap: go.TextBlock.WrapFit },
new go.Binding("text", "title", function(s) {return s;}))
) // end of Adornment
}
); // end Node
// without lines
tree.myDiagram.linkTemplate = $(go.Link);
// // with lines
// myDiagram.linkTemplate =
// $(go.Link,
// { selectable: false,
// routing: go.Link.Orthogonal,
// fromEndSegmentLength: 4,
// toEndSegmentLength: 4,
// fromSpot: new go.Spot(0.001, 1, 7, 0),
// toSpot: go.Spot.Left },
// $(go.Shape,
// { stroke: 'gray', strokeDashArray: [1,2] }));
if (false) {
// create a random tree
//tree.nodeDataArray = [{ key: 0 }];
var max = 30;
var count = 0;
while (count < max) {
count = tree.makeTree(3, count, max, tree.nodeDataArray, tree.nodeDataArray[0]);
}
}
// tree.myDiagram.model = new go.TreeModel(nodeDataArray);
},
loadTreeArray: function(jsonObj) {
var arr = jsonObj.TargetsTree;
if (!arr) {
alert('Cannot find array of tree data.');
return false;
} else {
if (tree.nodeDataArray) {
tree.nodeDataArray.length = 0; // this clears the array.
}
tree.nodeDataArray = new Array();
var i = 0;
var len = arr.length;
while (i < len) {
var obj = arr[i];
console.log('json: key: ' + obj.key + ' parent: ' + obj.parent + ' code: ' + obj.code + ' title: ' + obj.title);
tree.nodeDataArray.push(obj);
i++;
}
}
return true;
},
drawTree: function() {
tree.myDiagram.model = new go.TreeModel(tree.nodeDataArray);
},
selectedCode:function() {
// assumes only 1 selected.
// (tree.myDiagram.selection.each(function(part) {if (part instanceof go.Node) {return('selected ' +
part.data.key);}}));
// or tree.myDiagram.iterator.each(function(part) {if (part instanceof go.Node) {console.log('selected ' +
part.data.key);}});
var it = tree.myDiagram.selection.iterator;
while (it.next()) {
var part = it.value;
var code = part.data.code;
return code;
}
return null;
},
selectedTitle:function() {
// assumes only 1 selected.
// (tree.myDiagram.selection.each(function(part) {if (part instanceof go.Node) {return('selected ' +
part.data.key);}}));
// or tree.myDiagram.iterator.each(function(part) {if (part instanceof go.Node) {console.log('selected ' +
part.data.key);}});
var it = tree.myDiagram.selection.iterator;
while (it.next()) {
var part = it.value;
var ttl = part.data.title;
return ttl;
}
return null;
},
numSelected: function() {
return tree.myDiagram.selection.iterator.count;
},
makeTree:function (level, count, max, nodeDataArray, parentdata) {
var numchildren = Math.floor(Math.random() * 10);
for (var i = 0; i < numchildren; i++) {
if (count >= max) return count;
count++;
var childdata = { key: count, parent: parentdata.key , code: 'code for ' + count};
nodeDataArray.push(childdata);
if (level > 0 && Math.random() > 0.5) {
count = tree.makeTree(level - 1, count, max, nodeDataArray, childdata);
}
}
return count;
},
// takes a property change on either isTreeLeaf or isTreeExpanded and selects the correct image to use
imageConverter:function (prop, picture) {
var node = picture.part;
if (node.isTreeLeaf) {
return "/gojs/samples/images/document.png";
} else {
if (node.isTreeExpanded) {
return "/gojs/samples/images/openFolder.png";
} else {
return "/gojs/samples/images/closedFolder.png";
}
}
}
};