UNPKG

24.1 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
7<link rel="stylesheet" href="../assets/css/style.css"/>
8<!-- Copyright 1998-2021 by Northwoods Software Corporation. --> <title> GoJS Grid Patterns -- Northwoods Software </title>
9 <link rel="stylesheet" href="../assets/css/prism.css" />
10 </head>
11 <script>
12
13 window.diagrams = [];
14 window.goCode = function(pre, w, h, parentid, animation) {
15 window.diagrams.push([pre, w, h, parentid, animation]);
16 }
17 </script>
18 <body>
19 <nav id="navTop" class="w-full z-30 top-0 text-white bg-nwoods-primary">
20 <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">
21 <div class="md:pl-4">
22 <a class="text-white hover:text-white no-underline hover:no-underline
23 font-bold text-2xl lg:text-4xl rounded-lg hover:bg-nwoods-secondary " href="../">
24 <h1 class="mb-0 p-1 ">GoJS</h1>
25 </a>
26 </div>
27 <button id="topnavButton" class="rounded-lg sm:hidden focus:outline-none focus:ring" aria-label="Navigation">
28 <svg fill="currentColor" viewBox="0 0 20 20" class="w-6 h-6">
29 <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>
30 <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>
31 </svg>
32 </button>
33 <div id="topnavList" class="hidden sm:block items-center w-auto mt-0 text-white p-0 z-20">
34 <ul class="list-reset list-none font-semibold flex justify-end flex-wrap sm:flex-nowrap items-center px-0 pb-0">
35 <li class="p-1 sm:p-0"><a class="topnav-link" href="../learn/">Learn</a></li>
36 <li class="p-1 sm:p-0"><a class="topnav-link" href="../samples/">Samples</a></li>
37 <li class="p-1 sm:p-0"><a class="topnav-link" href="../intro/">Intro</a></li>
38 <li class="p-1 sm:p-0"><a class="topnav-link" href="../api/">API</a></li>
39 <li class="p-1 sm:p-0"><a class="topnav-link" href="https://www.nwoods.com/products/register.html">Register</a></li>
40 <li class="p-1 sm:p-0"><a class="topnav-link" href="../download.html">Download</a></li>
41 <li class="p-1 sm:p-0"><a class="topnav-link" href="https://forum.nwoods.com/c/gojs/11">Forum</a></li>
42 <li class="p-1 sm:p-0"><a class="topnav-link" href="https://www.nwoods.com/contact.html"
43 target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/contact.html', 'contact');">Contact</a></li>
44 <li class="p-1 sm:p-0"><a class="topnav-link" href="https://www.nwoods.com/sales/index.html"
45 target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/sales/index.html', 'buy');">Buy</a></li>
46 </ul>
47 </div>
48 </div>
49 <hr class="border-b border-gray-600 opacity-50 my-0 py-0" />
50 </nav>
51
52 <div class="md:flex flex-col md:flex-row md:min-h-screen w-full max-w-screen-xl mx-auto">
53
54 <div id="navSide" class="flex flex-col w-full md:w-40 lg:w-48 text-gray-700 bg-white flex-shrink-0">
55 <div class="flex-shrink-0 px-8 py-4">
56 <button id="navButton" class="rounded-lg md:hidden focus:outline-none focus:ring" aria-label="Navigation">
57 <svg fill="currentColor" viewBox="0 0 20 20" class="w-6 h-6">
58 <path id="navOpen" 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>
59 <path id="navClosed" 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>
60 </svg>
61 </button>
62 </div>
63 <nav id="navList" class="min-h-screen hidden md:block sidebar-nav flex-grow px-1 lg:px-4 pb-4 md:pb-0 md:overflow-y-auto break-words">
64 <a href="index.html">Basics</a>
65 <a href="buildingObjects.html">Building Parts</a>
66 <a href="usingModels.html">Using Models</a>
67 <a href="dataBinding.html">Data Binding</a>
68 <a href="react.html">GoJS with React</a>
69 <a href="angular.html">GoJS with Angular</a>
70 <a href="textBlocks.html">TextBlocks</a>
71 <a href="shapes.html">Shapes</a>
72 <a href="pictures.html">Pictures</a>
73 <a href="panels.html">Panels</a>
74 <a href="tablePanels.html">Table Panels</a>
75 <a href="brush.html">Brushes</a>
76 <a href="sizing.html">Sizing Objects</a>
77 <a href="itemArrays.html">Item Arrays</a>
78 <a href="changedEvents.html">Changed Events</a>
79 <a href="transactions.html">Transactions</a>
80 <a href="viewport.html">Coordinates</a>
81 <a href="initialView.html">Initial View</a>
82 <a href="collections.html">Collections</a>
83 <a href="links.html">Links</a>
84 <a href="linkLabels.html">Link Labels</a>
85 <a href="connectionPoints.html">Link Points</a>
86 <a href="ports.html">Ports</a>
87 <a href="nodes.html">Nodes</a>
88 <a href="debugging.html">Debugging</a>
89 <a href="layouts.html">Layouts</a>
90 <a href="trees.html">Trees</a>
91 <a href="subtrees.html">SubTrees</a>
92 <a href="groups.html">Groups</a>
93 <a href="subgraphs.html">SubGraphs</a>
94 <a href="sizedGroups.html">Sized Groups</a>
95 <a href="selection.html">Selection</a>
96 <a href="highlighting.html">Highlighting</a>
97 <a href="animation.html">Animation</a>
98 <a href="toolTips.html">ToolTips</a>
99 <a href="contextmenus.html">Context Menus</a>
100 <a href="events.html">Diagram Events</a>
101 <a href="tools.html">Tools</a>
102 <a href="commands.html">Commands</a>
103 <a href="permissions.html">Permissions</a>
104 <a href="validation.html">Validation</a>
105 <a href="HTMLInteraction.html">HTML Interaction</a>
106 <a href="layers.html">Layers &amp; Z-ordering</a>
107 <a href="palette.html">Palette</a>
108 <a href="overview.html">Overview</a>
109 <a href="resizing.html">Resizing Diagrams</a>
110 <a href="replacingDeleting.html">Replacing and Deleting</a>
111 <a href="buttons.html">Buttons</a>
112 <a href="templateMaps.html">Template Maps</a>
113 <a href="legends.html">Legends and Titles</a>
114 <a href="extensions.html">Extensions</a>
115 <a href="geometry.html">Geometry Strings</a>
116 <a href="grids.html">Grid Patterns</a>
117 <a href="graduatedPanels.html">Graduated Panels</a>
118 <a href="makingImages.html">Diagram Images</a>
119 <a href="makingSVG.html">Diagram SVG</a>
120 <a href="printing.html">Printing</a>
121 <a href="serverSideImages.html">Server-side Images</a>
122 <a href="nodeScript.html">GoJS in Node.js</a>
123 <a href="testing.html">Testing</a>
124 <a href="storage.html">Storage</a>
125 <a href="performance.html">Performance</a>
126 <a href="source.html">Building from Source</a>
127 <a href="platforms.html">Platforms</a>
128 <a href="deployment.html">Deployment</a>
129 </nav>
130 </div>
131 <div class="pt-4 px-2 md:px-0 lg:px-4 pb-16 w-full overflow-hidden">
132
133<h1>Grid Patterns</h1>
134<p>
135It is common to want to display a grid of lines drawn at regular intervals.
136You may also want to force dragged parts to be aligned on grid points, and to resize parts to be multiples of the grid cell size.
137</p>
138<p>
139Grids are implemented using a type of <a>Panel</a>, <a>Panel,Grid</a>.
140Grid Panels, like most other types of Panels, can be used within <a>Node</a>s or any other kind of <a>Part</a>.
141However when they are used as the <a>Diagram.grid</a>, they are effectively infinite in extent.
142</p>
143<p>
144Unlike in other kinds of <a>Panel</a>s, Grid Panel elements must be <a>Shape</a>s that are only used to control how the grid lines or grid bars are drawn.
145</p>
146<p>
147See samples that make use of grids in the <a href="../samples/index.html#grid">samples index</a>.
148</p>
149
150<h2 id="DefaultGrid">Default Grid</h2>
151<p>
152To display a grid pattern in the background of the diagram, you can just make the <a>Diagram.grid</a> visible:
153</p>
154<pre class="lang-js" id="defaultGrid"><code>
155 diagram.grid.visible = true;
156
157 diagram.nodeTemplate =
158 $(go.Node, "Auto",
159 $(go.Shape, "Rectangle", { fill: "lightgray" }),
160 $(go.TextBlock, { margin: 5},
161 new go.Binding("text", "key"))
162 );
163 var nodeDataArray = [
164 { key: "Alpha" }, { key: "Beta" }, { key: "Gamma" }
165 ];
166 diagram.model = new go.GraphLinksModel(nodeDataArray);
167</code></pre>
168<script>goCode("defaultGrid", 600, 150)</script>
169
170<h2 id="GridSnapping">Grid Snapping</h2>
171<p>
172The <a>DraggingTool</a> and <a>ResizingTool</a> can change their behavior based on the background grid pattern,
173if you set the <a>DraggingTool.isGridSnapEnabled</a> and/or <a>ResizingTool.isGridSnapEnabled</a> properties to true.
174</p>
175<p>
176 Setting <a>DraggingTool.isGridSnapEnabled</a> to true will not affect disconnected Links,
177 but these can snap if you define a custom <a>Part.dragComputation</a> to do so on the Link template.
178</p>
179<pre class="lang-js" id="gridSnapping"><code>
180 diagram.grid.visible = true;
181 diagram.toolManager.draggingTool.isGridSnapEnabled = true;
182 diagram.toolManager.resizingTool.isGridSnapEnabled = true;
183
184
185 diagram.nodeTemplate =
186 $(go.Node, "Auto",
187 { resizable: true },
188 $(go.Shape, "Rectangle", { fill: "lightgray" }),
189 $(go.TextBlock, { margin: 5},
190 new go.Binding("text", "key"))
191 );
192 var nodeDataArray = [
193 { key: "Alpha" }, { key: "Beta" }, { key: "Gamma" }
194 ];
195 diagram.model = new go.GraphLinksModel(nodeDataArray);
196</code></pre>
197<script>goCode("gridSnapping", 600, 150)</script>
198
199<h2 id="SimpleGridCustomization">Simple Grid Customization</h2>
200<p>
201You can change the size of the grid cell by setting <a>Panel.gridCellSize</a>:
202</p>
203<pre class="lang-js" id="biggerGrid"><code>
204 diagram.grid.visible = true;
205 diagram.grid.gridCellSize = new go.Size(30, 20);
206 diagram.toolManager.draggingTool.isGridSnapEnabled = true;
207 diagram.toolManager.resizingTool.isGridSnapEnabled = true;
208
209
210 diagram.nodeTemplate =
211 $(go.Node, "Auto",
212 { resizable: true },
213 $(go.Shape, "Rectangle", { fill: "lightgray" }),
214 $(go.TextBlock, { margin: 5},
215 new go.Binding("text", "key"))
216 );
217 var nodeDataArray = [
218 { key: "Alpha" }, { key: "Beta" }, { key: "Gamma" }
219 ];
220 diagram.model = new go.GraphLinksModel(nodeDataArray);
221</code></pre>
222<script>goCode("biggerGrid", 600, 150)</script>
223
224<p>
225The cell size used when snapping the locations of Parts during a drag need not be exactly
226the same as the background grid's cell size.
227The value of <a>DraggingTool.gridSnapCellSize</a> takes precedence over the <a>Panel.gridCellSize</a>.
228Note that if <a>DraggingTool.gridSnapCellSize</a> is set but <a>ResizingTool.cellSize</a> is not,
229Parts will use the DraggingTool.gridSnapCellSize value when resizing.
230</p>
231<pre class="lang-js" id="gridSnapping2"><code>
232 diagram.grid.visible = true;
233 diagram.toolManager.draggingTool.isGridSnapEnabled = true;
234 diagram.toolManager.resizingTool.isGridSnapEnabled = true;
235
236 // snap to every other point both vertically and horizontally
237 // (the default background grid has a cell size of 10x10)
238 diagram.toolManager.draggingTool.gridSnapCellSize = new go.Size(20, 20);
239
240
241 diagram.nodeTemplate =
242 $(go.Node, "Auto",
243 { resizable: true },
244 $(go.Shape, "Rectangle", { fill: "lightgray" }),
245 $(go.TextBlock, { margin: 5},
246 new go.Binding("text", "key"))
247 );
248 var nodeDataArray = [
249 { key: "Alpha" }, { key: "Beta" }, { key: "Gamma" }
250 ];
251 diagram.model = new go.GraphLinksModel(nodeDataArray);
252</code></pre>
253<script>goCode("gridSnapping2", 600, 150)</script>
254
255<h2 id="CustomGrids">Custom Grids</h2>
256<p>
257Grid patterns are implemented by the <a>Panel</a> class when its <a>Panel.type</a> is <a>Panel,Grid</a>.
258The elements of a Grid Panel must be <a>Shape</a>s whose <a>Shape.figure</a> is one of a small set of known kinds of figures.
259The only figures it can accept are: "LineH", "LineV", "BarH", and "BarV".
260The two "Line" figures result in stroked lines separating the grid cells;
261the two "Bar" figures result in filled rectangles in the grid cells.
262</p>
263<p>
264Here is a simple grid consisting of blue horizontal lines and green vertical lines:
265</p>
266<pre class="lang-js" id="customBackground"><code>
267 diagram.grid =
268 $(go.Panel, go.Panel.Grid, // or "Grid"
269 { gridCellSize: new go.Size(25, 25) },
270 $(go.Shape, "LineH", { stroke: "blue" }),
271 $(go.Shape, "LineV", { stroke: "green" })
272 );
273</code></pre>
274<script>goCode("customBackground", 600, 150)</script>
275
276<p>
277The <a>Shape.interval</a> property is also used by a Grid Panel to determine how frequently a line should be drawn.
278The value should be a positive integer specifying how many cells there are between drawings of this particular line.
279So if you wanted darker blue and darker green lines every five cells:
280</p>
281<pre class="lang-js" id="customBackground2"><code>
282 diagram.grid =
283 $(go.Panel, "Grid",
284 { gridCellSize: new go.Size(10, 10) },
285 $(go.Shape, "LineH", { stroke: "lightblue" }),
286 $(go.Shape, "LineV", { stroke: "lightgreen" }),
287 $(go.Shape, "LineH", { stroke: "blue", interval: 5 }),
288 $(go.Shape, "LineV", { stroke: "green", interval: 5 })
289 );
290
291
292 diagram.nodeTemplate =
293 $(go.Node, "Auto",
294 { resizable: true },
295 $(go.Shape, "Rectangle", { fill: "lightgray" }),
296 $(go.TextBlock, { margin: 5},
297 new go.Binding("text", "key"))
298 );
299 var nodeDataArray = [
300 { key: "Alpha" }
301 ];
302 diagram.model = new go.GraphLinksModel(nodeDataArray);
303</code></pre>
304<script>goCode("customBackground2", 600, 150)</script>
305<p>
306Note that the Shapes are drawn in the order in which they appear in the Panel,
307so you can see that the dark blue horizontal lines are drawn in front of the light green vertical lines,
308and that the dark green vertical line crosses in front of the dark blue horizontal lines.
309</p>
310<p>
311Here is the definition of the predefined <a>Diagram.grid</a>:
312</p>
313 <pre class="lang-js" id="standardGrid"><code>
314 diagram.grid =
315 $(go.Panel, "Grid",
316 {
317 name: "GRID",
318 visible: false,
319 gridCellSize: new go.Size(10, 10),
320 gridOrigin: new go.Point(0, 0)
321 },
322 $(go.Shape, "LineH", { stroke: "lightgray", strokeWidth: 0.5, interval: 1 }),
323 $(go.Shape, "LineH", { stroke: "gray", strokeWidth: 0.5, interval: 5 }),
324 $(go.Shape, "LineH", { stroke: "gray", strokeWidth: 1.0, interval: 10 }),
325 $(go.Shape, "LineV", { stroke: "lightgray", strokeWidth: 0.5, interval: 1 }),
326 $(go.Shape, "LineV", { stroke: "gray", strokeWidth: 0.5, interval: 5 }),
327 $(go.Shape, "LineV", { stroke: "gray", strokeWidth: 1.0, interval: 10 })
328 );
329
330 diagram.grid.visible = true; // so that this example shows the standard grid
331 diagram.div.style.background = "white";
332</code></pre>
333<script>goCode("standardGrid", 600, 150)</script>
334<p>
335You can get a green-bar pattern by using the "BarH" figure. Note the use of <a>Shape.fill</a>
336instead of <a>Shape.stroke</a> and explicitly setting the <a>GraphObject.height</a>:
337</p>
338<pre class="lang-js" id="customBackground3"><code>
339 diagram.grid =
340 $(go.Panel, "Grid",
341 { gridCellSize: new go.Size(50, 50) },
342 $(go.Shape, "BarH", { fill: "lightgreen", interval: 2, height: 50 })
343 );
344
345
346 diagram.nodeTemplate =
347 $(go.Node, "Auto",
348 {
349 dragComputation: function(node, pt, gridpt) {
350 pt.y = Math.round(pt.y/100)*100;
351 return pt;
352 }
353 },
354 $(go.Shape, "Rectangle", { fill: "lightgray" }),
355 $(go.TextBlock, { margin: 5},
356 new go.Binding("text", "key"))
357 );
358 var nodeDataArray = [
359 { key: "Alpha" }
360 ];
361 diagram.model = new go.GraphLinksModel(nodeDataArray);
362</code></pre>
363<script>goCode("customBackground3", 600, 350)</script>
364<p>
365This example also demonstrates how one can use the <a>Part.dragComputation</a> property to customize where
366the user can drag the node. In this case the <a>Part.location</a>.y is limited to be multiples of 100,
367corresponding to the rows of cells filled by the green bars.
368</p>
369<p>
370To get a tablecloth effect, one can use both vertical and horizontal bars with a translucent color:
371</p>
372<pre class="lang-js" id="customBackground4"><code>
373 diagram.grid =
374 $(go.Panel, "Grid",
375 { gridCellSize: new go.Size(100, 100) },
376 $(go.Shape, "BarV", { fill: "rgba(255,0,0,0.1)", width: 50 }),
377 $(go.Shape, "BarH", { fill: "rgba(255,0,0,0.1)", height: 50 })
378 );
379
380 diagram.toolManager.draggingTool.isGridSnapEnabled = true;
381
382 diagram.nodeTemplate =
383 $(go.Node, "Auto",
384 { width: 50, height: 50 },
385 $(go.Shape, "Rectangle", { fill: "lightgray" }),
386 $(go.TextBlock, { margin: 5},
387 new go.Binding("text", "key"))
388 );
389 var nodeDataArray = [
390 { key: "Alpha" }
391 ];
392 diagram.model = new go.GraphLinksModel(nodeDataArray);
393</code></pre>
394<script>goCode("customBackground4", 600, 350)</script>
395<p>
396This example limits dragging of all nodes by setting <a>DraggingTool.isGridSnapEnabled</a> to true.
397</p>
398<p>
399Here is an example of using a "Grid" <a>Panel</a> as a regular data bound element in a <a>Node</a>:
400</p>
401<pre class="lang-js" id="nodeGrid"><code>
402
403 diagram.nodeTemplate =
404 $(go.Node, "Auto",
405 { resizable: true, resizeObjectName: "GRID" },
406 $(go.Shape, "Rectangle", { fill: "transparent" }),
407 $(go.Panel, "Grid",
408 { name: "GRID", desiredSize: new go.Size(100, 100), gridCellSize: new go.Size(20, 20) },
409 new go.Binding("desiredSize", "size", go.Size.parse).makeTwoWay(go.Size.stringify),
410 new go.Binding("gridCellSize", "cell", go.Size.parse).makeTwoWay(go.Size.stringify),
411 $(go.Shape, "LineV",
412 new go.Binding("stroke")),
413 $(go.Shape, "LineH",
414 new go.Binding("stroke"))
415 ));
416
417 diagram.model = new go.GraphLinksModel([
418 { key: "Alpha", cell: "25 25", stroke: "lightgreen" },
419 { key: "Beta", size: "150 75", cell: "15 30" }
420 ]);
421</code></pre>
422<script>goCode("nodeGrid", 600, 350)</script>
423
424<h2 id="OtherConsiderations">Other Considerations</h2>
425<p>
426 A Grid Panel should have a non-null <code>background</code> if it needs to be pickable.
427 One cannot set or bind the <a>Panel.itemArray</a> of a Grid Panel.
428</p>
429<p>
430 Events on the Shapes will be ignored.
431 Shapes in a Grid Panel must not be scaled or rotated.
432</p>
433
434 </div>
435 </div>
436
437 <div class="bg-nwoods-primary">
438 <section class="max-w-screen-lg text-white container mx-auto py-2 px-12">
439 <p id="version" class="leading-none mb-2 my-4">GoJS</p>
440 </section>
441 </div><footer class="bg-nwoods-primary text-white">
442 <div class="container max-w-screen-lg mx-auto px-8">
443 <div class="w-full py-6">
444
445 <div class="max-w-screen-lg xl:max-w-screen-xl mx-auto px-4 sm:px-6 md:px-8">
446 <ul class="text-sm font-medium pb-14 sm:pb-20 grid grid-cols-1 sm:grid-cols-3 gap-y-10">
447 <li class="list-none row-span-2">
448 <h2 class="text-base font-semibold tracking-wide">GoJS</h2>
449 <ul class="list-none space-y-4 md:space-y-1 px-0">
450 <li>
451 <a href="../samples/index.html">Samples</a>
452 </li>
453 <li>
454 <a href="../learn/index.html">Learn</a>
455 </li>
456 <li>
457 <a href="../intro/index.html">Intro</a>
458 </li>
459 <li>
460 <a href="../api/index.html">API</a>
461 </li>
462 <li>
463 <a href="../changelog.html">Changelog</a>
464 </li>
465 <li>
466 <a href="https://github.com/NorthwoodsSoftware/GoJS">GitHub</a>
467 </li>
468 </ul>
469 </li>
470 <li class="list-none row-span-2">
471 <h2 class="text-base font-semibold tracking-wide">Support</h2>
472 <ul class="list-none space-y-4 md:space-y-1 px-0">
473 <li>
474 <a href="https://www.nwoods.com/contact.html"
475 target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/contact.html', 'contact');">Contact</a>
476 </li>
477 <li>
478 <a href="https://forum.nwoods.com/c/gojs">Forum</a>
479 </li>
480 <li>
481 <a href="https://www.nwoods.com/app/activate.aspx?sku=gojs">Activate</a>
482 </li>
483 <li>
484 <a href="https://www.nwoods.com/sales/index.html"
485 target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/sales/index.html', 'buy');">Buy</a>
486 </li>
487 <li>
488 <a href="https://www.youtube.com/channel/UC9We8EoX596-6XFjJDtZIDg">Videos</a>
489 </li>
490 </ul>
491 </li>
492 <li class="list-none row-span-2">
493 <h2 class="text-base font-semibold tracking-wide">Company</h2>
494 <ul class="list-none space-y-4 md:space-y-1 px-0">
495 <li>
496 <a href="https://www.nwoods.com">Northwoods</a>
497 </li>
498 <li>
499 <a href="https://www.nwoods.com/about.html">About Us</a>
500 </li>
501 <li>
502 <a href="https://www.nwoods.com/contact.html">Contact Us</a>
503 </li>
504 <li>
505 <a href="https://twitter.com/northwoodsgo">Twitter</a>
506 </li>
507
508 </ul>
509 </li>
510 </ul>
511
512
513 <p class="text-sm text-gray-100 md:mb-6">
514 Copyright 1998-2021 <a class="text-white" href="https://www.nwoods.com">Northwoods Software</a>
515 </p>
516 </div>
517 </div>
518</footer> </body>
519
520<script async src="https://www.googletagmanager.com/gtag/js?id=UA-1506307-5"></script>
521<script>
522 window.dataLayer = window.dataLayer || [];
523 function gtag(){dataLayer.push(arguments);}
524 gtag('js', new Date()); gtag('config', 'UA-1506307-5');
525 var getOutboundLink = function(url, label) {
526 gtag('event', 'click', {
527 'event_category': 'outbound',
528 'event_label': label,
529 'transport_type': 'beacon'
530 });
531 }
532
533 // topnav
534 var topButton = document.getElementById("topnavButton");
535 var topnavList = document.getElementById("topnavList");
536 topButton.addEventListener("click", function() {
537 this.classList.toggle("active");
538 topnavList.classList.toggle("hidden");
539 document.getElementById("topnavOpen").classList.toggle("hidden");
540 document.getElementById("topnavClosed").classList.toggle("hidden");
541 });
542</script>
543 <script src="../assets/js/prism.js"></script>
544 <script src="../release/go.js"></script>
545 <script src="../assets/js/goDoc.js"></script>
546 <script>
547 document.addEventListener("DOMContentLoaded", function() {
548 if (window.go) document.getElementById('version').textContent = "GoJS version " + go.version;
549 if (window.goDoc) window.goDoc();
550 var d = window.diagrams;
551 for (var i = 0; i < d.length; i++) {
552 var dargs = d[i];
553 goCodeExecute(dargs[0], dargs[1], dargs[2], dargs[3], dargs[4]);
554 }
555 if (window.extra) window.extra();
556 });
557 </script>
558</html>