create-gojs-kit
Version:
A CLI for downloading GoJS samples, extensions, and docs
715 lines (656 loc) • 28.6 kB
HTML
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, viewport-fit=cover"/>
<meta name="description" content="Show the relationships of nodes and links and groups." />
<meta itemprop="description" content="Show the relationships of nodes and links and groups." />
<meta property="og:description" content="Show the relationships of nodes and links and groups." />
<meta name="twitter:description" content="Show the relationships of nodes and links and groups." />
<link rel="preconnect" href="https://rsms.me/">
<link rel="stylesheet" href="../assets/css/style.css">
<!-- Copyright 1998-2025 by Northwoods Software Corporation. -->
<meta itemprop="name" content="Programmatic Navigation Through Related Nodes/Links/Groups" />
<meta property="og:title" content="Programmatic Navigation Through Related Nodes/Links/Groups" />
<meta name="twitter:title" content="Programmatic Navigation Through Related Nodes/Links/Groups" />
<meta property="og:image" content="https://gojs.net/latest/assets/images/screenshots/navigation.png" />
<meta itemprop="image" content="https://gojs.net/latest/assets/images/screenshots/navigation.png" />
<meta name="twitter:image" content="https://gojs.net/latest/assets/images/screenshots/navigation.png" />
<meta property="og:url" content="https://gojs.net/latest/samples/navigation.html" />
<meta property="twitter:url" content="https://gojs.net/latest/samples/navigation.html" />
<meta name="twitter:card" content="summary_large_image" />
<meta property="og:type" content="website" />
<meta property="twitter:domain" content="gojs.net" />
<title>
Programmatic Navigation Through Related Nodes/Links/Groups | GoJS Diagramming Library
</title>
</head>
<body>
<!-- This top nav is not part of the sample code -->
<nav id="navTop" class=" w-full h-[var(--topnav-h)] z-30 bg-white border-b border-b-gray-200">
<div class="max-w-screen-xl mx-auto flex flex-wrap items-start justify-between px-4">
<a class="text-white bg-nwoods-primary font-bold !leading-[calc(var(--topnav-h)_-_1px)] my-0 px-2 text-4xl lg:text-5xl logo"
href="../">
GoJS
</a>
<div class="relative">
<button id="topnavButton" class="h-[calc(var(--topnav-h)_-_1px)] px-2 m-0 text-gray-900 bg-inherit shadow-none md:hidden hover:!bg-inherit hover:!text-nwoods-accent hover:!shadow-none" aria-label="Navigation">
<svg class="h-7 w-7 block" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
<path d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</button>
<div id="topnavList" class="hidden md:block">
<div class="absolute right-0 z-30 flex flex-col items-end rounded border border-gray-200 p-4 pl-12 shadow bg-white text-gray-900 font-semibold
md:flex-row md:space-x-4 md:items-start md:border-0 md:p-0 md:shadow-none md:bg-inherit">
<a href="../learn/">Learn</a>
<a href="../samples/">Samples</a>
<a href="../intro/">Intro</a>
<a href="../api/">API</a>
<a href="../download.html">Download</a>
<a href="https://forum.nwoods.com/c/gojs/11" target="_blank" rel="noopener">Forum</a>
<a id="tc" href="https://nwoods.com/contact.html"
target="_blank" rel="noopener" onclick="getOutboundLink('https://nwoods.com/contact.html', 'contact');">Contact</a>
<a id="tb" href="https://nwoods.com/sales/index.html"
target="_blank" rel="noopener" onclick="getOutboundLink('https://nwoods.com/sales/index.html', 'buy');">Buy</a>
</div>
</div>
</div>
</div>
</nav>
<script>
window.addEventListener("DOMContentLoaded", function () {
// topnav
var topButton = document.getElementById("topnavButton");
var topnavList = document.getElementById("topnavList");
if (topButton && topnavList) {
topButton.addEventListener("click", function (e) {
topnavList
.classList
.toggle("hidden");
e.stopPropagation();
});
document.addEventListener("click", function (e) {
// if the clicked element isn't the list, close the list
if (!topnavList.classList.contains("hidden") && !e.target.closest("#topnavList")) {
topButton.click();
}
});
// set active <a> element
var url = window
.location
.href
.toLowerCase();
var aTags = topnavList.getElementsByTagName('a');
for (var i = 0; i < aTags.length; i++) {
var lowerhref = aTags[i]
.href
.toLowerCase();
if (lowerhref.endsWith('.html'))
lowerhref = lowerhref.slice(0, -5);
if (url.startsWith(lowerhref)) {
aTags[i]
.classList
.add('active');
break;
}
}
}
});
</script>
<div class="flex flex-col prose">
<div class="w-full max-w-screen-xl mx-auto">
<!-- * * * * * * * * * * * * * -->
<!-- Start of GoJS sample code -->
<script src="https://cdn.jsdelivr.net/npm/gojs@3.1.0"></script>
<div id="allSampleContent" class="p-4 w-full">
<script id="code">
function init() {
myDiagram = new go.Diagram('myDiagramDiv', {
maxSelectionCount: 1 // no more than 1 element can be selected at a time
});
// define the node template
myDiagram.nodeTemplate =
new go.Node('Auto', {
locationSpot: go.Spot.Center,
toEndSegmentLength: 30,
fromEndSegmentLength: 30,
// define a tooltip for each node that displays its information
toolTip:
go.GraphObject.build('ToolTip')
.add(
new go.TextBlock({ margin: 4 })
.bind('text', '', getInfo)
)
})
.bindTwoWay('location')
.add(
new go.Shape('Rectangle', {
name: 'OBJSHAPE',
fill: 'white',
desiredSize: new go.Size(30, 30)
}),
new go.TextBlock({ margin: 4 })
.bind('text', 'key')
);
// define the link template
myDiagram.linkTemplate =
new go.Link({
selectionAdornmentTemplate:
new go.Adornment()
.add(
new go.Shape({ isPanelMain: true, stroke: 'dodgerblue', strokeWidth: 3 }),
new go.Shape({ toArrow: 'Standard', fill: 'dodgerblue', stroke: null, scale: 1 })
),
routing: go.Routing.Normal,
curve: go.Curve.Bezier,
toShortLength: 2,
// define a tooltip for each link that displays its information
toolTip:
go.GraphObject.build('ToolTip')
.add(
new go.TextBlock({ margin: 4 })
.bind('text', '', getInfo)
)
})
.add(
new go.Shape({ name: 'OBJSHAPE' }), // the link shape
new go.Shape({ name: 'ARWSHAPE', toArrow: 'Standard' }) // the arrowhead
);
// define the group template
myDiagram.groupTemplate =
new go.Group('Spot', {
// adornment when a group is selected
selectionAdornmentTemplate:
new go.Adornment('Auto')
.add(
new go.Shape('Rectangle', { fill: null, stroke: 'dodgerblue', strokeWidth: 3 }),
new go.Placeholder()
),
toSpot: go.Spot.AllSides, // links coming into groups at any side
toEndSegmentLength: 30,
fromEndSegmentLength: 30,
// define a tooltip for each group that displays its information
toolTip:
go.GraphObject.build('ToolTip')
.add(
new go.TextBlock({ margin: 4 })
.bind('text', '', getInfo)
)
})
.add(
new go.Panel('Auto')
.add(
new go.Shape('Rectangle', {
name: 'OBJSHAPE',
parameter1: 14,
fill: 'rgba(255,0,0,0.10)'
})
.bind('desiredSize', 'ds'),
new go.Placeholder({ padding: 16 })
),
new go.TextBlock({
name: 'GROUPTEXT',
alignment: go.Spot.TopLeft,
alignmentFocus: new go.Spot(0, 0, -4, -4),
font: 'Bold 10pt Sans-Serif'
})
.bind('text', 'key')
);
// add nodes, including groups, and links to the model
myDiagram.model = new go.GraphLinksModel(
[
// node data
{ key: 'A', location: new go.Point(320, 100) },
{ key: 'B', location: new go.Point(420, 270) },
{ key: 'C', group: 'Psi', location: new go.Point(270, 215) },
{ key: 'D', group: 'Omega', location: new go.Point(270, 325) },
{ key: 'E', group: 'Phi', location: new go.Point(120, 225) },
{ key: 'F', group: 'Omega', location: new go.Point(200, 350) },
{ key: 'G', location: new go.Point(180, 450) },
{ key: 'Chi', isGroup: true },
{ key: 'Psi', isGroup: true, group: 'Chi' },
{ key: 'Phi', isGroup: true, group: 'Psi' },
{ key: 'Omega', isGroup: true, group: 'Psi' }
],
[
// link data
{ from: 'A', to: 'B' },
{ from: 'A', to: 'C' },
{ from: 'A', to: 'C' },
{ from: 'B', to: 'B' },
{ from: 'B', to: 'C' },
{ from: 'B', to: 'Omega' },
{ from: 'C', to: 'A' },
{ from: 'C', to: 'Psi' },
{ from: 'C', to: 'D' },
{ from: 'D', to: 'F' },
{ from: 'E', to: 'F' },
{ from: 'F', to: 'G' }
]
);
// whenever selection changes, run updateHighlights
myDiagram.addDiagramListener('ChangedSelection', () => updateHighlights(getRadioButton()));
myDiagram.select(myDiagram.findNodeForKey('A'));
}
// This highlights all graph objects that should be highlighted
// whenever a radio button is checked or selection changes.
// Parameter e is the checked radio button.
function updateHighlights(e) {
// Set highlight to 0 for everything before updating
myDiagram.nodes.each(node => (node.highlight = 0));
myDiagram.links.each(link => (link.highlight = 0));
// Get the selected GraphObject and run the appropriate method
var sel = myDiagram.selection.first();
if (sel !== null) {
switch (e.id) {
case 'linksIn':
linksTo(sel, 1);
break;
case 'linksOut':
linksFrom(sel, 1);
break;
case 'linksAll':
linksAll(sel, 1);
break;
case 'nodesIn':
nodesTo(sel, 1);
break;
case 'nodesOut':
nodesFrom(sel, 1);
break;
case 'nodesConnect':
nodesConnect(sel, 1);
break;
case 'nodesReach':
nodesReach(sel, 1);
break;
case 'group':
containing(sel, 1);
break;
case 'groupsAll':
containingAll(sel, 1);
break;
case 'nodesMember':
childNodes(sel, 1);
break;
case 'nodesMembersAll':
allMemberNodes(sel, 1);
break;
case 'linksMember':
childLinks(sel, 1);
break;
case 'linksMembersAll':
allMemberLinks(sel, 1);
break;
}
}
// Give everything the appropriate highlighting ( color and width of stroke )
// nodes, including groups
myDiagram.nodes.each(node => {
var shp = node.findObject('OBJSHAPE');
var grp = node.findObject('GROUPTEXT');
var hl = node.highlight;
highlight(shp, grp, hl);
});
// links
myDiagram.links.each(link => {
var hl = link.highlight;
var shp = link.findObject('OBJSHAPE');
var arw = link.findObject('ARWSHAPE');
highlight(shp, arw, hl);
});
}
// Functions for highlighting, called by updateHighlights.
// x in each case is the selected object or the object being treated as such.
// Some have return values for use by each other or for tooltips.
// if the link connects to this node, highlight it
function linksTo(x, i) {
if (x instanceof go.Node) {
x.findLinksInto().each(link => (link.highlight = i));
}
}
// if the link comes from this node, highlight it
function linksFrom(x, i) {
if (x instanceof go.Node) {
x.findLinksOutOf().each(link => (link.highlight = i));
}
}
// highlight all links connected to this node
function linksAll(x, i) {
if (x instanceof go.Node) {
x.linksConnected.each(link => (link.highlight = i));
}
}
// If selected object is a link, highlight its fromNode.
// Otherwise highlight the fromNode of each link coming into the selected node.
// Return a List of the keys of the nodes.
function nodesTo(x, i) {
var nodesToList = new go.List(/*"string"*/);
if (x instanceof go.Link) {
x.fromNode.highlight = i;
nodesToList.add(x.data.from);
} else {
x.findNodesInto().each(node => {
node.highlight = i;
nodesToList.add(node.data.key);
});
}
return nodesToList;
}
// same as nodesTo, but 'from' instead of 'to'
function nodesFrom(x, i) {
var nodesFromList = new go.List(/*"string"*/);
if (x instanceof go.Link) {
x.toNode.highlight = i;
nodesFromList.add(x.data.to);
} else {
x.findNodesOutOf().each(node => {
node.highlight = i;
nodesFromList.add(node.data.key);
});
}
return nodesFromList;
}
// If x is a link, highlight its toNode, or if it is a node, the node(s) it links to,
// and then call nodesReach on the highlighted node(s), with the next color.
// Do not highlight any node that has already been highlit with a color
// indicating a closer relationship to the original node.
function nodesReach(x, i) {
if (x instanceof go.Link) {
x.toNode.highlight = i;
nodesReach(x.toNode, i + 1);
} else {
x.findNodesOutOf().each(node => {
if (node.highlight === 0 || node.highlight > i) {
node.highlight = i;
nodesReach(node, i + 1);
}
});
}
}
// highlight all nodes linked to this one
function nodesConnect(x, i) {
if (x instanceof go.Link) {
x.toNode.highlight = i;
x.fromNode.highlight = i;
} else {
x.findNodesConnected().each(node => (node.highlight = i));
}
}
// highlights the group containing this object, specific method for links
// returns the containing group of x
function containing(x, i) {
var container = x.containingGroup;
if (container !== null) container.highlight = i;
return container;
}
// container is the group that contains this node and
// will be the parameter x for the next call of this function.
// Calling containing(x,i) highlights each group the appropriate color
function containingAll(x, i) {
containing(x, i);
var container = x.containingGroup;
if (container !== null) containingAll(container, i + 1);
}
// if the Node"s containingGroup is x, highlight it
function childNodes(x, i) {
var childLst = new go.List(/*"string"*/);
if (x instanceof go.Group) {
myDiagram.nodes.each(node => {
if (node.containingGroup === x) {
node.highlight = i;
childLst.add(node.data.key);
}
});
}
return childLst;
}
// same as childNodes, then run allMemberNodes for each child Group with the next color
function allMemberNodes(x, i) {
if (x instanceof go.Group) {
myDiagram.nodes.each(node => {
if (node.containingGroup === x) {
node.highlight = i;
allMemberNodes(node, i + 1);
}
});
}
}
// if the link"s containing Group is x, highlight it
function childLinks(x, i) {
var childLst = new go.List(/*go.Link*/);
myDiagram.links.each(link => {
if (link.containingGroup === x) {
link.highlight = i;
childLst.add(link);
}
});
return childLst;
}
// same as childLinks, then run allMemberLinks for each child Group with the next color
function allMemberLinks(x, i) {
childLinks(x, i);
myDiagram.nodes.each(node => {
if (node instanceof go.Group && node.containingGroup === x) {
allMemberLinks(node, i + 1);
}
});
}
// perform the actual highlighting
function highlight(shp, obj2, hl) {
var color;
var width = 3;
if (hl === 0) {
color = 'black';
width = 1;
} else if (hl === 1) {
color = 'blue';
} else if (hl === 2) {
color = 'green';
} else if (hl === 3) {
color = 'orange';
} else if (hl === 4) {
color = 'red';
} else {
color = 'purple';
}
shp.stroke = color;
shp.strokeWidth = width;
if (obj2 !== null) {
obj2.stroke = color;
obj2.fill = color;
}
}
// return the selected radio button in "highlight"
function getRadioButton() {
var radio = document.getElementsByName('highlight');
for (var i = 0; i < radio.length; i++) if (radio[i].checked) return radio[i];
}
// returns the text for a tooltip, param obj is the text itself
function getInfo(model, obj) {
var x = obj.panel.adornedPart; // the object that the mouse is over
var text = ''; // what will be displayed
if (x instanceof go.Node) {
if (x instanceof go.Group) text += 'Group: ';
else text += 'Node: ';
text += x.data.key;
var toLst = nodesTo(x, 0); // display names of nodes going into this node
if (toLst.count > 0) {
toLst.sort((a, b) => (a < b ? -1 : 1));
text += '\nNodes into: ';
toLst.each(key => {
if (key !== text.substring(text.length - 3, text.length - 2)) {
text += key + ', ';
}
});
text = text.substring(0, text.length - 2);
}
var frLst = nodesFrom(x, 0); // display names of nodes coming out of this node
if (frLst.count > 0) {
frLst.sort((a, b) => (a < b ? -1 : 1));
text += '\nNodes out of: ';
frLst.each(key => {
if (key !== text.substring(text.length - 3, text.length - 2)) {
text += key + ', ';
}
});
text = text.substring(0, text.length - 2);
}
var grpC = containing(x, 0); // if the node is in a group, display its name
if (grpC !== null) text += '\nContaining SubGraph: ' + grpC.data.key;
if (x instanceof go.Group) {
// if it"s a group, also display nodes and links contained in it
text += '\nMember nodes: ';
var children = childNodes(x, 0);
children.sort((a, b) => (a < b ? -1 : 1));
children.each(key => {
if (key !== text.substring(text.length - 3, text.length - 2)) {
text += key + ', ';
}
});
text = text.substring(0, text.length - 2);
var linkChildren = childLinks(x, 0);
if (linkChildren.count > 0) {
text += '\nMember links: ';
var linkStrings = new go.List(/*"string"*/);
linkChildren.each(link => {
linkStrings.add(link.data.from + ' --> ' + link.data.to);
});
linkStrings.sort((a, b) => (a < b ? -1 : 1));
linkStrings.each(str => {
text += str + ', ';
});
text = text.substring(0, text.length - 2);
}
}
} else if (x instanceof go.Link) {
// if it"s a link, display its to and from nodes
text += 'Link: ' + x.data.from + ' --> ' + x.data.to + '\nNode To: ' + x.data.to + '\nNode From: ' + x.data.from;
var grp = containing(x, 0); // and containing group, if it has one
if (grp !== null) text += '\nContaining SubGraph: ' + grp.data.key;
}
return text;
}
window.addEventListener('DOMContentLoaded', init);
</script>
<div id="sample">
<div id="displays" style="width: 100%; white-space: nowrap;">
<div id="myDiagramDiv" style="border: solid 1px black; height: 560px; display: inline-block; vertical-align: top; width: 70%"></div>
<div id="controls" style="border: solid 1px black; display: inline-block; vertical-align: top">
<div id="buttons" style="border-radius: 10px; border: solid 1px gray; background-color: #eaeaea; margin: 5px">
<b style="margin: 5px">Related Parts Highlighted</b> <br />
<label><input type="radio" name="highlight" onclick="updateHighlights(this)" id="None" />Unhighlight All</label><br />
<label><input type="radio" name="highlight" onclick="updateHighlights(this)" id="linksIn" />Links Into</label><br />
<label><input type="radio" name="highlight" onclick="updateHighlights(this)" id="linksOut" />Links Out Of</label><br />
<label><input type="radio" name="highlight" onclick="updateHighlights(this)" id="linksAll" />Links Connected</label><br />
<label><input type="radio" name="highlight" onclick="updateHighlights(this)" id="nodesIn" />Nodes Into</label><br />
<label><input type="radio" name="highlight" onclick="updateHighlights(this)" id="nodesOut" />Nodes Out Of</label><br />
<label><input type="radio" name="highlight" onclick="updateHighlights(this)" id="nodesConnect" />Nodes Connected</label><br />
<label><input type="radio" name="highlight" onclick="updateHighlights(this)" id="nodesReach" checked="checked" />Nodes Reachable</label><br />
<label><input type="radio" name="highlight" onclick="updateHighlights(this)" id="group" />Containing Group (Parent)</label><br />
<label><input type="radio" name="highlight" onclick="updateHighlights(this)" id="groupsAll" />Containing Groups (All)</label><br />
<label><input type="radio" name="highlight" onclick="updateHighlights(this)" id="nodesMember" />Member Nodes (Children)</label><br />
<label><input type="radio" name="highlight" onclick="updateHighlights(this)" id="nodesMembersAll" />Member Nodes (All)</label><br />
<label><input type="radio" name="highlight" onclick="updateHighlights(this)" id="linksMember" />Member Links (Children)</label><br />
<label><input type="radio" name="highlight" onclick="updateHighlights(this)" id="linksMembersAll" />Member Links (All)</label><br />
</div>
<div id="colorKey" style="border-radius: 10px; border: solid 1px gray; background-color: #eaeaea; margin: 5px">
<b style="margin: 5px">Relationship Colors</b>
<table>
<tr>
<td><div style="float: left; margin: 5px; height: 20px; width: 20px; background-color: black"></div></td>
<td>Not related</td>
</tr>
<tr>
<td><div style="float: left; margin: 5px; height: 20px; width: 20px; background-color: blue"></div></td>
<td>Directly related</td>
</tr>
<tr>
<td><div style="float: left; margin: 5px; height: 20px; width: 20px; background-color: green"></div></td>
<td>2 relationships apart</td>
</tr>
<tr>
<td><div style="float: left; margin: 5px; height: 20px; width: 20px; background-color: orange"></div></td>
<td>3 relationships apart</td>
</tr>
<tr>
<td><div style="float: left; margin: 5px; height: 20px; width: 20px; background-color: red"></div></td>
<td>4 relationships apart</td>
</tr>
<tr>
<td><div style="float: left; margin: 5px; height: 20px; width: 20px; background-color: purple"></div></td>
<td>Very indirectly related</td>
</tr>
</table>
</div>
</div>
</div>
<div>
<p>This sample displays relationships between different parts of a diagram.</p>
<p>
Select a node or link and one of the radio buttons to highlight parts with a certain relationship to the one selected. The highlighting color depends on
the "distance" between the parts.
</p>
</div>
</div>
</div>
<!-- * * * * * * * * * * * * * -->
<!-- End of GoJS sample code -->
</div>
<div id="allTagDescriptions" class="p-4 w-full max-w-screen-xl mx-auto">
<hr/>
<h3 class="text-xl">GoJS Features in this sample</h3>
<!-- blacklist tags that do not correspond to a specific GoJS feature -->
<h4>Collections</h4>
<p>
<b>GoJS</b> provides its own collection classes: <a href="../api/symbols/List.html" target="api">List</a>, <a href="../api/symbols/Set.html" target="api">Set</a>, and <a href="../api/symbols/Map.html" target="api">Map</a>.
You can iterate over a collection by using an <a href="../api/symbols/Iterator.html" target="api">Iterator</a>.
More information can be found in the <a href="../intro/collections.html">GoJS Intro</a>.
</p>
<p>
<a href="../samples/index.html#collections">Related samples</a>
</p>
<hr>
<!-- blacklist tags that do not correspond to a specific GoJS feature -->
<h4>Groups</h4>
<p>
The <a href="../api/symbols/Group.html" target="api">Group</a> class is used to treat a collection of <a href="../api/symbols/Node.html" target="api">Node</a>s and <a href="../api/symbols/Link.html" target="api">Link</a>s as if they were a single <a href="../api/symbols/Node.html" target="api">Node</a>.
Those nodes and links are members of the group; together they constitute a subgraph.
</p>
<p>
A subgraph is <em>not</em> another <a href="../api/symbols/Diagram.html" target="api">Diagram</a>, so there is no separate HTML Div element for the subgraph of a group.
All of the <a href="../api/symbols/Part.html" target="api">Part</a>s that are members of a <a href="../api/symbols/Group.html" target="api">Group</a> belong to the same Diagram as the Group.
There can be links between member nodes and nodes outside of the group as well as links between the group itself and other nodes.
There can even be links between member nodes and the containing group itself.
</p>
<p>
More information can be found in the <a href="../intro/groups.html">GoJS Intro</a>.
</p>
<p>
<a href="../samples/index.html#groups">Related samples</a>
</p>
<hr>
<!-- blacklist tags that do not correspond to a specific GoJS feature -->
<h4>ToolTips</h4>
<p>
A tooltip is an <a href="../api/symbols/Adornment.html" target="api">Adornment</a> that is shown when the mouse hovers over an object that has its <a href="../api/symbols/GraphObject.html#toolTip" target="api">GraphObject.toolTip</a> set.
The tooltip part is bound to the same data as the part itself.
</p>
<p>
It is typical to implement a tooltip as a "ToolTip" Panel holding a <a href="../api/symbols/TextBlock.html" target="api">TextBlock</a> or a Panel of TextBlocks and other objects.
Each "ToolTip" is just an "Auto" Panel <a href="../api/symbols/Adornment.html" target="api">Adornment</a> that is shadowed, and where the border is a rectangular <a href="../api/symbols/Shape.html" target="api">Shape</a> with a light gray fill.
However you can implement the tooltip as any arbitrarily complicated Adornment.
</p>
<p>
More information can be found in the <a href="../intro/tooltips.html">GoJS Intro</a>.
</p>
<p>
<a href="../samples/index.html#tooltips">Related samples</a>
</p>
<hr>
</div>
</div>
</body>
<!-- This script is part of the gojs.net website, and is not needed to run the sample -->
<script src="../assets/js/goSamples.js"></script>
</html>