UNPKG

14.2 kBHTMLView Raw
1<!DOCTYPE html>
2<html lang="en">
3<head>
4<meta charset="utf-8"/>
5<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, viewport-fit=cover"/>
6<meta name="description" content="TypeScript: SwimLaneLayout, laying out the whole graph while assigning nodes to stay in lanes/groups."/>
7<link rel="stylesheet" href="../assets/css/style.css"/>
8<!-- Copyright 1998-2021 by Northwoods Software Corporation. -->
9<title>Beat Paths with Lanes for Divisions Using SwimLaneLayout</title>
10</head>
11
12<body>
13 <!-- This top nav is not part of the sample code -->
14 <nav id="navTop" class="w-full z-30 top-0 text-white bg-nwoods-primary">
15 <div class="w-full container max-w-screen-lg mx-auto flex flex-wrap sm:flex-nowrap items-center justify-between mt-0 py-2">
16 <div class="md:pl-4">
17 <a class="text-white hover:text-white no-underline hover:no-underline
18 font-bold text-2xl lg:text-4xl rounded-lg hover:bg-nwoods-secondary " href="../">
19 <h1 class="mb-0 p-1 ">GoJS</h1>
20 </a>
21 </div>
22 <button id="topnavButton" class="rounded-lg sm:hidden focus:outline-none focus:ring" aria-label="Navigation">
23 <svg fill="currentColor" viewBox="0 0 20 20" class="w-6 h-6">
24 <path id="topnavOpen" fill-rule="evenodd" d="M3 5a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM3 10a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM9 15a1 1 0 011-1h6a1 1 0 110 2h-6a1 1 0 01-1-1z" clip-rule="evenodd"></path>
25 <path id="topnavClosed" class="hidden" fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path>
26 </svg>
27 </button>
28 <div id="topnavList" class="hidden sm:block items-center w-auto mt-0 text-white p-0 z-20">
29 <ul class="list-reset list-none font-semibold flex justify-end flex-wrap sm:flex-nowrap items-center px-0 pb-0">
30 <li class="p-1 sm:p-0"><a class="topnav-link" href="../learn/">Learn</a></li>
31 <li class="p-1 sm:p-0"><a class="topnav-link" href="../samples/">Samples</a></li>
32 <li class="p-1 sm:p-0"><a class="topnav-link" href="../intro/">Intro</a></li>
33 <li class="p-1 sm:p-0"><a class="topnav-link" href="../api/">API</a></li>
34 <li class="p-1 sm:p-0"><a class="topnav-link" href="https://www.nwoods.com/products/register.html">Register</a></li>
35 <li class="p-1 sm:p-0"><a class="topnav-link" href="../download.html">Download</a></li>
36 <li class="p-1 sm:p-0"><a class="topnav-link" href="https://forum.nwoods.com/c/gojs/11">Forum</a></li>
37 <li class="p-1 sm:p-0"><a class="topnav-link" href="https://www.nwoods.com/contact.html"
38 target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/contact.html', 'contact');">Contact</a></li>
39 <li class="p-1 sm:p-0"><a class="topnav-link" href="https://www.nwoods.com/sales/index.html"
40 target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/sales/index.html', 'buy');">Buy</a></li>
41 </ul>
42 </div>
43 </div>
44 <hr class="border-b border-gray-600 opacity-50 my-0 py-0" />
45 </nav>
46 <div class="md:flex flex-col md:flex-row md:min-h-screen w-full max-w-screen-xl mx-auto">
47 <div id="navSide" class="flex flex-col w-full md:w-48 text-gray-700 bg-white flex-shrink-0"></div>
48 <!-- * * * * * * * * * * * * * -->
49 <!-- Start of GoJS sample code -->
50
51
52 <div class="p-4 w-full">
53<div id="sample">
54 <p><b>Beat Paths</b>: The 2007 NFL Season, divided by conference or by division</p>
55 <div id="myDiagramDiv" style="border: solid 1px gray; margin: 10px; height: 700px"></div>
56 <input type="radio" name="A" id="conferenceButton" />
57 <label for="conferenceButton">Conferences</label><br />
58 <input type="radio" name="A" id="divisionButton" checked />
59 <label for="divisionButton">Divisions</label><br />
60</div>
61<script type="module" id="code">
62 import * as go from "../release/go-module.js";
63 import { SwimLaneLayout } from "./SwimLaneLayout.js";
64
65 if (window.goSamples) window.goSamples(); // init for these samples -- you don't need to call this
66 const $ = go.GraphObject.make; // for conciseness in defining templates
67
68 const DIRECTION = 90; // used to customize the layout and the templates, only upon first initialization
69
70 const myDiagram =
71 $(go.Diagram, "myDiagramDiv",
72 { // automatically scale the diagram to fit the viewport's size
73 initialAutoScale: go.Diagram.Uniform,
74 // disable user copying of parts
75 allowCopy: false,
76 // position all of the nodes and route all of the links
77 layout:
78 $(SwimLaneLayout,
79 {
80 laneProperty: "group", // needs to know how to assign vertexes/nodes into lanes/groups
81 direction: DIRECTION, // Group template also depends on DIRECTION
82 setsPortSpots: false,
83 layerSpacing: 20,
84 columnSpacing: 5,
85 commitLayers: function(layerRects, offset) {
86 if (layerRects.length === 0) return;
87
88 var horiz = (this.direction === 0 || this.direction === 180);
89 var forwards = (this.direction === 0 || this.direction === 90);
90
91 var rect = layerRects[forwards ? layerRects.length - 1 : 0];
92 var totallength = horiz ? rect.right : rect.bottom;
93
94 for (var i = 0; i < this.laneNames.length; i++) {
95 var lane = this.laneNames[i];
96 // assume lane names do not conflict with node names
97 var group = this.diagram.findNodeForKey(lane);
98 if (group === null) {
99 this.diagram.model.addNodeData({ key: lane, isGroup: true });
100 group = this.diagram.findNodeForKey(lane);
101 }
102 if (horiz) {
103 group.location = new go.Point(-this.layerSpacing / 2, this.lanePositions.get(lane) * this.columnSpacing + offset.y);
104 } else {
105 group.location = new go.Point(this.lanePositions.get(lane) * this.columnSpacing + offset.x, -this.layerSpacing / 2);
106 }
107 var ph = group.findObject("PLACEHOLDER"); // won't be a go.Placeholder, but just a regular Shape
108 if (ph === null) ph = group;
109 if (horiz) {
110 ph.desiredSize = new go.Size(totallength, this.laneBreadths.get(lane) * this.columnSpacing);
111 } else {
112 ph.desiredSize = new go.Size(this.laneBreadths.get(lane) * this.columnSpacing, totallength);
113 }
114 }
115 }
116 })
117 });
118
119 // replace the default Node template in the nodeTemplateMap
120 myDiagram.nodeTemplate =
121 $(go.Node, "Vertical", // the whole node panel
122 { // when the DIRECTION is vertical, use the whole Node as the port
123 fromSpot: go.Spot.TopBottomSides,
124 toSpot: go.Spot.TopBottomSides
125 },
126 $(go.TextBlock, // the text label
127 new go.Binding("text", "key")),
128 $(go.Picture, // the icon showing the logo
129 // You should set the desiredSize (or width and height)
130 // whenever you know what size the Picture should be.
131 {
132 desiredSize: new go.Size(50, 50),
133 // when the DIRECTION is horizontal, use this icon as the port
134 portId: (DIRECTION === 0 || DIRECTION === 180) ? "" : null,
135 fromSpot: go.Spot.LeftRightSides,
136 toSpot: go.Spot.LeftRightSides
137 },
138 new go.Binding("source", "key", convertKeyImage))
139 );
140
141 function convertKeyImage(key) {
142 if (!key) key = "NE";
143 return "https://www.nwoods.com/go/beatpaths/" + key + "_logo-50x50.png";
144 }
145
146 // replace the default Link template in the linkTemplateMap
147 myDiagram.linkTemplate =
148 $(go.Link, // the whole link panel
149 { routing: go.Link.AvoidsNodes, corner: 10 },
150 $(go.Shape, // the link shape
151 { strokeWidth: 1.5 }),
152 $(go.Shape, // the arrowhead
153 { toArrow: "Standard", stroke: null })
154 );
155
156 myDiagram.groupTemplate = // assumes SwimLaneLayout.direction === 0
157 $(go.Group, (DIRECTION === 0 || DIRECTION === 180) ? "Horizontal" : "Vertical",
158 {
159 layerName: "Background", // always behind all regular nodes and links
160 movable: false, // user cannot move or copy any lanes
161 copyable: false,
162 locationObjectName: "PLACEHOLDER", // this object will be sized and located by SwimLaneLayout
163 layout: null, // no lane lays out its member nodes
164 avoidable: false // don't affect any AvoidsNodes link routes
165 },
166 $(go.TextBlock, { font: "bold 12pt sans-serif", angle: (DIRECTION === 0 || DIRECTION === 180) ? 270 : 0 },
167 new go.Binding("text", "key")),
168 $(go.Panel, "Auto",
169 $(go.Shape, { fill: "transparent", stroke: "orange" }),
170 $(go.Shape, { name: "PLACEHOLDER", fill: null, stroke: null, strokeWidth: 0 })
171 ),
172 $(go.TextBlock, { font: "bold 12pt sans-serif", angle: (DIRECTION === 0 || DIRECTION === 180) ? 90 : 0 },
173 new go.Binding("text", "key"))
174 );
175
176 // the array of node data describing each team, each division, and each conference
177 const nodeDataArray = [
178 { key: "AFC", isGroup: true },
179 { key: "NFC", isGroup: true },
180 { key: "AFCE", isGroup: true },
181 { key: "AFCN", isGroup: true },
182 { key: "AFCS", isGroup: true },
183 { key: "AFCW", isGroup: true },
184 { key: "NFCE", isGroup: true },
185 { key: "NFCN", isGroup: true },
186 { key: "NFCS", isGroup: true },
187 { key: "NFCW", isGroup: true },
188 { key: "NE", conf: "AFC", div: "AFCE" },
189 { key: "PIT", conf: "AFC", div: "AFCN" },
190 { key: "DAL", conf: "NFC", div: "NFCE" },
191 { key: "CLE", conf: "AFC", div: "AFCN" },
192 { key: "NYG", conf: "NFC", div: "NFCE" },
193 { key: "GB", conf: "NFC", div: "NFCN" },
194 { key: "SEA", conf: "NFC", div: "NFCW" },
195 { key: "IND", conf: "AFC", div: "AFCS" },
196 { key: "MIN", conf: "NFC", div: "NFCN" },
197 { key: "PHI", conf: "NFC", div: "NFCE" },
198 { key: "DET", conf: "NFC", div: "NFCN" },
199 { key: "JAC", conf: "AFC", div: "AFCS" },
200 { key: "SD", conf: "AFC", div: "AFCW" },
201 { key: "CHI", conf: "NFC", div: "NFCN" },
202 { key: "TB", conf: "NFC", div: "NFCS" },
203 { key: "KC", conf: "AFC", div: "AFCW" },
204 { key: "DEN", conf: "AFC", div: "AFCW" },
205 { key: "TEN", conf: "AFC", div: "AFCS" },
206 { key: "BUF", conf: "AFC", div: "AFCE" },
207 { key: "OAK", conf: "AFC", div: "AFCW" },
208 { key: "HOU", conf: "AFC", div: "AFCS" },
209 { key: "ATL", conf: "NFC", div: "NFCS" },
210 { key: "WAS", conf: "NFC", div: "NFCE" },
211 { key: "CIN", conf: "AFC", div: "AFCN" },
212 { key: "NYJ", conf: "AFC", div: "AFCE" },
213 { key: "CAR", conf: "NFC", div: "NFCS" },
214 { key: "NO", conf: "NFC", div: "NFCS" },
215 { key: "BAL", conf: "AFC", div: "AFCN" },
216 { key: "MIA", conf: "AFC", div: "AFCE" },
217 { key: "ARI", conf: "NFC", div: "NFCW" },
218 { key: "STL", conf: "NFC", div: "NFCW" },
219 { key: "SF", conf: "NFC", div: "NFCW" }
220 ];
221
222 // the array of link data objects: the relationships between the nodes
223 const linkDataArray = [
224 { from: "NE", to: "CLE" },
225 { from: "NE", to: "DAL" },
226 { from: "NE", to: "IND" },
227 { from: "PIT", to: "CLE" },
228 { from: "DAL", to: "NYG" },
229 { from: "DAL", to: "GB" },
230 { from: "CLE", to: "SEA" },
231 { from: "NYG", to: "DET" },
232 { from: "GB", to: "MIN" },
233 { from: "GB", to: "PHI" },
234 { from: "SEA", to: "PHI" },
235 { from: "SEA", to: "CIN" },
236 { from: "IND", to: "TB" },
237 { from: "IND", to: "JAC" },
238 { from: "MIN", to: "SD" },
239 { from: "PHI", to: "NYJ" },
240 { from: "DET", to: "CHI" },
241 { from: "DET", to: "DEN" },
242 { from: "JAC", to: "DEN" },
243 { from: "SD", to: "DEN" },
244 { from: "CHI", to: "OAK" },
245 { from: "TB", to: "TEN" },
246 { from: "DEN", to: "TEN" },
247 { from: "DEN", to: "KC" },
248 { from: "DEN", to: "BUF" },
249 { from: "TEN", to: "OAK" },
250 { from: "TEN", to: "ATL" },
251 { from: "TEN", to: "HOU" },
252 { from: "BUF", to: "WAS" },
253 { from: "OAK", to: "MIA" },
254 { from: "HOU", to: "MIA" },
255 { from: "HOU", to: "CAR" },
256 { from: "WAS", to: "NYJ" },
257 { from: "WAS", to: "ARI" },
258 { from: "CIN", to: "BAL" },
259 { from: "NYJ", to: "MIA" },
260 { from: "CAR", to: "ARI" },
261 { from: "CAR", to: "STL" },
262 { from: "CAR", to: "SF" },
263 { from: "NO", to: "SF" },
264 { from: "BAL", to: "STL" },
265 { from: "BAL", to: "SF" }
266 ];
267
268 function partitionBy(a) {
269 // create the model and assign it to the Diagram
270 const model = new go.GraphLinksModel();
271 // depending on how we are partitioning the graph, each node belongs either
272 // to a conference group or to a division group
273 model.nodeGroupKey = (a === 'c') ? "conf" : "div";
274 model.nodeDataArray = nodeDataArray;
275 model.linkDataArray = linkDataArray;
276 // each node's lane information is the same as the group information
277 myDiagram.layout.laneProperty = model.nodeGroupKey;
278 // optionally, specify the order of known lane names, without setting laneComparer
279 myDiagram.layout.laneNames = (a === 'c') ?
280 ["AFC", "NFC"] :
281 ["AFCE", "AFCN", "AFCS", "AFCW", "NFCE", "NFCN", "NFCS", "NFCW"];
282 myDiagram.model = model;
283 }
284
285 partitionBy('d');
286
287 document.getElementById("conferenceButton").onclick = function() { partitionBy('c'); }
288 document.getElementById("divisionButton").onclick = function() { partitionBy('d'); }
289 </script>
290 </div>
291 <!-- * * * * * * * * * * * * * -->
292 <!-- End of GoJS sample code -->
293 </div>
294</body>
295<!-- This script is part of the gojs.net website, and is not needed to run the sample -->
296<script src="../assets/js/goSamples.js"></script>
297</html>