I used the flow chart example to first create a simple chart output without editing possibilities. The JSON is generated by the server and everything works fine.
After that, I tried to add some editing possibilities again, but failed at the ports so far. New links start with a wrong direction and go through the rectangle. Relinking existing links from the JSON source is not possible at all.
I checked the code a few times but cannot find the problem.
I use GoJS 1.6.7, Firefox 44 on Windows 10.
The first screenshot shows the generated graph. It looks exactly like I want it to:
In the second screenshot, I tried to add two links (top and bottom). The routing is just broken:
![]()
The third screenshot shows me trying to relink. I don't get any other proposals than the whole rectangle. The ports are in the middle of all four sides:
![]()
The Code (I make some use of jQuery):
var make = go.GraphObject.make;
// Define a function for creating a "port" that is normally transparent.
// The "name" is used as the GraphObject.portId, the "spot" is used to control how links connect
// and where the port is positioned on the node, and the boolean "output" and "input" arguments
// control whether the user can draw links from or to the port.
function makePort(name, spot, output, input) {
// the port is basically just a small circle that has a white stroke when it is made visible
return make(go.Shape, "Circle",
{
fill: "transparent",
stroke: null,
strokeWidth: 1,
desiredSize: new go.Size(8, 8),
alignment: spot, alignmentFocus: spot,
portId: name,
fromSpot: spot, toSpot: spot,
fromLinkable: output, toLinkable: input,
cursor: "pointer"
}
);
}
// helper definitions for node templates
function nodeStyle() {
return [
// The Node.location comes from the "loc" property of the node data,
// converted by the Point.parse static method.
// If the Node.location is changed, it updates the "loc" property of the node data,
// converting back using the Point.stringify static method.
new go.Binding("location", "position", go.Point.parse).makeTwoWay(go.Point.stringify),
{
// the Node.location is at the center of each node
locationSpot: go.Spot.Center,
//isShadowed: true,
//shadowColor: "#888",
// handle mouse enter/leave events to show/hide the ports
mouseEnter: function (e, obj) { showPorts(obj.part, true); },
mouseLeave: function (e, obj) { showPorts(obj.part, false); }
}
];
}
// Make all ports on a node visible when the mouse is over the node
function showPorts(node, show) {
var diagram = node.diagram;
if (!diagram || diagram.isReadOnly || !diagram.allowLink) return;
node.ports.each(function(port) {
if (show) {
port.stroke = "#333333";
port.fill = "#0078d0";
port.mouseEnter = function (e, obj) {
obj.fill = "#e00034";
};
port.mouseLeave = function (e, obj) {
obj.fill = "#0078d0";
};
} else {
port.stroke = null;
port.fill = null;
port.mouseEnter = null;
port.mouseLeave = null;
}
});
}
ctx.createDiagram = function(el, graph) {
var diagram = make(go.Diagram, el, {
initialContentAlignment: go.Spot.Center,
allowDrop: true,
mouseWheelBehavior: go.ToolManager.WheelZoom,
layout: new go.TreeLayout(),
"undoManager.isEnabled": true
});
diagram.nodeTemplateMap.add("diamond",
make(go.Node, "Spot", nodeStyle(),
make(go.Panel, "Auto",
make(go.Shape, "Diamond", {fill: "transparent", stroke: "black", strokeWidth: 2, desiredSize: new go.Size(60, 60)})
),
makePort("T", go.Spot.Top, true, true),
makePort("L", go.Spot.Left, true, false),
makePort("R", go.Spot.Right, false, true),
makePort("B", go.Spot.Bottom, true, true)
)
);
diagram.nodeTemplateMap.add("bar",
make(go.Node, "Spot", nodeStyle(),
make(go.Panel, "Auto",
make(go.Shape, "Rectangle", {fill: "black", stroke: null, desiredSize: new go.Size(15, 80)})
),
makePort("L", go.Spot.Left, true, false),
makePort("R", go.Spot.Right, false, true)
)
);
diagram.nodeTemplateMap.add("activity",
make(go.Node, "Spot", nodeStyle(),
make(go.Panel, "Auto",
make(go.Shape, "RoundedRectangle", {fill: "transparent", stroke: "black", strokeWidth: 2 }),
make(go.Panel, "Vertical",
make(go.TextBlock,
{
font: "8pt Lato, sans-serif",
stroke: "black",
margin: 4,
maxSize: new go.Size(160, NaN),
wrap: go.TextBlock.WrapFit,
editable: false,
alignment: go.Spot.Left
}, new go.Binding("text", "role")
),
make(go.TextBlock,
{
font: "12pt Lato, sans-serif",
stroke: "#0078d0",
margin: 4,
maxSize: new go.Size(160, NaN),
wrap: go.TextBlock.WrapFit,
editable: false,
alignment: go.Spot.Left,
click: function(e, target) {
var win = window.open("/testcases.html?activity=" + target.part.data.key, '_blank');
win.focus();
},
cursor: "pointer",
mouseEnter: function(e, target) {
target.stroke = "#e00034";
},
mouseLeave: function(e, target) {
target.stroke = "#0078d0";
}
}, new go.Binding("text", "name")
), make(go.TextBlock,
{
font: "10pt Lato, sans-serif",
stroke: "black",
margin: 4,
maxSize: new go.Size(160, NaN),
wrap: go.TextBlock.WrapFit,
editable: false,
visible: false,
name: "description",
}, new go.Binding("text", "description", function(text) {
return $("<div>").html(text).text();
})
)
)
),
makePort("T", go.Spot.Top, true, true),
makePort("L", go.Spot.Left, true, false),
makePort("R", go.Spot.Right, false, true),
makePort("B", go.Spot.Bottom, true, true)
)
);
diagram.nodeTemplateMap.add("start",
make(go.Node, "Spot", nodeStyle(),
make(go.Shape, "Circle", {desiredSize: new go.Size(40, 40), fill: "black", stroke: null }),
makePort("R", go.Spot.Right, true, false)
)
);
diagram.nodeTemplateMap.add("end",
make(go.Node, "Spot", nodeStyle(),
make(go.Shape, "Circle", {desiredSize: new go.Size(40, 40), fill: "transparent", stroke: "black", strokeWidth: 2 }),
make(go.Shape, "Circle", {desiredSize: new go.Size(32, 32), fill: "black", stroke: null }),
makePort("L", go.Spot.Left, false, true)
)
);
diagram.linkTemplate = make(go.Link, {
routing: go.Link.AvoidsNodes,
curve: go.Link.JumpOver,
corner: 5,
toShortLength: 4,
relinkableFrom: true,
relinkableTo: true,
reshapable: true,
resegmentable: true,
mouseEnter: function(e, link) { link.findObject("HIGHLIGHT").stroke = "rgba(30,144,255,0.2)"; },
mouseLeave: function(e, link) { link.findObject("HIGHLIGHT").stroke = "transparent"; }
}, new go.Binding("points").makeTwoWay(),
make(go.Shape, {isPanelMain: true, strokeWidth: 8, stroke: "transparent", name: "HIGHLIGHT"}),
make(go.Shape, {isPanelMain: true, stroke: "black", strokeWidth: 2}),
make(go.Shape, {toArrow: "standard", stroke: null, fill: "black"}),
make(go.Panel, "Auto", {visible: false, name: "label", segmentIndex: 2, segmentFraction: 0.5},
make(go.Shape, "RoundedRectangle", {fill: "#F8F8F8", stroke: null}),
make(go.TextBlock,
{
textAlign: "center",
font: "10pt Lato, sans-serif",
stroke: "black",
editable: false
},
new go.Binding("text", "text")
)
)
);
// temporary links used by LinkingTool and RelinkingTool are also orthogonal:
diagram.toolManager.linkingTool.temporaryLink.routing = go.Link.Orthogonal;
diagram.toolManager.relinkingTool.temporaryLink.routing = go.Link.Orthogonal;
// Nur die Anfangsanimation soll aus
diagram.animationManager.isEnabled = false;
diagram.model = go.Model.fromJson(graph);
diagram.animationManager.isEnabled = true;
// Show non-empty labels
var i = diagram.findLinksByExample({text: function(text) {
return typeof text !== "undefined";
}});
while (i.next()) {
var label = i.value.findObject("label");
label.visible = true;
}
// Show non-empty descriptions
var i = diagram.findNodesByExample({description: function(description) {
return typeof description !== "undefined";
}});
while (i.next()) {
var label = i.value.findObject("description");
label.visible = true;
}
};
The example graph:
{"nodeDataArray":[{"role":"Controller","name":"Report ETA","description":"<p>The controller reports the ETAs to every involved customers of the tour.</p>","category":"activity","key":257628},{"role":"Controller","name":"Plan route","description":"<p>The controller plans the route considering additional orders that can be combined with this one.</p>","category":"activity","key":257626},{"role":"Controller","name":"Replan open tour parts","category":"activity","key":257657},{"role":"Controller","name":"Receive order","category":"activity","key":257616},{"role":"Controller","name":"Check tour / stall fee","category":"activity","key":257664},{"role":"Controller","name":"Send tour","description":"<p>The controller sends the tour to the vehicle.</p>","category":"activity","key":257630},{"role":"Controller","name":"Approve tour for invoice processing","category":"activity","key":257668},{"role":"Driver","name":"Receive tour","category":"activity","key":257652},{"role":"Driver","name":"Drive tour","category":"activity","key":257654},{"role":"Controller","name":"Plan tour","description":"<p>The controller creates a tour containing the order and assigns it to a vehicle/driver.</p>","category":"activity","key":257621},{"category":"diamond","key":257660},{"category":"bar","key":258057},{"category":"bar","key":258061},{"category":"diamond","key":257624},{"category":"start","key":-1},{"category":"end","key":-2}],"linkDataArray":[{"from":257660,"to":257657,"text":"Disturbances occur"},{"from":257657,"to":257624},{"from":257654,"to":257660},{"from":257660,"to":257664,"text":"No disturbances occur"},{"from":257621,"to":258057},{"from":257664,"to":257668},{"from":257628,"to":258061},{"from":257626,"to":257621},{"from":258057,"to":257630},{"from":258057,"to":257628},{"from":257624,"to":257626},{"from":258061,"to":257654},{"from":257630,"to":257652},{"from":257616,"to":257624},{"from":257652,"to":258061},{"from":-1,"to":257616},{"from":257668,"to":-2}],"class":"go.GraphLinksModel","linkFromPortIdProperty":"fromPort","linkToPortIdProperty":"toPort"}
Can you please help me fix those two problems?
Thanks.