UNPKG

30.5 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 Debugging Suggestions-- 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<div id="container" class="container-fluid">
134 <div id="content">
135
136 <h1>Debugging Suggestions</h1>
137
138 <p>
139 Developing a diagramming app involves a lot more than just writing some JavaScript code that uses the <b>GoJS</b> library.
140 </p>
141 <ul>
142 <li>You will need to be familiar with HTML DOM and CSS.</li>
143 <li>You will need to test your app on many different devices using many different browsers.</li>
144 <li>You will need to be familiar with your JavaScript framework (if any).</li>
145 <li>You will need to know how to use each browser's development facilities, especially the console window and debugger.</li>
146 </ul>
147
148 <h3 id="UseGoDebugJSLibrary">Use the <code>go-debug.js</code> library</h3>
149 <p>
150 While developing your app make sure you use the debug library, <code>go-debug.js</code>, rather than the <code>go.js</code> library.
151 The debug library does more error checking of property values and method arguments, and it detects more unusual situations.
152 Most warning and errors will be written to the console window. Always check it for messages. We have tried to make them informative.
153 </p>
154
155 <h3 id="UseDocumentedAPI">Use the documented API</h3>
156 <p>
157 Try to limit your code to only use documented classes, properties, and methods, as listed in the
158 <a href="../api/index.html" target="api">API</a> reference or in the TypeScript definition file,
159 <a href="../release/go.d.ts" target="_blank">go.d.ts</a>.
160 </p>
161 <p>
162 Please do not refer to some minified property name, which will only be one or two letters long.
163 In another version of the library the minified names will be different, so such code would no longer work.
164 Basically: never use one or two letter property names
165 except for "x" and "y" on <a>Point</a>, <a>Rect</a>, <a>Spot</a>, and <a>LayoutVertex</a> instances
166 and the <a>InputEvent.up</a> property.
167 </p>
168 <p>
169 Do not modify the prototypes of any of the <b>GoJS</b> classes.
170 If you modify the built-in classes, we cannot support you.
171 The way to modify the behavior of the <b>GoJS</b> classes is via the techniques discussed at
172 <a href="extensions.html">Extensions</a>.
173 However most of the <b>GoJS</b> classes cannot be subclassed and most of the documented methods cannot be overridden.
174 Generally the <a>Tool</a> and <a>Layout</a> classes and the <a>CommandHandler</a> and <a>Link</a> classes may be subclassed;
175 look at the API documentation to see if a method may be overridden.
176 </p>
177
178 <h2 id="UsingConsoleWindow">Using the Console window</h2>
179 <p>
180 First you will need to get a reference to your <a>Diagram</a> object in the Console window or the Debugger window.
181 </p>
182 <p>
183 One way to do that is by remembering it in your code.
184 You can set a property on the <code>window</code> object to refer to the Diagram that you create.
185 Many of the samples do this just by leaving out the <code>var</code> declaration:
186 <pre class="lang-js"><code>myDiagram = $(go.Diagram, "myDiagramDiv", . . .);</code></pre>
187 </p>
188 <p>
189 Alternatively, in the console, if you know the name of the HTML DIV element,
190 you can call the static function <a>Diagram,fromDiv</a> to get the <a>Diagram</a> object:
191 <pre class="lang-js"><code> myDiagram = go.Diagram.fromDiv("myDiagramDiv");</code></pre>
192 If that DIV element is not named, perhaps you have some other way of getting a reference to the DIV element.
193 That may depend on the framework that you are using.
194 You can still call <a>Diagram,fromDiv</a> on that element to get the corresponding Diagram object.
195 </p>
196 <p>
197 Then in the console you can use the <code>myDiagram</code> reference to the <a>Diagram</a> object. Some examples:
198 </p>
199 <p>
200 <pre class="lang-js"><code>myDiagram.nodes.size</code></pre>
201 returns the number of <a>Node</a>s in the Diagram.
202 </p>
203 <p>
204 <pre class="lang-js"><code>myDiagram.model.nodeDataArray[0]</code></pre>
205 returns the first node data object in the diagram's model's <a>Model.nodeDataArray</a>.
206 </p>
207 <p>
208 <pre class="lang-js"><code>myDiagram.layoutDiagram(true)</code></pre>
209 forces all layouts to happen, rearranging the nodes and routing the links.
210 </p>
211 <p>
212 The code that you execute in the console can be more complicated too.
213 For example, you can find, select, and scroll to a particular node:
214 <pre class="lang-js">><code> myNode = myDiagram.findNodeForKey("Omega");
215> myNode.isSelected = true
216> myDiagram.commandHandler.scrollToPart(myNode)</code></pre>
217 If you don't know the key for the node that you want to see in the viewport,
218 perhaps you know how to find the node data object in the model.
219 The <a>Diagram.findNodesByExample</a> method might also be useful.
220 </p>
221
222 <h3 id="ExaminingSelectedNode">Examining a selected Node</h3>
223 <p>
224 <pre class="lang-js"><code>myDiagram.selection.first()</code></pre>
225 returns the first selected <a>Part</a>, which might be either a <a>Node</a>, a <a>Link</a>,
226 or null if nothing is selected.
227 </p>
228 <p>
229 If you remember the selected Node or Link, you can then examine it further more easily. For example:
230 <pre class="lang-js">><code> myNode = myDiagram.selection.first()
231> myNode.data.key</code></pre>
232 remembers the first selected Node and returns the key of the node data.
233 You might want to look at all of the properties of the <pre class="lang-js"><code>myNode.data</code></pre> object.
234 </p>
235 <p>
236 You could also look at other properties of the Node and call its methods. For example:
237 <pre class="lang-js"><code>myNode.location</code></pre>
238 returns a <a>Point</a> whose properties the debugger may show. Or call:
239 <pre class="lang-js"><code>myNode.location.toString()</code></pre>
240 to see a human-readable textual rendering of that Point object.
241 </p>
242 <p>
243 As another example, you can print out all of the nodes the selected node is connected to:
244 <pre class="lang-js"><code>myNode.findNodesOutOf().each(function(n) { console.log(n.data.key); })</code></pre>
245 You can find more examples of iterating at <a href="collections.html#MoreIterationExamples">Collections</a>
246 </p>
247 <p>
248 You can also look at the structure of the visual tree of a node. With this recursive function:
249 <pre class="lang-js"><code> function walk(x, level, index) {
250 console.log(level + "," + index + ": " + x.toString());
251 if (!(x instanceof go.Panel)) return;
252 for (var i = 0; i < x.elements.size; i++) walk(x.elt(i), level+1, i);
253 }</code></pre>
254 you could call
255 <pre class="lang-js"><code> walk(myNode, 0, 0)</code></pre>
256 and in the Org Chart sample get results such as:
257 <pre class="lang-js"><code>
2580,0: Node#653(Kensaku Tamaki)
2591,0: Shape(Rectangle)#656
2601,1: Panel(Panel.Table)#657
2612,0: TextBlock("Kensaku Tamaki")
2622,1: Picture(https://www.nwoods.com/go/Flags/japan-flag.Png)#664
2632,2: TextBlock("Title: Vice Chairman"...)</code></pre>
264 So you can see how the Node is a panel composed of Shape surrounding a nested Table Panel,
265 which in turn is composed of two TextBlocks and a Picture.
266 </p>
267
268 <h2 id="DebuggingNodePanelDesigns">Debugging Node Panel designs</h2>
269 <p>
270 When building your own node template, there may be times when the objects in the node are not sized and positioned the way that you would like.
271 It is important that you understand how objects may be assembled within panels. You will want to re-read:
272 </p>
273 <ul>
274 <li><a href="https://gojs.net/latest/intro/buildingObjects.html">Building with GraphObjects</a></li>
275 <li><a href="https://gojs.net/latest/intro/textBlocks.html">TextBlocks</a></li>
276 <li><a href="https://gojs.net/latest/intro/shapes.html">Shapes</a></li>
277 <li><a href="https://gojs.net/latest/intro/pictures.html">Pictures</a></li>
278 <li><a href="https://gojs.net/latest/intro/panels.html">Panels</a></li>
279 <li><a href="https://gojs.net/latest/intro/tablePanels.html">Table Panels</a></li>
280 <li><a href="https://gojs.net/latest/intro/sizing.html">Sizing of GraphObjects</a></li>
281 </ul>
282
283 <p>
284 Say that you want a node consisting of two TextBlocks, one above the other. You might start off with:
285 </p>
286 <pre class="lang-js" id="first"><code>
287diagram.nodeTemplate =
288 $(go.Node, "Auto",
289 $(go.Shape, { fill: "white" }),
290 $(go.Panel, "Vertical",
291 { margin: 3 },
292 $(go.TextBlock,
293 new go.Binding("text", "t1")),
294 $(go.TextBlock,
295 new go.Binding("text", "t2"))
296 )
297 );
298diagram.model.nodeDataArray = [{ t1: "Top", t2: "Bottom"}];
299 </code></pre>
300 <script>goCode("first", 500, 140)</script>
301
302 <p>
303 But wait -- you want the node to be a fixed size. So you set the node's width and height:
304 </p>
305 <pre class="lang-js" id="second"><code>
306diagram.nodeTemplate =
307 $(go.Node, "Auto",
308 { width: 80, height: 100 },
309 $(go.Shape, { fill: "white" }),
310 $(go.Panel, "Vertical",
311 { margin: 3 },
312 $(go.TextBlock,
313 new go.Binding("text", "t1")),
314 $(go.TextBlock,
315 new go.Binding("text", "t2"))
316 )
317 );
318diagram.model.nodeDataArray = [{ t1: "Top", t2: "Bottom"}];
319 </code></pre>
320 <script>goCode("second", 500, 140)</script>
321
322 <p>
323 That looks better, but you are suprised that both TextBlocks are near the center. Why is that?
324 For debugging purposes let's change the <a>GraphObject.background</a> colors of each TextBlock and the nested Panel.
325 </p>
326 <pre class="lang-js" id="third"><code>
327diagram.nodeTemplate =
328 $(go.Node, "Auto",
329 { width: 80, height: 100 },
330 $(go.Shape, { fill: "white" }),
331 $(go.Panel, "Vertical", { background: "red" },
332 { margin: 3 },
333 $(go.TextBlock, { background: "lime" },
334 new go.Binding("text", "t1")),
335 $(go.TextBlock, { background: "cyan" },
336 new go.Binding("text", "t2"))
337 )
338 );
339diagram.model.nodeDataArray = [{ t1: "Top", t2: "Bottom"}];
340 </code></pre>
341 <script>goCode("third", 500, 140)</script>
342 <p>
343 It is now clear that the TextBlocks are no bigger than they need to be to hold the text,
344 and that the Panel is also no bigger than need be to hold the two TextBlocks.
345 </p>
346
347 <p>
348 So you think that you just need to <a>GraphObject.stretch</a> the panel.
349 </p>
350 <pre class="lang-js" id="fourth"><code>
351diagram.nodeTemplate =
352 $(go.Node, "Auto",
353 { width: 80, height: 100 },
354 $(go.Shape, { fill: "white" }),
355 $(go.Panel, "Vertical", { background: "red" },
356 { margin: 3, stretch: go.GraphObject.Fill },
357 $(go.TextBlock, { background: "lime" },
358 new go.Binding("text", "t1")),
359 $(go.TextBlock, { background: "cyan" },
360 new go.Binding("text", "t2"))
361 )
362 );
363diagram.model.nodeDataArray = [{ t1: "Top", t2: "Bottom"}];
364 </code></pre>
365 <script>goCode("fourth", 500, 140)</script>
366 <p>
367 Now the Panel with the red background indeed fills up the whole outer Auto Panel,
368 inside its main Shape acting as a border.
369 But the lime green and cyan blue TextBlocks are still only their natural heights.
370 </p>
371
372 <p>
373 If you want the text to be spaced evenly vertically,
374 you might think you only need to stretch those two TextBlocks.
375 </p>
376 <pre class="lang-js" id="fifth"><code>
377diagram.nodeTemplate =
378 $(go.Node, "Auto",
379 { width: 80, height: 100 },
380 $(go.Shape, { fill: "white" }),
381 $(go.Panel, "Vertical", { background: "red" },
382 { margin: 3, stretch: go.GraphObject.Fill },
383 $(go.TextBlock, { background: "lime" },
384 { stretch: go.GraphObject.Fill },
385 new go.Binding("text", "t1")),
386 $(go.TextBlock, { background: "cyan" },
387 { stretch: go.GraphObject.Fill },
388 new go.Binding("text", "t2"))
389 )
390 );
391diagram.model.nodeDataArray = [{ t1: "Top", t2: "Bottom"}];
392 </code></pre>
393 <script>goCode("fifth", 500, 140)</script>
394 <p>
395 Now the TextBlocks are stretching horizontally but not vertically!
396 The reason is that a Vertical Panel never stretches its elements vertically.
397 It always stacks its elements on top of each other with their natural heights.
398 When a Vertical Panel is taller than the stack of its elements, there is extra space at the bottom.
399 </p>
400
401 <p>
402 Instead of a Vertical Panel we should use a Table Panel.
403 This requires assigning the <a>GraphObject.row</a> on each element (i.e. each TextBlock).
404 </p>
405 <pre class="lang-js" id="sixth"><code>
406diagram.nodeTemplate =
407 $(go.Node, "Auto",
408 { width: 80, height: 100 },
409 $(go.Shape, { fill: "white" }),
410 $(go.Panel, "Table", { background: "red" },
411 { margin: 3, stretch: go.GraphObject.Fill },
412 $(go.TextBlock, { background: "lime" },
413 { row: 0 },
414 new go.Binding("text", "t1")),
415 $(go.TextBlock, { background: "cyan" },
416 { row: 1 },
417 new go.Binding("text", "t2"))
418 )
419 );
420diagram.model.nodeDataArray = [{ t1: "Top", t2: "Bottom"}];
421 </code></pre>
422 <script>goCode("sixth", 500, 140)</script>
423 <p>
424 Because by default elements are centered within the cells of a Table Panel, no stretching of the TextBlocks is needed.
425 (You could change that by setting <a>Panel.defaultAlignment</a> or <a>Panel.defaultStretch</a>.)
426 </p>
427
428 <p>
429 Are we all done? Maybe. What happens when the text changes size?
430 One way to test that is to create a bunch of nodes using different model data, using short and long strings.
431 </p>
432 <p>
433 But to demonstrate one more debugging technique, we'll make the Node <a>Part.resizable</a>.
434 You can interactively resize the node (the whole node because we haven't set <a>Part.resizeObjectName</a>)
435 so you can see how the nested Panel and the TextBlocks handle constrained sizing.
436 </p>
437 <pre class="lang-js" id="seventh"><code>
438diagram.nodeTemplate =
439 $(go.Node, "Auto", { resizable: true },
440 { width: 80, height: 100 },
441 $(go.Shape, { fill: "white" }),
442 $(go.Panel, "Table", { background: "red" },
443 { margin: 3, stretch: go.GraphObject.Fill },
444 $(go.TextBlock, { background: "lime" },
445 { row: 0 },
446 new go.Binding("text", "t1")),
447 $(go.TextBlock, { background: "cyan" },
448 { row: 1 },
449 new go.Binding("text", "t2"))
450 )
451 );
452diagram.model.nodeDataArray = [{ t1: "Top String", t2: "Bottom String"}];
453diagram.findNodeForData(diagram.model.nodeDataArray[0]).isSelected = true;
454 </code></pre>
455 <script>goCode("seventh", 500, 140)</script>
456 <p>
457 Note how when the node becomes narrow, it clips the text rather than make the text wrap.
458 Let's say that you would rather that the text wrap.
459 </p>
460
461 <p>
462 This can be implemented by stretching the TextBlocks horizontally, which will define their widths, forcing the text to wrap.
463 But text normally is drawn at the left side of the bounds of the TextBlock when the text direction is left-to-right.
464 If you want each TextBlock to be centered within its bounds, you'll need to set <a>TextBlock.textAlign</a> to "center".
465 </p>
466 <pre class="lang-js" id="eighth"><code>
467diagram.nodeTemplate =
468 $(go.Node, "Auto", { resizable: true },
469 { width: 80, height: 100 },
470 $(go.Shape, { fill: "white" }),
471 $(go.Panel, "Table", { background: "red" },
472 { margin: 3, stretch: go.GraphObject.Fill,
473 defaultStretch: go.GraphObject.Horizontal },
474 $(go.TextBlock, { background: "lime" },
475 { row: 0, textAlign: "center" },
476 new go.Binding("text", "t1")),
477 $(go.TextBlock, { background: "cyan" },
478 { row: 1, textAlign: "center" },
479 new go.Binding("text", "t2"))
480 )
481 );
482diagram.model.nodeDataArray = [{ t1: "Top String", t2: "Bottom String"}];
483diagram.findNodeForData(diagram.model.nodeDataArray[0]).isSelected = true;
484 </code></pre>
485 <script>goCode("eighth", 500, 140)</script>
486 <p>
487 The TextBlocks can be seen to stretch across the width of the available area.
488 Note how the text wraps as the node becomes narrow, causing the TextBlocks to become more narrow.
489 Of course when there's not enough room to render all of the text, the TextBlocks will be clipped.
490 </p>
491
492 <p>
493 Now we just need to get rid of the colored backgrounds and resizable-ness used for debugging
494 and assign the desired colors and fonts.
495 </p>
496 <pre class="lang-js" id="ninth"><code>
497diagram.nodeTemplate =
498 $(go.Node, "Auto",
499 { width: 80, height: 100 },
500 $(go.Shape, { fill: "white" }),
501 $(go.Panel, "Table",
502 { margin: 3, stretch: go.GraphObject.Fill,
503 defaultStretch: go.GraphObject.Horizontal, background: "purple" },
504 $(go.TextBlock,
505 { row: 0, textAlign: "center", stroke: "white", font: "bold 11pt sans-serif" },
506 new go.Binding("text", "t1")),
507 $(go.TextBlock,
508 { row: 1, textAlign: "center", stroke: "white", font: "bold 11pt sans-serif" },
509 new go.Binding("text", "t2"))
510 )
511 );
512diagram.model.nodeDataArray = [{ t1: "Top String", t2: "Bottom String"}];
513 </code></pre>
514 <script>goCode("ninth", 500, 140)</script>
515
516 </div>
517 </div>
518
519 <div class="bg-nwoods-primary">
520 <section class="max-w-screen-lg text-white container mx-auto py-2 px-12">
521 <p id="version" class="leading-none mb-2 my-4">GoJS</p>
522 </section>
523 </div><footer class="bg-nwoods-primary text-white">
524 <div class="container max-w-screen-lg mx-auto px-8">
525 <div class="w-full py-6">
526
527 <div class="max-w-screen-lg xl:max-w-screen-xl mx-auto px-4 sm:px-6 md:px-8">
528 <ul class="text-sm font-medium pb-14 sm:pb-20 grid grid-cols-1 sm:grid-cols-3 gap-y-10">
529 <li class="list-none row-span-2">
530 <h2 class="text-base font-semibold tracking-wide">GoJS</h2>
531 <ul class="list-none space-y-4 md:space-y-1 px-0">
532 <li>
533 <a href="../samples/index.html">Samples</a>
534 </li>
535 <li>
536 <a href="../learn/index.html">Learn</a>
537 </li>
538 <li>
539 <a href="../intro/index.html">Intro</a>
540 </li>
541 <li>
542 <a href="../api/index.html">API</a>
543 </li>
544 <li>
545 <a href="../changelog.html">Changelog</a>
546 </li>
547 <li>
548 <a href="https://github.com/NorthwoodsSoftware/GoJS">GitHub</a>
549 </li>
550 </ul>
551 </li>
552 <li class="list-none row-span-2">
553 <h2 class="text-base font-semibold tracking-wide">Support</h2>
554 <ul class="list-none space-y-4 md:space-y-1 px-0">
555 <li>
556 <a href="https://www.nwoods.com/contact.html"
557 target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/contact.html', 'contact');">Contact</a>
558 </li>
559 <li>
560 <a href="https://forum.nwoods.com/c/gojs">Forum</a>
561 </li>
562 <li>
563 <a href="https://www.nwoods.com/app/activate.aspx?sku=gojs">Activate</a>
564 </li>
565 <li>
566 <a href="https://www.nwoods.com/sales/index.html"
567 target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/sales/index.html', 'buy');">Buy</a>
568 </li>
569 <li>
570 <a href="https://www.youtube.com/channel/UC9We8EoX596-6XFjJDtZIDg">Videos</a>
571 </li>
572 </ul>
573 </li>
574 <li class="list-none row-span-2">
575 <h2 class="text-base font-semibold tracking-wide">Company</h2>
576 <ul class="list-none space-y-4 md:space-y-1 px-0">
577 <li>
578 <a href="https://www.nwoods.com">Northwoods</a>
579 </li>
580 <li>
581 <a href="https://www.nwoods.com/about.html">About Us</a>
582 </li>
583 <li>
584 <a href="https://www.nwoods.com/contact.html">Contact Us</a>
585 </li>
586 <li>
587 <a href="https://twitter.com/northwoodsgo">Twitter</a>
588 </li>
589
590 </ul>
591 </li>
592 </ul>
593
594
595 <p class="text-sm text-gray-100 md:mb-6">
596 Copyright 1998-2021 <a class="text-white" href="https://www.nwoods.com">Northwoods Software</a>
597 </p>
598 </div>
599 </div>
600</footer> </body>
601
602<script async src="https://www.googletagmanager.com/gtag/js?id=UA-1506307-5"></script>
603<script>
604 window.dataLayer = window.dataLayer || [];
605 function gtag(){dataLayer.push(arguments);}
606 gtag('js', new Date()); gtag('config', 'UA-1506307-5');
607 var getOutboundLink = function(url, label) {
608 gtag('event', 'click', {
609 'event_category': 'outbound',
610 'event_label': label,
611 'transport_type': 'beacon'
612 });
613 }
614
615 // topnav
616 var topButton = document.getElementById("topnavButton");
617 var topnavList = document.getElementById("topnavList");
618 topButton.addEventListener("click", function() {
619 this.classList.toggle("active");
620 topnavList.classList.toggle("hidden");
621 document.getElementById("topnavOpen").classList.toggle("hidden");
622 document.getElementById("topnavClosed").classList.toggle("hidden");
623 });
624</script>
625 <script src="../assets/js/prism.js"></script>
626 <script src="../release/go.js"></script>
627 <script src="../assets/js/goDoc.js"></script>
628 <script>
629 document.addEventListener("DOMContentLoaded", function() {
630 if (window.go) document.getElementById('version').textContent = "GoJS version " + go.version;
631 if (window.goDoc) window.goDoc();
632 var d = window.diagrams;
633 for (var i = 0; i < d.length; i++) {
634 var dargs = d[i];
635 goCodeExecute(dargs[0], dargs[1], dargs[2], dargs[3], dargs[4]);
636 }
637 if (window.extra) window.extra();
638 });
639 </script>
640</html>