-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgraphobject.html
442 lines (377 loc) · 15.9 KB
/
graphobject.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="Tutorial for GraphObject manipulation with GoJS." />
<title>GraphObject Manipulation</title>
<!-- Copyright 1998-2016 by Northwoods Software Corporation. -->
<link href="../assets/css/bootstrap.min.css" rel="stylesheet" >
<!-- custom CSS after bootstrap -->
<link href="../assets/css/main.css" rel="stylesheet" type="text/css"/>
<link href="../assets/css/highlight.css" rel="stylesheet" type="text/css" media="all" />
<script src="../assets/js/highlight.js"></script>
<script src="go.js"></script>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-1506307-5', 'auto');
ga('send', 'pageview');
</script>
</head>
<body>
<!-- non-fixed navbar -->
<nav id="api-nav" class="navbar navbar-inverse navbar-top">
<div class="container">
<div class="navbar-header" data-toggle="collapse" data-target="#navbar">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<!--<a class="navbar-brand" href="#">GoJS</a>-->
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li class="active"><a href="../index.html">Home</a></li>
<li><a href="../learn/index.html">Learn</a></li>
<li><a href="../samples/index.html">Samples</a></li>
<li><a href="../intro/index.html">Intro</a></li>
<li><a href="../api/index.html">API</a></li>
<li><a href="https://www.nwoods.com/components/evalform.htm">Register</a></li>
<li><a href="../doc/download.html">Download</a></li>
<li><a href="https://forum.nwoods.com/c/gojs">Forum</a></li>
<li><a href="https://www.nwoods.com/support/query.htm">Contact</a></li>
<li class="buy"><a href="https://www.nwoods.com/sales/ordering.htm">Buy</a></li>
<li class="activate"><a href="https://www.nwoods.com/app/activate.aspx?sku=gojs">Activate</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>
</nav>
<div id="bannertop" class="jumbotron banner">
<div class="container">
<h1><span>GraphObject Manipulation</span></h1>
</div>
</div>
<div class="container-fluid learn-container">
<h2>Programmatically interacting with Nodes</h2>
<p>
This guide will show you some basic ways of programmatically interacting with <b>GoJS</b> nodes and model data.
Throughout this guide, we will use the following diagram setup as our starting point:
</p>
<pre><code>
var $ = go.GraphObject.make;
myDiagram = $(go.Diagram, "myDiagramDiv",
{
initialContentAlignment: go.Spot.Center,
"undoManager.isEnabled": true
});
// define a simple Node template
myDiagram.nodeTemplate =
$(go.Node, "Auto",
$(go.Shape, "Rectangle",
new go.Binding("fill", "color")),
$(go.TextBlock,
{ margin: 6, font: "18px sans-serif" },
new go.Binding("text", "key"))
);
myDiagram.model = new go.GraphLinksModel(
[
{ key: "Alpha", color: "lightblue" },
{ key: "Beta", color: "orange" },
{ key: "Gamma", color: "lightgreen" },
{ key: "Delta", color: "pink" }
]);
</code></pre>
<p>
The code produces this Diagram:
</p>
<!-- LIVE -->
<div id="myDiagramDiv" class="diagramStyling" style="width:700px; height:150px"></div>
<script>
function setupDiagram(divname) {
var $ = go.GraphObject.make;
var myDiagram = $(go.Diagram, divname,
{
initialContentAlignment: go.Spot.Center,
"undoManager.isEnabled": true
});
// define a simple Node template
myDiagram.nodeTemplate =
$(go.Node, "Auto",
$(go.Shape, "Rectangle",
{ stroke: null, name: "SHAPE" },
new go.Binding("fill", "color")),
$(go.TextBlock,
{ margin: 6, font: "18px sans-serif" },
new go.Binding("text", "key"))
);
myDiagram.model = new go.GraphLinksModel(
[
{ key: "Alpha", color: "lightblue" },
{ key: "Beta", color: "orange" },
{ key: "Gamma", color: "lightgreen" },
{ key: "Delta", color: "pink" }
]);
return myDiagram;
}
setupDiagram("myDiagramDiv")
</script>
<h2>Finding single nodes: Diagram.findNodeForKey</h2>
<p>
You can use <code>Diagram.findNodeForKey(key)</code> to get a reference to a Node in JavaScript.
Key values in <b>GoJS</b> can be either strings or numbers.
You can then use the Node reference to manipulate and inspect the Node.
</p>
<pre><code>
var node = myDiagram.findNodeForKey("Alpha");
// Selects the node:
myDiagram.select(node);
// Outputs a JavaScript object in the developer console
// display of output will differ per browser, but is essentially the object:
// { key: "Alpha", color: "lightblue" }
// plus some internal implementation details.
console.log(node.data);
</code></pre>
<!-- LIVE -->
<div id="myDiagramDiv2" class="diagramStyling" style="width:700px; height:150px"></div>
<script>
var myDiagram = setupDiagram("myDiagramDiv2");
var node = myDiagram.findNodeForKey("Alpha");
myDiagram.select(node);
if (window.console) console.log(node.data);
</script>
<p>
However <code>findNodeForKey</code> may return <code>null</code> if no node data uses that key value.
Also, it only looks at the model data to find a node data that uses the given key value,
from which it finds the corresponding Node in the Diagram.
It does not look at the text values of any TextBlocks that are within the Nodes,
so it can work even if no text is shown at all.
</p>
<p>
Note that there is no <code>Node.key</code> property.
But you can get the key for a Node via <code>someNode.data.key</code>.
</p>
<h2>Collections of Nodes and Links</h2>
<p>
Diagrams have several properties and methods that return iterators describing collections of Parts.
(Nodes and Links are kinds of Parts.)
<code>Diagram.nodes</code> and <code>Diagram.links</code> return iterators of all Nodes and Links in the Diagram, respectively.
<code>Diagram.selection</code> returns an iterator of selected Parts
(both selected Nodes and selected Links).
</p>
<p>
There are also more specific methods for common operations, such as <code>Diagram.findTreeRoots()</code>
which returns an iterator of all top-level Nodes that have no parent nodes.
</p>
<p>
This next example uses <code>Diagram.nodes</code> and shows how to iterate over the collection.
</p>
<pre><code>
// wrapping code in startTransaction/commitTransaction automatically updates the display
// and allows the effects to be undone
myDiagram.startTransaction("decrease scale");
// get an iterator for all nodes
var itr = myDiagram.nodes;
while (itr.next()) {
var node = itr.value;
if (node.data.key === "Beta") continue; //skip Beta, just to contrast
node.scale = 0.4; // shrink each node
}
myDiagram.commitTransaction("decrease scale");
</code></pre>
<p>As a result we have very scaled-down nodes, except for Beta:</p>
<!-- LIVE -->
<div id="myDiagramDiv3" class="diagramStyling" style="width:700px; height:150px"></div>
<script>
var myDiagram = setupDiagram("myDiagramDiv3");
// wrapping code in startTransaction/commitTransaction automatically updates the display
// and allows the effects to be undone
myDiagram.startTransaction("decrease scale");
// get an iterator of all nodes
var itr = myDiagram.nodes;
while (itr.next()) {
var node = itr.value;
if (node.data.key === "Beta") continue; // skip Beta, just to contrast
node.scale = 0.4; // shrink each node
}
myDiagram.commitTransaction("decrease scale");
</script>
<h2>Named GraphObjects and Panel.findObject</h2>
<p>
Often we want to manipulate a property that belongs to one of the Node's elements,
perhaps an element arbitrarily deep in the template.
In our example Diagram, each Node has one Shape,
and if we want to change the color of this Shape directly we would need a reference to it.
To make it possible to find, we can give that Shape a name:
</p>
<pre><code>
myDiagram.nodeTemplate =
$(go.Node, "Auto",
$(go.Shape, "Rectangle",
{ stroke: null, name: "SHAPE" }, // added the name property
new go.Binding("fill", "color")),
$(go.TextBlock,
{ margin: 6, font: "18px sans-serif" },
new go.Binding("text", "key"))
);
</code></pre>
<p>
Names allow us to easily find GraphObjects inside of Panels
(all Nodes are also Panels) using <code>Panel.findObject</code>,
which will search the visual tree of a Panel starting at that panel.
So when we have a reference to a Node, we can call <code>someNode.findObject("SomeName")</code>
to search through the node for the named object.
It will return a reference to the named GraphObject if it is found, or <code>null</code> otherwise.
</p>
<p>
Using this, we could make an HTML button that changes the fill of the Shape inside of a selected Node:
</p>
<pre><code>
var selectionButton = document.getElementById("selectionButton");
selectionButton.addEventListener("click", function() {
myDiagram.startTransaction("change color");
var it = myDiagram.selection.iterator;
while (it.next()) {
var node = it.value;
var shape = node.findObject("SHAPE");
// If there was a GraphObject in the node named SHAPE, then set its fill to red:
if (shape !== null) {
shape.fill = "red";
}
}
myDiagram.commitTransaction("change color");
});
</code></pre>
<!-- LIVE -->
<div id="myDiagramDiv4" class="diagramStyling" style="width:700px; height:150px"></div>
<button id="selectionButton">Change Shape.fill inside selected Nodes</button>
<script>
var myDiagram = setupDiagram("myDiagramDiv4");
var selectionButton = document.getElementById("selectionButton");
selectionButton.addEventListener("click", function() {
myDiagram.startTransaction("change color");
var it = myDiagram.selection.iterator;
while (it.next()) {
var node = it.value;
var shape = node.findObject("SHAPE");
// If there was a GraphObject in the node named SHAPE, then set its fill to red:
if (shape !== null) {
shape.fill = "red";
}
}
myDiagram.commitTransaction("change color");
});
</script>
<h2>Changing Properties and Updating the Model using Data Bindings</h2>
<p>
Looking again at our Node template, we have the <code>Shape.fill</code>
property data-bound to the "color" property of our Node data:
</p>
<pre><code>
myDiagram.nodeTemplate =
$(go.Node, "Auto",
$(go.Shape, "Rectangle",
{ stroke: null, name: "SHAPE" },
new go.Binding("fill", "color")), // note this data binding
$(go.TextBlock,
{ margin: 6, font: "18px sans-serif" },
new go.Binding("text", "key"))
);
</code></pre>
<p>
Changing the Shape's <code>fill</code> property inside our node will not,
as the Node template currently stands, update the model data.
</p>
<pre><code>
var node = myDiagram.findNodeForKey("Alpha");
var shape = node.findObject("SHAPE");
shape.fill = "red";
// outputs "lightblue" - the model has not changed!
console.log(node.data.color);
</code></pre>
<p>
This is undesirable in some cases.
When we want the change to persist while saving and loading,
we will want the model data updated too.
</p>
<p>
In other situations this might be a good thing.
For instance if we want the color change for only cosmetic purposes,
such as changing the color of a button when hovering over it with the mouse,
we would not bother modifying the model data.
</p>
<p>
Suppose that we do want to update the model.
The preferred way to do this is to modify the data in the model
and depend on the data binding to automatically update the Shape.
However, we cannot modify the data directly by just setting the JavaScript property.
</p>
<pre style="border: 6px solid red"><code>
var node = myDiagram.findNodeForKey("Alpha");
// DO NOT DO THIS!
// This would update the data, but GoJS would not be notified
// that this arbitrary JavaScript object has been modified,
// and the associated Node will not be updated appropriately
node.data.color = "red";
</code></pre>
<p>
Instead we should set the data property using the method
<code>Model.setDataProperty(data, propertyName, propertyValue)</code>.
</p>
<pre style="border: 6px solid lime"><code>
var node = myDiagram.findNodeForKey("Alpha");
var model = myDiagram.model;
// all model changes should happen in a transaction
model.startTransaction("change color");
// This is the safe way to change model data
// GoJS will be notified that the data has changed
// and can update the node in the Diagram
// and record the change in the UndoManager
model.setDataProperty(node.data, "color", "red");
model.commitTransaction("change color");
// outputs "red" - the model has changed!
console.log(node.data.color);
</code></pre>
<pre><code>
myDiagram.nodeTemplate =
$(go.Node, "Auto",
$(go.Shape, "Rectangle",
{ stroke: null }, // removed the name property
new go.Binding("fill", "color")),
$(go.TextBlock,
{ margin: 6, font: "18px sans-serif" },
new go.Binding("text", "key"))
);
</code></pre>
<p>
Note that there is no longer any need to name the Shape "SHAPE",
because there is no longer any need to call <code>findObject</code> to look for the particular Shape.
Data binding will automatically update properties, so we do not have to do that ourselves.
</p>
<h2>Subjects Mentioned and Further Reading</h2>
<ul>
<li>Data Binding — See the <a href="../intro/dataBinding.html">intro page on Data Binding for lots more detail</a>.</li>
<li>Transactions — See the <a href="../intro/transactions.html">intro page on Transactions</a>.</li>
<li><code>console.log</code> — A powerful debugging aid that is part of most browser's developer tools.
See the <a href="https://developers.google.com/chrome-developer-tools/docs/console">Chrome guide</a> or
the <a href="https://developer.mozilla.org/en-US/docs/Tools/Browser_Console">Firefox guide</a> for their respective developer consoles.</li>
</ul>
<p>
If you are ready for a comprehensive overview of <b>GoJS</b>, have a look at the <a href="../intro/index.html">technical introduction</a>.
If you want to explore by example, have a look at <a href="../samples/index.html">the samples</a> to get a feel for what's possible with <b>GoJS</b>.
</p>
<p class="footer">
GoJS ® by Northwoods Software. Copyright © 1998-2016 <a href="https://www.nwoods.com" target="_blank">Northwoods Software</a> ®
</p>
</div> <!-- end main -->
<div class="banner" id="bannerbottom">
<!-- text in banner-->
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script async src="../assets/js/bootstrap.min.js"></script>
</body>
</html>