I have 2 JS files.
1) The first one is main one and it's organized according to module pattern. It looks as following:
"use strict";
var SchemaEditor = (function () {
/* Private members */
var black = "black";
var transparent = "transparent";
var sd = {
mode: "pointer", // Set to default mode. Alternatives are "node" and "link", for adding a new node or a new link respectively.
itemType: "pointer", // Set when user clicks on a node or link button.
nodeCounter: {}
};
var myDiagram;
var $ = go.GraphObject.make;
/* Private methods */
// update the diagram every 250 milliseconds
function loop() {
setTimeout(function () { updateStates(); loop(); }, 250);
}
// update the value and appearance of each node according to its type and input values
function updateStates() {
var oldskip = myDiagram.skipsUndoManager;
myDiagram.skipsUndoManager = true;
// do all "input" nodes first
myDiagram.nodes.each(function (node) {
if (node.category === "input") {
doInput(node);
}
});
// now we can do all other kinds of nodes
myDiagram.nodes.each(function (node) {
switch (node.category) {
case "image1": doImage1(node); break;
case "image2": doImage2(node); break;
case "image3": doImage3(node); break;
case "image4": doImage4(node); break;
case "image5": doImage5(node); break;
case "image6": doImage6(node); break;
case "image7": doImage7(node); break;
case "image8": doImage8(node); break;
case "image9": doImage9(node); break;
case "image10": doImage10(node); break;
case "table": doTable(node); break;
case "hBar": dohBar(node); break;
}
});
myDiagram.skipsUndoManager = oldskip;
}
// update nodes by the specific function for its type
// determine the color of links coming out of this node based on those coming in and node type
function doImage1(node) {
// assume there is just one input link
// we just need to update the node's Shape.fill
node.linksConnected.each(function (link) { node.findObject("NODESHAPE1").fill = link.findObject("SHAPE").stroke; });
}
function doImage2(node) {
// assume there is just one input link
// we just need to update the node's Shape.fill
node.linksConnected.each(function (link) { node.findObject("NODESHAPE1").fill = link.findObject("SHAPE").stroke; });
}
function doImage3(node) {
// assume there is just one input link
// we just need to update the node's Shape.fill
node.linksConnected.each(function (link) { node.findObject("NODESHAPE1").fill = link.findObject("SHAPE").stroke; });
}
function doImage4(node) {
// assume there is just one input link
// we just need to update the node's Shape.fill
node.linksConnected.each(function (link) { node.findObject("NODESHAPE1").fill = link.findObject("SHAPE").stroke; });
}
function doImage5(node) {
// assume there is just one input link
// we just need to update the node's Shape.fill
node.linksConnected.each(function (link) { node.findObject("NODESHAPE1").fill = link.findObject("SHAPE").stroke; });
}
function doImage6(node) {
// assume there is just one input link
// we just need to update the node's Shape.fill
node.linksConnected.each(function (link) { node.findObject("NODESHAPE1").fill = link.findObject("SHAPE").stroke; });
}
function doImage7(node) {
// assume there is just one input link
// we just need to update the node's Shape.fill
node.linksConnected.each(function (link) { node.findObject("NODESHAPE1").fill = link.findObject("SHAPE").stroke; });
}
function doImage8(node) {
// assume there is just one input link
// we just need to update the node's Shape.fill
node.linksConnected.each(function (link) { node.findObject("NODESHAPE1").fill = link.findObject("SHAPE").stroke; });
}
function doImage9(node) {
// assume there is just one input link
// we just need to update the node's Shape.fill
node.linksConnected.each(function (link) { node.findObject("NODESHAPE1").fill = link.findObject("SHAPE").stroke; });
}
function doImage10(node) {
// assume there is just one input link
// we just need to update the node's Shape.fill
node.linksConnected.each(function (link) { node.findObject("NODESHAPE1").fill = link.findObject("SHAPE").stroke; });
}
function doTable(node) {
// assume there is just one input link
// we just need to update the node's Shape.fill
node.linksConnected.each(function (link) { node.findObject("NODESHAPE1").fill = link.findObject("SHAPE").stroke; });
}
function dohBar(node) {
// assume there is just one input link
// we just need to update the node's Shape.fill
node.linksConnected.each(function (link) { node.findObject("NODESHAPE1").fill = link.findObject("SHAPE").stroke; });
}
function BarLink() {
go.Link.call(this);
}
go.Diagram.inherit(BarLink, go.Link);
/** #override */
BarLink.prototype.getLinkPoint = function (node, port, spot, from, ortho, othernode, otherport) {
if (node.category === "hBar") {
var op = go.Link.prototype.getLinkPoint.call(this, othernode, otherport, this.computeSpot(!from), !from, ortho, node, port);
var r = new go.Rect(port.getDocumentPoint(go.Spot.TopLeft),
port.getDocumentPoint(go.Spot.BottomRight));
var y = (op.y > r.centerY) ? r.bottom : r.top;
if (op.x < r.left) return new go.Point(r.left, y);
if (op.x > r.right) return new go.Point(r.right, y);
return new go.Point(op.x, y);
} else {
return go.Link.prototype.getLinkPoint.call(this, node, port, spot, from, ortho, othernode, otherport);
}
};
/** #override */
BarLink.prototype.getLinkDirection = function (node, port, linkpoint, spot, from, ortho, othernode, otherport) {
var p = port.getDocumentPoint(go.Spot.Center);
var op = otherport.getDocumentPoint(go.Spot.Center);
var below = op.y > p.y;
return below ? 90 : 270;
};
// end BarLink class
var setMode = function (mode, itemType) {
myDiagram.startTransaction();
sd.mode = mode;
sd.itemType = itemType;
if (mode === "link") {
if (itemType === 'default') {
if (document.getElementById("defaultMode").classList.contains('non-pushed')) {
document.getElementById("defaultMode").classList.remove('non-pushed');
document.getElementById("defaultMode").classList.add('pushed');
document.getElementById("orthoMode").classList.add('non-pushed');
document.getElementById("cornerMode").classList.add('non-pushed');
}
}
if (itemType === 'ortho') {
if (document.getElementById("orthoMode").classList.contains('non-pushed')) {
document.getElementById("orthoMode").classList.remove('non-pushed');
document.getElementById("orthoMode").classList.add('pushed');
document.getElementById("defaultMode").classList.add('non-pushed');
document.getElementById("cornerMode").classList.add('non-pushed');
}
}
if (itemType === 'corner') {
if (document.getElementById("cornerMode").classList.contains('non-pushed')) {
document.getElementById("cornerMode").classList.remove('non-pushed');
document.getElementById("cornerMode").classList.add('pushed');
document.getElementById("defaultMode").classList.add('non-pushed');
document.getElementById("orthoMode").classList.add('non-pushed');
}
}
myDiagram.allowLink = true;
myDiagram.nodes.each(function (n) { n.port.cursor = "pointer"; });
}
myDiagram.commitTransaction("mode changed");
};
// save a model to and load a model from JSON text, displayed below the Diagram
var save = function () {
document.getElementById("mySavedModel").value = myDiagram.model.toJson();
myDiagram.isModified = false;
};
var load = function () {
myDiagram.model = go.Model.fromJson(document.getElementById("mySavedModel").value);
};
function addLinkTemplateMaps() {
// creates relinkable Links that will avoid crossing Nodes when possible and will jump over other Links in their paths
myDiagram.linkTemplateMap.add("default",
$(go.Link,
{
relinkableFrom: true, relinkableTo: true,
selectionAdorned: false, // Links are not adorned when selected so that their color remains visible.
shadowOffset: new go.Point(0, 0), shadowBlur: 5, shadowColor: "black"
},
new go.Binding("isShadowed", "isSelected").ofObject(),
$(go.Shape,
{ name: "SHAPE", strokeWidth: 2, stroke: black })));
myDiagram.linkTemplateMap.add("corner",
$(go.Link,
{ reshapable: true, resegmentable: true, routing: go.Link.AvoidsNodes },
new go.Binding("points").makeTwoWay(), // TwoWay Binding of Link.points
$(go.Shape)
));
myDiagram.linkTemplateMap.add("ortho",
$(BarLink, // subclass defined below
{
routing: go.Link.Orthogonal,
relinkableFrom: true,
relinkableTo: true,
toPortChanged: function (link, oldport, newport) {
if (newport instanceof go.Shape) link.path.stroke = newport.fill;
}
},
$(go.Shape,
{ strokeWidth: 2 })
));
};
var initSchemaEditor = function () {
myDiagram = $(go.Diagram, "myDiagramDiv",
{
initialContentAlignment: go.Spot.Center,
allowDrop: true, // Nodes from the Palette can be dropped into the Diagram
"undoManager.isEnabled": true,
"grid.visible": true,
"linkingTool.portGravity": 0, // no snapping while drawing new links
"linkingTool.doActivate": function () {
// change the curve of the LinkingTool.temporaryLink
this.temporaryLink.curve = (sd.itemType === "default") ? go.Link.Normal : go.Link.Orthogonal;
go.LinkingTool.prototype.doActivate.call(this);
},
// override the link creation process
"linkingTool.insertLink": function (fromnode, fromport, tonode, toport) {
// to control what kind of Link is created,
// change the LinkingTool.archetypeLinkData's category
myDiagram.model.setCategoryForLinkData(this.archetypeLinkData, sd.itemType);
// also change the text indicating the condition, which the user can edit
this.archetypeLinkData.text = sd.itemType;
return go.LinkingTool.prototype.insertLink.call(this, fromnode, fromport, tonode, toport);
},
"clickCreatingTool.archetypeNodeData": {}, // enable ClickCreatingTool
"clickCreatingTool.isDoubleClick": false, // operates on a single click in background
"clickCreatingTool.canStart": function () { // but only in "node" creation mode
return sd.mode === "node" && go.ClickCreatingTool.prototype.canStart.call(this);
},
"clickCreatingTool.insertPart": function (loc) { // customize the data for the new node
sd.nodeCounter[sd.itemType] += 1;
var newNodeId = sd.itemType + sd.nodeCounter[sd.itemType];
this.archetypeNodeData = {
key: newNodeId,
category: sd.itemType,
label: newNodeId
};
return go.ClickCreatingTool.prototype.insertPart.call(this, loc);
}
});
myDiagram.requestUpdate();
// when the document is modified, add a "*" to the title and enable the "Save" button
myDiagram.addDiagramListener("Modified", function (e) {
var button = document.getElementById("saveModel");
if (button) button.disabled = !myDiagram.isModified;
var idx = document.title.indexOf("*");
if (myDiagram.isModified) {
if (idx < 0) document.title += "*";
} else {
if (idx >= 0) document.title = document.title.substr(0, idx);
}
});
myDiagram.model =
$(go.GraphLinksModel,
{
linkFromPortIdProperty: "fromPort", // required information:
linkToPortIdProperty: "toPort" // identifies data property names
});
addLinkTemplateMaps();
loadNodes();
myDiagram.nodeTemplateMap.add("image1", image1Template);
myDiagram.nodeTemplateMap.add("image2", image2Template);
myDiagram.nodeTemplateMap.add("image3", image3Template);
myDiagram.nodeTemplateMap.add("image4", image4Template);
myDiagram.nodeTemplateMap.add("image5", image5Template);
myDiagram.nodeTemplateMap.add("image6", image6Template);
myDiagram.nodeTemplateMap.add("image7", image7Template);
myDiagram.nodeTemplateMap.add("image8", image8Template);
myDiagram.nodeTemplateMap.add("image9", image9Template);
myDiagram.nodeTemplateMap.add("image10", image10Template);
myDiagram.nodeTemplateMap.add("table", tableTemplate);
myDiagram.nodeTemplateMap.add("hBar", hBarTemplate);
var palette = new go.Palette("palette"); // create a new Palette in the HTML DIV element "palette"
// share the template map with the Palette
palette.nodeTemplateMap = myDiagram.nodeTemplateMap;
//palette.groupTemplateMap = myDiagram.groupTemplateMap;
palette.model.nodeDataArray = [
{ category: "image1" },
{ category: "image2" },
{ category: "image3" },
{ category: "image4" },
{ category: "image5" },
{ category: "image6" },
{ category: "image7" },
{ category: "image8" },
{ category: "image9" },
{ category: "image10" },
{ category: "table" },
{ category: "hBar" }
];
myDiagram.addDiagramListener("ExternalObjectsDropped", function (e) {
if (myDiagram.currentTool instanceof go.TextEditingTool) {
myDiagram.currentTool.acceptText(go.TextEditingTool.LostFocus);
}
myDiagram.commandHandler.ungroupSelection();
jQuery.ajax({
type: "GET",
url: '/Home/GetRandomObjectProperties'
}).done(function (data) {
// loop through selection to find table node and populate properties
myDiagram.selection.each(function (p) {
if (p instanceof go.Node && p.category === "table") {
var nodedata = p.data;
var properties = data.map(function (item) {
return { "property_name": item.Item1.toString(), "property_value": item.Item2.toString() };
});
myDiagram.model.setDataProperty(nodedata, "properties", properties);
return;
}
});
});
});
// load the initial diagram
load();
// continually update the diagram
loop();
};
/* Public methods */
return {
initSchemaEditor: initSchemaEditor,
setMode: setMode,
save: save,
load: load
};
})();
2) The second JS file is not organized according to module pattern and it looks as following:
"use strict";
var sharedToolTip;
var image1Template;
var image2Template;
var image3Template;
var image4Template;
var image5Template;
var image6Template;
var image7Template;
var image8Template;
var image9Template;
var image10Template;
var tableTemplate;
var hBarTemplate;
function loadNodes() {
var $ = go.GraphObject.make;
// node template helpers
sharedToolTip =
$(go.Adornment, "Auto",
$(go.Shape, "RoundedRectangle", { fill: "lightyellow" }),
$(go.TextBlock, { margin: 2 },
new go.Binding("text", "", function (d) { return d.category; })));
// define some common property settings
function nodeStyle() {
return [
new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify),
new go.Binding("isShadowed", "isSelected").ofObject(),
{
selectionAdorned: false,
shadowOffset: new go.Point(0, 0),
shadowBlur: 15,
shadowColor: "blue",
toolTip: sharedToolTip
}
];
}
function portStyle0(input) {
return {
desiredSize: new go.Size(3, 3),
fill: "black",
fromLinkable: !input,
toLinkable: input,
cursor: "pointer"
};
}
function portStyle1() {
return {
desiredSize: new go.Size(3, 3),
fill: "black",
toLinkable: true,
cursor: "pointer",
fromLinkable: true,
fromSpot: go.Spot.TopBottomSides,
toSpot: go.Spot.TopBottomSides
};
}
image1Template =
$(go.Node, "Vertical", nodeStyle(),
$(go.Picture, "Images/ElectricalElements/Cell_1.svg"),
$(go.Shape, "Rectangle", portStyle1(),
{ portId: "", alignment: new go.Spot(0.18, 0) })
);
image2Template =
$(go.Node, "Vertical", nodeStyle(),
$(go.Picture, "Images/ElectricalElements/Cell_2.svg"),
$(go.Shape, "Rectangle", portStyle1(),
{ portId: "", alignment: new go.Spot(0.33, 0) })
);
image3Template =
$(go.Node, "Vertical", nodeStyle(),
$(go.Picture, "Images/ElectricalElements/GTU.svg"),
$(go.Shape, "Rectangle", portStyle1(),
{ portId: "", alignment: new go.Spot(0.215, 0) })
);
image4Template =
$(go.Node, "Vertical", nodeStyle(),
$(go.Shape, "Rectangle", portStyle0(false),
{ portId: "1", alignment: new go.Spot(0.125, 0) }),
$(go.Picture, "Images/ElectricalElements/Sec_1.svg"),
$(go.Shape, "Rectangle", portStyle1(),
{ portId: "2", alignment: new go.Spot(0.125, 0) })
);
image5Template =
$(go.Node, "Vertical", nodeStyle(),
$(go.Shape, "Rectangle", portStyle0(true),
{ portId: "3", alignment: new go.Spot(0.523, 0) }),
$(go.Picture, "Images/ElectricalElements/Sec_2.svg"),
$(go.Shape, "Rectangle", portStyle1(),
{ portId: "4", alignment: new go.Spot(0.523, 0) })
);
image6Template =
$(go.Node, "Vertical", nodeStyle(),
$(go.Shape, "Rectangle", portStyle0(true),
{ portId: "", alignment: new go.Spot(0.12, 0) }),
$(go.Picture, "Images/ElectricalElements/Sec_3.svg"),
$(go.Shape, "Rectangle", portStyle1(),
{ portId: "", alignment: new go.Spot(0.12, 0) })
);
image7Template =
$(go.Node, "Vertical", nodeStyle(),
$(go.Picture, "Images/ElectricalElements/Tr_1.svg"),
$(go.Shape, "Rectangle", portStyle1(),
{ portId: "", alignment: new go.Spot(0.42, 0) })
);
image8Template =
$(go.Node, "Vertical", nodeStyle(),
$(go.Shape, "Rectangle", portStyle1(),
{ portId: "", alignment: new go.Spot(0.59, 0) }),
$(go.Picture, "Images/ElectricalElements/Tr_2.svg")
);
image9Template =
$(go.Node, "Vertical", nodeStyle(),
{
resizable: true,
resizeObjectName: "SHAPE", selectionObjectName: "SHAPE"
},
$(go.Shape, "Rectangle",
{
name: "SHAPE",
fill: transparent,
width: 60,
height: 40,
stroke: black,
strokeWidth: 1,
strokeDashArray: [5, 5]
},
new go.Binding("desiredSize", "size", go.Size.parse).makeTwoWay(go.Size.stringify))
);
image10Template =
$(go.Node, "Vertical", nodeStyle(),
$(go.TextBlock,
{
text: "text",
editable: true,
isMultiline: true
},
new go.Binding("text", "text").makeTwoWay())
);
tableTemplate =
$(go.Node, go.Panel.Auto, nodeStyle(),
$(go.Shape, { fill: "white", stroke: "gray", strokeWidth: 1 }),
{ movable: true },
new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify),
$(go.Panel, "Table",
new go.Binding("itemArray", "properties"),
{
defaultAlignment: go.Spot.Left,
defaultColumnSeparatorStroke: "black",
itemTemplate:
$(go.Panel, "TableRow",
$(go.TextBlock, new go.Binding("text", "property_name"),
{ column: 0, margin: 1, font: "bold 7pt sans-serif" }),
$(go.TextBlock, new go.Binding("text", "property_value"),
{ column: 1, margin: 1 })
)
},
$(go.Panel, "TableRow",
{ isPanelMain: true },
$(go.TextBlock, "Name",
{ column: 0, margin: new go.Margin(1, 1, 0, 1), font: "bold 7pt sans-serif" }),
$(go.TextBlock, "Value",
{ column: 1, margin: new go.Margin(1, 1, 0, 1), font: "bold 7pt sans-serif" })
),
$(go.RowColumnDefinition,
{ row: 0, background: "lightgray" }),
$(go.RowColumnDefinition,
{ row: 1, separatorStroke: "black" })
)
);
hBarTemplate =
$(go.Node,
new go.Binding("location", "location", go.Point.parse).makeTwoWay(go.Point.stringify),
{
layerName: "Background",
// special resizing: just at the ends
resizable: true, resizeObjectName: "SHAPE",
resizeAdornmentTemplate:
$(go.Adornment, "Spot",
$(go.Placeholder),
$(go.Shape, // left resize handle
{
alignment: go.Spot.Left, cursor: "col-resize",
desiredSize: new go.Size(6, 6), fill: "lightblue", stroke: "dodgerblue"
}),
$(go.Shape, // right resize handle
{
alignment: go.Spot.Right, cursor: "col-resize",
desiredSize: new go.Size(6, 6), fill: "lightblue", stroke: "dodgerblue"
})),
rotatable: true
},
$(go.Shape, "Rectangle",
{
name: "SHAPE",
fill: "black", stroke: null, strokeWidth: 0,
width: 60, height: 5,
minSize: new go.Size(50, 5),
maxSize: new go.Size(Infinity, 5)
},
new go.Binding("desiredSize", "size", go.Size.parse).makeTwoWay(go.Size.stringify),
new go.Binding("fill"),
{ portId: "", toLinkable: true })
);
};
I call the function loadNodes from second JS file in main JS file and it works.
But, when I've tried to organize the second JS file according to module pattern it stopped working.
I've tried the folowing:
1) The main file:
...
NodeRepository.loadNodes();
myDiagram.nodeTemplateMap.add("image1", NodeRepository.image1Template);
myDiagram.nodeTemplateMap.add("image2", NodeRepository.image2Template);
myDiagram.nodeTemplateMap.add("image3", NodeRepository.image3Template);
myDiagram.nodeTemplateMap.add("image4", NodeRepository.image4Template);
myDiagram.nodeTemplateMap.add("image5", NodeRepository.image5Template);
myDiagram.nodeTemplateMap.add("image6", NodeRepository.image6Template);
myDiagram.nodeTemplateMap.add("image7", NodeRepository.image7Template);
myDiagram.nodeTemplateMap.add("image8", NodeRepository.image8Template);
myDiagram.nodeTemplateMap.add("image9", NodeRepository.image9Template);
myDiagram.nodeTemplateMap.add("image10", NodeRepository.image10Template);
myDiagram.nodeTemplateMap.add("table", NodeRepository.tableTemplate);
myDiagram.nodeTemplateMap.add("hBar", NodeRepository.hBarTemplate);
...
2) The second file:
"use strict";
var NodeRepository = (function () {
var sharedToolTip;
var image1Template;
var image2Template;
var image3Template;
var image4Template;
var image5Template;
var image6Template;
var image7Template;
var image8Template;
var image9Template;
var image10Template;
var tableTemplate;
var hBarTemplate;
function loadNodes() {
var $ = go.GraphObject.make;
...
};
return {
image1Template: image1Template,
image2Template: image2Template,
image3Template: image3Template,
image4Template: image4Template,
image5Template: image5Template,
image6Template: image6Template,
image7Template: image7Template,
image8Template: image8Template,
image9Template: image9Template,
image10Template: image10Template,
tableTemplate: tableTemplate,
hBarTemplate: hBarTemplate,
loadNodes: loadNodes
};
})();
What I'm doing wrong?
Here's what I did:
"use strict";
var NodeRepository = (function () {
var sharedToolTip;
var image1Template;
var image2Template;
var image3Template;
var image4Template;
var image5Template;
var image6Template;
var image7Template;
var image8Template;
var image9Template;
var image10Template;
var tableTemplate;
var hBarTemplate;
function image1Public() {
return image1Template;
}
function image2Public() {
return image2Template;
}
function image3Public() {
return image3Template;
}
function image4Public() {
return image4Template;
}
function image5Public() {
return image5Template;
}
function image6Public() {
return image6Template;
}
function image7Public() {
return image7Template;
}
function image8Public() {
return image8Template;
}
function image9Public() {
return image9Template;
}
function image10Public() {
return image10Template;
}
function image11Public() {
return tableTemplate;
}
function image12Public() {
return hBarTemplate;
}
function loadNodes() {
var $ = go.GraphObject.make;
// node template helpers
sharedToolTip =
$(go.Adornment, "Auto",
$(go.Shape, "RoundedRectangle", { fill: "lightyellow" }),
$(go.TextBlock, { margin: 2 },
new go.Binding("text", "", function (d) { return d.category; })));
// define some common property settings
function nodeStyle() {
return [
new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify),
new go.Binding("isShadowed", "isSelected").ofObject(),
{
selectionAdorned: false,
shadowOffset: new go.Point(0, 0),
shadowBlur: 15,
shadowColor: "blue",
toolTip: sharedToolTip
}
];
}
function portStyle0(input) {
return {
desiredSize: new go.Size(3, 3),
fill: "black",
fromLinkable: !input,
toLinkable: input,
cursor: "pointer"
};
}
function portStyle1() {
return {
desiredSize: new go.Size(3, 3),
fill: "black",
toLinkable: true,
cursor: "pointer",
fromLinkable: true,
fromSpot: go.Spot.TopBottomSides,
toSpot: go.Spot.TopBottomSides
};
}
image1Template =
$(go.Node, "Vertical", nodeStyle(),
$(go.Picture, "Images/ElectricalElements/Cell_1.svg"),
$(go.Shape, "Rectangle", portStyle1(),
{ portId: "", alignment: new go.Spot(0.18, 0) })
);
image2Template =
$(go.Node, "Vertical", nodeStyle(),
$(go.Picture, "Images/ElectricalElements/Cell_2.svg"),
$(go.Shape, "Rectangle", portStyle1(),
{ portId: "", alignment: new go.Spot(0.33, 0) })
);
image3Template =
$(go.Node, "Vertical", nodeStyle(),
$(go.Picture, "Images/ElectricalElements/GTU.svg"),
$(go.Shape, "Rectangle", portStyle1(),
{ portId: "", alignment: new go.Spot(0.215, 0) })
);
image4Template =
$(go.Node, "Vertical", nodeStyle(),
$(go.Shape, "Rectangle", portStyle0(false),
{ portId: "1", alignment: new go.Spot(0.125, 0) }),
$(go.Picture, "Images/ElectricalElements/Sec_1.svg"),
$(go.Shape, "Rectangle", portStyle1(),
{ portId: "2", alignment: new go.Spot(0.125, 0) })
);
image5Template =
$(go.Node, "Vertical", nodeStyle(),
$(go.Shape, "Rectangle", portStyle0(true),
{ portId: "3", alignment: new go.Spot(0.523, 0) }),
$(go.Picture, "Images/ElectricalElements/Sec_2.svg"),
$(go.Shape, "Rectangle", portStyle1(),
{ portId: "4", alignment: new go.Spot(0.523, 0) })
);
image6Template =
$(go.Node, "Vertical", nodeStyle(),
$(go.Shape, "Rectangle", portStyle0(true),
{ portId: "", alignment: new go.Spot(0.12, 0) }),
$(go.Picture, "Images/ElectricalElements/Sec_3.svg"),
$(go.Shape, "Rectangle", portStyle1(),
{ portId: "", alignment: new go.Spot(0.12, 0) })
);
image7Template =
$(go.Node, "Vertical", nodeStyle(),
$(go.Picture, "Images/ElectricalElements/Tr_1.svg"),
$(go.Shape, "Rectangle", portStyle1(),
{ portId: "", alignment: new go.Spot(0.42, 0) })
);
image8Template =
$(go.Node, "Vertical", nodeStyle(),
$(go.Shape, "Rectangle", portStyle1(),
{ portId: "", alignment: new go.Spot(0.59, 0) }),
$(go.Picture, "Images/ElectricalElements/Tr_2.svg")
);
image9Template =
$(go.Node, "Vertical", nodeStyle(),
{
resizable: true,
resizeObjectName: "SHAPE", selectionObjectName: "SHAPE"
},
$(go.Shape, "Rectangle",
{
name: "SHAPE",
fill: transparent,
width: 60,
height: 40,
stroke: black,
strokeWidth: 1,
strokeDashArray: [5, 5]
},
new go.Binding("desiredSize", "size", go.Size.parse).makeTwoWay(go.Size.stringify))
);
image10Template =
$(go.Node, "Vertical", nodeStyle(),
$(go.TextBlock,
{
text: "text",
editable: true,
isMultiline: true
},
new go.Binding("text", "text").makeTwoWay())
);
tableTemplate =
$(go.Node, go.Panel.Auto, nodeStyle(),
$(go.Shape, { fill: "white", stroke: "gray", strokeWidth: 1 }),
{ movable: true },
new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify),
$(go.Panel, "Table",
new go.Binding("itemArray", "properties"),
{
defaultAlignment: go.Spot.Left,
defaultColumnSeparatorStroke: "black",
itemTemplate:
$(go.Panel, "TableRow",
$(go.TextBlock, new go.Binding("text", "property_name"),
{ column: 0, margin: 1, font: "bold 7pt sans-serif" }),
$(go.TextBlock, new go.Binding("text", "property_value"),
{ column: 1, margin: 1 })
)
},
$(go.Panel, "TableRow",
{ isPanelMain: true },
$(go.TextBlock, "Name",
{ column: 0, margin: new go.Margin(1, 1, 0, 1), font: "bold 7pt sans-serif" }),
$(go.TextBlock, "Value",
{ column: 1, margin: new go.Margin(1, 1, 0, 1), font: "bold 7pt sans-serif" })
),
$(go.RowColumnDefinition,
{ row: 0, background: "lightgray" }),
$(go.RowColumnDefinition,
{ row: 1, separatorStroke: "black" })
)
);
hBarTemplate =
$(go.Node,
new go.Binding("location", "location", go.Point.parse).makeTwoWay(go.Point.stringify),
{
layerName: "Background",
// special resizing: just at the ends
resizable: true, resizeObjectName: "SHAPE",
resizeAdornmentTemplate:
$(go.Adornment, "Spot",
$(go.Placeholder),
$(go.Shape, // left resize handle
{
alignment: go.Spot.Left, cursor: "col-resize",
desiredSize: new go.Size(6, 6), fill: "lightblue", stroke: "dodgerblue"
}),
$(go.Shape, // right resize handle
{
alignment: go.Spot.Right, cursor: "col-resize",
desiredSize: new go.Size(6, 6), fill: "lightblue", stroke: "dodgerblue"
})),
rotatable: true
},
$(go.Shape, "Rectangle",
{
name: "SHAPE",
fill: "black", stroke: null, strokeWidth: 0,
width: 60, height: 5,
minSize: new go.Size(50, 5),
maxSize: new go.Size(Infinity, 5)
},
new go.Binding("desiredSize", "size", go.Size.parse).makeTwoWay(go.Size.stringify),
new go.Binding("fill"),
{ portId: "", toLinkable: true })
);
};
return {
image1Public: image1Public,
image2Public: image2Public,
image3Public: image3Public,
image4Public: image4Public,
image5Public: image5Public,
image6Public: image6Public,
image7Public: image7Public,
image8Public: image8Public,
image9Public: image9Public,
image10Public: image10Public,
image11Public: image11Public,
image12Public: image12Public,
loadNodes: loadNodes
};
})();
I want to have a diagram which has vertical and horizontal layout in the same diagram. How can I achieve this in gojs?
There are many ways in which you can achieve your goal. I can think of three off-hand. In decreasing order of work:
Create a custom Layout that does what you want. This is the most general and can be the most compatible with the data structures that you have used with your two existing diagrams that you want to combine.
In your case you might be able to use the TableLayout that is in the extensions directory: http://gojs.net/latest/extensions/Table.html. You probably could continue to use Groups, but you would set their Group.layout to null so that they are completely ignored when the layout is performed.
Put everything in one of your existing diagrams into a Group and put everything from your other existing diagram into another Group. The Diagram.layout of the first would be the Group.layout of the first group, and the Diagram.layout of the second diagram would be the Group.layout of the second group.
Note that each Diagram can have exactly one Model (the Diagram.model), so for all three techniques you would need to add all of the data into a single model without getting references between them confused. That means you need to make sure the keys for the nodes are all unique.
Here's an example of how you can put two separate diagrams into a single diagram using the third technique. I'll start with two copies of the Minimal sample, http://gojs.net/latest/samples/minimal.html, where the only change is that one has a ForceDirectedLayout and the other one has a LayeredDigraphLayout. So one will be defined:
myDiagram = $(go.Diagram, "myDiagramDiv",
{
initialContentAlignment: go.Spot.Center,
layout: $(go.ForceDirectedLayout),
"undoManager.isEnabled": true
});
and the other will be defined:
myDiagram = $(go.Diagram, "myDiagramDiv",
{
initialContentAlignment: go.Spot.Center,
layout: $(go.LayeredDigraphLayout),
"undoManager.isEnabled": true
});
But otherwise these two diagrams are exactly like the Minimal sample.
Initially each model of Minimal is created by:
myDiagram.model = new go.GraphLinksModel(
[
{ key: "Alpha", color: "lightblue" },
{ key: "Beta", color: "orange" },
{ key: "Gamma", color: "lightgreen" },
{ key: "Delta", color: "pink" }
],
[
{ from: "Alpha", to: "Beta" },
{ from: "Alpha", to: "Gamma" },
{ from: "Beta", to: "Beta" },
{ from: "Gamma", to: "Delta" },
{ from: "Delta", to: "Alpha" }
]);
So, we first need to create a combined model that is the two models added together. One way to put them together is:
myDiagram.model = new go.GraphLinksModel(
[
{ key: "Alpha", color: "lightblue" },
{ key: "Beta", color: "orange" },
{ key: "Gamma", color: "lightgreen" },
{ key: "Delta", color: "pink" },
{ key: "Alpha2", color: "lightblue" },
{ key: "Beta2", color: "orange" },
{ key: "Gamma2", color: "lightgreen" },
{ key: "Delta2", color: "pink" }
],
[
{ from: "Alpha", to: "Beta" },
{ from: "Alpha", to: "Gamma" },
{ from: "Beta", to: "Beta" },
{ from: "Gamma", to: "Delta" },
{ from: "Delta", to: "Alpha" },
{ from: "Alpha2", to: "Beta2" },
{ from: "Alpha2", to: "Gamma2" },
{ from: "Beta2", to: "Beta2" },
{ from: "Gamma2", to: "Delta2" },
{ from: "Delta2", to: "Alpha2" }
]);
Again, I'll mention that this is work you would need to do no matter which technique you used. Presumably you have already done this and are just wondering how to handle two layouts.
The third technique I suggested uses Groups to encapsulate what had originally been in a whole Diagram. So let us add two groups to the model and assign each of the original nodes to the corresponding group:
myDiagram.model = new go.GraphLinksModel(
[
{ key: "FD", isGroup: true, category: "FD" }, // NEW
{ key: "LD", isGroup: true, category: "LD" }, // NEW
{ key: "Alpha", color: "lightblue", group: "FD" },
{ key: "Beta", color: "orange", group: "FD" },
{ key: "Gamma", color: "lightgreen", group: "FD" },
{ key: "Delta", color: "pink", group: "FD" },
{ key: "Alpha2", color: "lightblue", group: "LD" },
{ key: "Beta2", color: "orange", group: "LD" },
{ key: "Gamma2", color: "lightgreen", group: "LD" },
{ key: "Delta2", color: "pink", group: "LD" }
],
[
{ from: "Alpha", to: "Beta" },
{ from: "Alpha", to: "Gamma" },
{ from: "Beta", to: "Beta" },
{ from: "Gamma", to: "Delta" },
{ from: "Delta", to: "Alpha" },
{ from: "Alpha2", to: "Beta2" },
{ from: "Alpha2", to: "Gamma2" },
{ from: "Beta2", to: "Beta2" },
{ from: "Gamma2", to: "Delta2" },
{ from: "Delta2", to: "Alpha2" }
]);
Now we just need to define each group/category/template:
myDiagram.groupTemplateMap.add("FD",
$(go.Group, "Auto",
{ layout: $(go.ForceDirectedLayout) },
$(go.Shape, { fill: "white", stroke: "lightgray" }),
$(go.Placeholder, { padding: 10 })
));
myDiagram.groupTemplateMap.add("LD",
$(go.Group, "Auto",
{ layout: $(go.LayeredDigraphLayout) },
$(go.Shape, { fill: "white", stroke: "lightgray" }),
$(go.Placeholder, { padding: 10 })
));
For the purposes of this demonstration the details of the visual appearance of each kind of group does not matter, just as the details of the appearances of the nodes and links do not matter. What does matter to you is that one group template uses one layout and the other uses a different one, there are two group data objects, and all the node data is assigned to the appropriate group.
In this case each group template is being used as a singleton, but perhaps your requirements will result in using more than one of any or all of the group templates.
Now you just need to specify the Diagram.layout to control how the two groups are arranged relative to each other. Perhaps the simplest would be to use a GridLayout:
myDiagram = $(go.Diagram, "myDiagramDiv",
{
initialContentAlignment: go.Spot.Center,
layout: $(go.GridLayout, { wrappingColumn: 1 }),
"undoManager.isEnabled": true
});
You can of course customize the layout in whatever manner you need, including using a completely different or custom layout.
Here's the complete code. For brevity I have removed a bunch of comments from the original Minimal sample:
<!DOCTYPE html>
<html>
<head>
<title>Combining 2 Diagrams with Different Layouts</title>
<!-- Copyright 1998-2016 by Northwoods Software Corporation. -->
<meta charset="UTF-8">
<script src="https://cdnjs.cloudflare.com/ajax/libs/gojs/1.6.5/go.js"></script>
<script id="code">
function init() {
var $ = go.GraphObject.make; // for conciseness in defining templates
myDiagram = $(go.Diagram, "myDiagramDiv",
{
initialContentAlignment: go.Spot.Center,
layout: $(go.GridLayout, { wrappingColumn: 1 }),
"undoManager.isEnabled": true
});
myDiagram.nodeTemplate =
$(go.Node, "Auto",
$(go.Shape, "RoundedRectangle",
new go.Binding("fill", "color")),
$(go.TextBlock, { margin: 3 },
new go.Binding("text", "key"))
);
myDiagram.groupTemplateMap.add("FD",
$(go.Group, "Auto",
{ layout: $(go.ForceDirectedLayout) },
$(go.Shape, { fill: "white", stroke: "lightgray" }),
$(go.Placeholder, { padding: 10 })
));
myDiagram.groupTemplateMap.add("LD",
$(go.Group, "Auto",
{ layout: $(go.LayeredDigraphLayout) },
$(go.Shape, { fill: "white", stroke: "lightgray" }),
$(go.Placeholder, { padding: 10 })
));
myDiagram.model = new go.GraphLinksModel(
[
{ key: "FD", isGroup: true, category: "FD" },
{ key: "LD", isGroup: true, category: "LD" },
{ key: "Alpha", color: "lightblue", group: "FD" },
{ key: "Beta", color: "orange", group: "FD" },
{ key: "Gamma", color: "lightgreen", group: "FD" },
{ key: "Delta", color: "pink", group: "FD" },
{ key: "Alpha2", color: "lightblue", group: "LD" },
{ key: "Beta2", color: "orange", group: "LD" },
{ key: "Gamma2", color: "lightgreen", group: "LD" },
{ key: "Delta2", color: "pink", group: "LD" }
],
[
{ from: "Alpha", to: "Beta" },
{ from: "Alpha", to: "Gamma" },
{ from: "Beta", to: "Beta" },
{ from: "Gamma", to: "Delta" },
{ from: "Delta", to: "Alpha" },
{ from: "Alpha2", to: "Beta2" },
{ from: "Alpha2", to: "Gamma2" },
{ from: "Beta2", to: "Beta2" },
{ from: "Gamma2", to: "Delta2" },
{ from: "Delta2", to: "Alpha2" }
]);
}
</script>
</head>
<body onload="init();">
<div id="sample">
<div id="myDiagramDiv" style="border: solid 1px black; width:400px; height:600px"></div>
</div>
</body>
</html>
I am new to GoJs but i tried this one.
Hope it helps :)
var $ = go.GraphObject.make;
//model
var myDiagram1 =
$(go.Diagram, "myNormal", {
initialContentAlignment: go.Spot.Center,
"undoManager.isEnabled": true // enable Ctrl-Z to undo and Ctrl-Y to redo
});
// define a simple Node template
myDiagram1.nodeTemplate =
$(go.Node, "Horizontal",
// the entire node will have a light-blue background
{
background: "#44CCFF"
},
$(go.Picture,
// Pictures should normally have an explicit width and height.
// This picture has a red background, only visible when there is no source set
// or when the image is partially transparent.
{
margin: 10,
width: 50,
height: 50,
background: "red"
},
// Picture.source is data bound to the "source" attribute of the model data
new go.Binding("source")),
$(go.TextBlock,
"Default Text", // the initial value for TextBlock.text
// some room around the text, a larger font, and a white stroke:
{
margin: 12,
stroke: "white",
font: "bold 16px sans-serif"
},
// TextBlock.text is data bound to the "name" attribute of the model data
new go.Binding("text", "name"))
);
var model = $(go.Model);
model.nodeDataArray = [ // note that each node data object holds whatever properties it needs;
// for this app we add the "name" and "source" properties
{
name: "Don Meow",
source: "cat1.png"
},
{
name: "Copricat",
source: "cat2.png"
},
{
name: "Demeter",
source: "cat3.png"
},
{ /* Empty node data */ }
];
myDiagram1.model = model;
// graph link model
var myDiagram2 =
$(go.Diagram, "graphlinksmodel", {
initialContentAlignment: go.Spot.Right,
"undoManager.isEnabled": true, // enable Ctrl-Z to undo and Ctrl-Y to redo
layout: $(go.TreeLayout, // specify a Diagram.layout that arranges trees
{
angle: 90,
layerSpacing: 35
})
});
// the template we defined earlier
myDiagram2.nodeTemplate =
$(go.Node, "Horizontal", {
background: "#44CCFF"
},
$(go.Picture, {
margin: 10,
width: 50,
height: 50,
background: "red"
},
new go.Binding("source")),
$(go.TextBlock, "Default Text", {
margin: 12,
stroke: "white",
font: "bold 16px sans-serif"
},
new go.Binding("text", "name"))
);
// define a Link template that routes orthogonally, with no arrowhead
myDiagram2.linkTemplate =
$(go.Link, {
routing: go.Link.Orthogonal,
corner: 5
},
$(go.Shape, {
strokeWidth: 3,
stroke: "#555"
})); // the link shape
var model = $(go.GraphLinksModel);
model.nodeDataArray = [{
key: "1",
name: "Don Meow",
source: "cat1.png"
},
{
key: "2",
name: "Demeter",
source: "cat2.png"
},
{
key: "3",
name: "Copricat",
source: "cat3.png"
},
{
key: "4",
name: "Jellylorum",
source: "cat4.png"
},
{
key: "5",
name: "Alonzo",
source: "cat5.png"
},
{
key: "6",
name: "Munkustrap",
source: "cat6.png"
}
];
model.linkDataArray = [{
from: "1",
to: "2"
},
{
from: "1",
to: "3"
},
{
from: "3",
to: "4"
},
{
from: "3",
to: "5"
},
{
from: "2",
to: "6"
}
];
myDiagram2.model = model;
//tree model
var myDiagram =
$(go.Diagram, "treemodel", {
"undoManager.isEnabled": true, // enable Ctrl-Z to undo and Ctrl-Y to redo
layout: $(go.TreeLayout, // specify a Diagram.layout that arranges trees
{
angle: 90,
layerSpacing: 35
})
});
// the template we defined earlier
myDiagram.nodeTemplate =
$(go.Node, "Horizontal", {
background: "#44CCFF"
},
$(go.Picture, {
margin: 10,
width: 50,
height: 50,
background: "red"
},
new go.Binding("source")),
$(go.TextBlock, "Default Text", {
margin: 12,
stroke: "white",
font: "bold 16px sans-serif"
},
new go.Binding("text", "name"))
);
// define a Link template that routes orthogonally, with no arrowhead
myDiagram.linkTemplate =
$(go.Link, {
routing: go.Link.Orthogonal,
corner: 5
},
$(go.Shape, {
strokeWidth: 3,
stroke: "#555"
})); // the link shape
var model = $(go.TreeModel);
model.nodeDataArray = [{
key: "1",
name: "Don Meow",
source: "cat1.png"
},
{
key: "2",
parent: "1",
name: "Demeter",
source: "cat2.png"
},
{
key: "3",
parent: "1",
name: "Copricat",
source: "cat3.png"
},
{
key: "4",
parent: "3",
name: "Jellylorum",
source: "cat4.png"
},
{
key: "5",
parent: "3",
name: "Alonzo",
source: "cat5.png"
},
{
key: "6",
parent: "2",
name: "Munkustrap",
source: "cat6.png"
}
];
myDiagram.model = model;
<!DOCTYPE html>
<!-- HTML5 document type -->
<html>
<head>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" integrity="sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB" crossorigin="anonymous">
</head>
<body>
<!-- The DIV for a Diagram needs an explicit size or else we will not see anything.
In this case we also add a background color so we can see that area. -->
<div class="container-fluid">
<div class="row">
<div class="col align-self-center" id="myNormal" style="width:400px; height:200px; background-color: #DAE4E4;"></div>
</div>
<div class="row">
<div class="col" id="graphlinksmodel" style="width:600px; height:300px; background-color: rgb(142, 236, 101);"></div>
<div class="col" id="treemodel" style="width:600px; height:300px; background-color: rgb(231, 243, 177);"></div>
</div>
</div>
<!-- use go-debug.js when developing and go.js when deploying -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js" integrity="sha384-smHYKdLADwkXOn1EmN1qk/HfnUcbVRZyYmZ4qpPea6sjB/pTJ0euyQp0Mk8ck+5T" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gojs/1.8.21/go-debug.js"></script>
<script src="./base.js"></script>
</body>
</html>