<!DOCTYPE html>
<html>
<head>
<title>Minimal GoJS Sample</title>
<!-- Copyright 1998-2020 by Northwoods Software Corporation. -->
<meta charset="UTF-8">
<script src="go.js"></script>
<script id="code">
function init() {
var $ = go.GraphObject.make;
function isDetailsLink(link) {
return link instanceof go.Link && link.category === "Comment" && link.fromNode.category === "Details";
}
function hasDetails(node) {
return node instanceof go.Node && node.linksConnected.any(isDetailsLink);
}
myDiagram =
$(go.Diagram, "myDiagramDiv",
{
"undoManager.isEnabled": true,
"draggingTool.computeEffectiveCollection": function(parts, options) {
var map = go.DraggingTool.prototype.computeEffectiveCollection.call(this, parts, options);
parts.each(function(node) {
if (node instanceof go.Node) {
node.linksConnected.each(function(l) {
if (isDetailsLink(l)) {
map.add(l, new go.DraggingInfo());
map.add(l.fromNode, new go.DraggingInfo(l.fromNode.location));
}
});
}
});
return map;
},
"ModelChanged": function(e) { // just for demonstration purposes,
if (e.isTransactionFinished) { // show the model data in the page's TextArea
document.getElementById("mySavedModel").textContent = e.model.toJson();
}
}
});
myDiagram.nodeTemplate =
$(go.Node, "Auto",
$(go.Shape,
{ fill: "white", portId: "" },
new go.Binding("fill", "color")),
$(go.Panel, "Vertical",
{ margin: 8 },
$(go.TextBlock, new go.Binding("text")),
$(go.TextBlock, new go.Binding("text", "info", function(i) { return i.t; }))
),
{
locationSpot: go.Spot.Center,
doubleClick: function(e, node) {
if (hasDetails(node)) return; // don't create a second Details node
e.diagram.commit(function(d) {
var newdata = { category: "Details", info: node.data.info };
d.model.addNodeData(newdata);
var newnode = d.findNodeForData(newdata);
newnode.location = new go.Point(node.location.x, node.location.y + node.actualBounds.height + 40);
var newlink = { category: "Comment", from: d.model.getKeyForNodeData(newdata), to: node.key };
d.model.addLinkData(newlink);
});
}
}
);
myDiagram.nodeTemplateMap.add("Details",
$(go.Node, "Table",
{ background: "lightgray", locationSpot: go.Spot.Center },
$(go.TextBlock, { row: 0 }, new go.Binding("text", "info", function(i) { return i.t1; })),
$(go.TextBlock, { row: 1 }, new go.Binding("text", "info", function(i) { return i.t2; })),
$(go.TextBlock, { row: 2 }, new go.Binding("text", "info", function(i) { return i.t3; })),
));
myDiagram.model =
$(go.GraphLinksModel,
{
nodeDataArray:
[
{ key: 1, text: "Alpha", color: "lightblue",
info: { t: "lowercase", t1: "text one", t2: "text two", t3: "text three" } },
{ key: 2, text: "Beta", color: "orange",
info: { t: "UPPERCASE", t1: "ONE", t2: "TWO", t3: "THREE" } }
],
linkDataArray:
[
{ from: 1, to: 2 }
]
});
}
function test() {
myDiagram.commit(function(d) {
d.selection.each(function(n) {
if (n instanceof go.Node) {
d.model.set(n.data.info, "t", n.data.info.t + ".");
d.model.set(n.data.info, "t2", n.data.info.t2 + "!");
n.updateTargetBindings("info");
n.findNodesConnected().each(function(m) { m.updateTargetBindings("info"); })
}
})
});
}
</script>
</head>
<body onload="init()">
<div id="myDiagramDiv" style="border: solid 1px black; width:100%; height:400px"></div>
<p>
Double click on a node to add a "Details" node with a "Comment" link connecting to the regular node.
The DraggingTool has been customized to drag the "Details" node (if one exists) along with the regular node.
</p>
<button onclick="test()">Test</button>
<p>
Clicking the "Test" button will append a character on the selected node's info.t and info.t2 properties.
</p>
<p>
The following output of Model.toJson does not preserve the shared object that is the value of node.data.info.
</p>
<textarea id="mySavedModel" style="width:100%;height:250px"></textarea>
</body>
</html>