-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
274 lines (258 loc) · 11.7 KB
/
index.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
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Regrouping Demo</title>
<meta name="description"
content="Create new collapsible groups, ungroup existing groups, and use drag-and-drop to change grouping memberships." />
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Copyright 1998-2020 by Northwoods Software Corporation. -->
<script src="https://gojs.net/latest/release/go.js"></script>
<script id="code">
function init() {
var $ = go.GraphObject.make;
myDiagram =
$(go.Diagram, "myDiagramDiv",
{
// what to do when a drag-drop occurs in the Diagram's background
mouseDrop: function (e) { finishDrop(e, null); },
layout: // Diagram has simple horizontal layout
$(go.GridLayout,
{ wrappingWidth: Infinity, alignment: go.GridLayout.Position, cellSize: new go.Size(1, 1) }),
"commandHandler.archetypeGroupData": { isGroup: true, category: "OfNodes" },
"undoManager.isEnabled": true
});
// There are two templates for Groups, "OfGroups" and "OfNodes".
// this function is used to highlight a Group that the selection may be dropped into
function highlightGroup(e, grp, show) {
if (!grp) return;
e.handled = true;
if (show) {
// cannot depend on the grp.diagram.selection in the case of external drag-and-drops;
// instead depend on the DraggingTool.draggedParts or .copiedParts
var tool = grp.diagram.toolManager.draggingTool;
var map = tool.draggedParts || tool.copiedParts; // this is a Map
// now we can check to see if the Group will accept membership of the dragged Parts
if (grp.canAddMembers(map.toKeySet())) {
grp.isHighlighted = true;
return;
}
}
grp.isHighlighted = false;
}
// Upon a drop onto a Group, we try to add the selection as members of the Group.
// Upon a drop onto the background, or onto a top-level Node, make selection top-level.
// If this is OK, we're done; otherwise we cancel the operation to rollback everything.
function finishDrop(e, grp) {
var ok = (grp !== null
? grp.addMembers(grp.diagram.selection, true)
: e.diagram.commandHandler.addTopLevelParts(e.diagram.selection, true));
if (!ok) e.diagram.currentTool.doCancel();
}
myDiagram.groupTemplateMap.add("OfGroups",
$(go.Group, "Auto",
{
background: "transparent",
// highlight when dragging into the Group
mouseDragEnter: function (e, grp, prev) { highlightGroup(e, grp, true); },
mouseDragLeave: function (e, grp, next) { highlightGroup(e, grp, false); },
computesBoundsAfterDrag: true,
// when the selection is dropped into a Group, add the selected Parts into that Group;
// if it fails, cancel the tool, rolling back any changes
mouseDrop: finishDrop,
handlesDragDropForMembers: true, // don't need to define handlers on member Nodes and Links
// Groups containing Groups lay out their members horizontally
layout:
$(go.GridLayout,
{
wrappingWidth: Infinity, alignment: go.GridLayout.Position,
cellSize: new go.Size(1, 1), spacing: new go.Size(4, 4)
})
},
new go.Binding("background", "isHighlighted", function (h) { return h ? "rgba(255,0,0,0.2)" : "transparent"; }).ofObject(),
$(go.Shape, "Rectangle",
{ fill: null, stroke: "#FFDD33", strokeWidth: 2 }),
$(go.Panel, "Vertical", // title above Placeholder
$(go.Panel, "Horizontal", // button next to TextBlock
{ stretch: go.GraphObject.Horizontal, background: "#FFDD33" },
$("SubGraphExpanderButton",
{ alignment: go.Spot.Right, margin: 5 }),
$(go.TextBlock,
{
alignment: go.Spot.Left,
editable: true,
margin: 5,
font: "bold 18px sans-serif",
opacity: 0.75,
stroke: "#404040"
},
new go.Binding("text", "text").makeTwoWay())
), // end Horizontal Panel
$(go.Placeholder,
{ padding: 5, alignment: go.Spot.TopLeft })
) // end Vertical Panel
)); // end Group and call to add to template Map
myDiagram.groupTemplateMap.add("OfNodes",
$(go.Group, "Auto",
{
background: "transparent",
ungroupable: true,
// highlight when dragging into the Group
mouseDragEnter: function (e, grp, prev) { highlightGroup(e, grp, true); },
mouseDragLeave: function (e, grp, next) { highlightGroup(e, grp, false); },
computesBoundsAfterDrag: true,
// when the selection is dropped into a Group, add the selected Parts into that Group;
// if it fails, cancel the tool, rolling back any changes
mouseDrop: finishDrop,
handlesDragDropForMembers: true, // don't need to define handlers on member Nodes and Links
// Groups containing Nodes lay out their members vertically
layout:
$(go.GridLayout,
{
wrappingColumn: 1, alignment: go.GridLayout.Position,
cellSize: new go.Size(1, 1), spacing: new go.Size(4, 4)
})
},
new go.Binding("background", "isHighlighted", function (h) { return h ? "rgba(255,0,0,0.2)" : "transparent"; }).ofObject(),
$(go.Shape, "Rectangle",
{ fill: null, stroke: "#33D3E5", strokeWidth: 2 }),
$(go.Panel, "Vertical", // title above Placeholder
$(go.Panel, "Horizontal", // button next to TextBlock
{ stretch: go.GraphObject.Horizontal, background: "#33D3E5" },
$("SubGraphExpanderButton",
{ alignment: go.Spot.Right, margin: 5 }),
$(go.TextBlock,
{
alignment: go.Spot.Left,
editable: true,
margin: 5,
font: "bold 16px sans-serif",
opacity: 0.75,
stroke: "#404040"
},
new go.Binding("text", "text").makeTwoWay())
), // end Horizontal Panel
$(go.Placeholder,
{ padding: 5, alignment: go.Spot.TopLeft })
) // end Vertical Panel
)); // end Group and call to add to template Map
myDiagram.nodeTemplate =
$(go.Node, "Auto",
{ // dropping on a Node is the same as dropping on its containing Group, even if it's top-level
mouseDrop: function (e, nod) { finishDrop(e, nod.containingGroup); }
},
$(go.Shape, "Rectangle",
{ fill: "#ACE600", stroke: null },
new go.Binding("fill", "color")),
$(go.TextBlock,
{
margin: 5,
editable: true,
font: "bold 13px sans-serif",
opacity: 0.75,
stroke: "#404040"
},
new go.Binding("text", "text").makeTwoWay())
);
// initialize the Palette and its contents
myPalette =
$(go.Palette, "myPaletteDiv",
{
nodeTemplateMap: myDiagram.nodeTemplateMap,
groupTemplateMap: myDiagram.groupTemplateMap,
layout: $(go.GridLayout, { wrappingColumn: 1, alignment: go.GridLayout.Position })
});
myPalette.model = new go.GraphLinksModel([
{ text: "lightgreen", color: "#ACE600" },
{ text: "yellow", color: "#FFDD33" },
{ text: "lightblue", color: "#33D3E5" }
]);
var slider = document.getElementById("levelSlider");
slider.addEventListener('change', reexpand);
slider.addEventListener('input', reexpand);
load();
}
function expandGroups(g, i, level) {
if (!(g instanceof go.Group)) return;
g.isSubGraphExpanded = i < level;
g.memberParts.each(function (m) {
expandGroups(m, i + 1, level);
})
}
function reexpand(e) {
myDiagram.startTransaction("reexpand");
var level = parseInt(document.getElementById("levelSlider").value);
myDiagram.findTopLevelGroups().each(function (g) { expandGroups(g, 0, level); })
myDiagram.commitTransaction("reexpand");
}
// save a model to and load a model from JSON text, displayed below the Diagram
function save() {
document.getElementById("mySavedModel").value = myDiagram.model.toJson();
myDiagram.isModified = false;
}
function load() {
myDiagram.model = go.Model.fromJson(document.getElementById("mySavedModel").value);
}
</script>
</head>
<body onload="init()">
<div id="sample">
<div style="width: 100%; display: flex; justify-content: space-between">
<div id="myPaletteDiv"
style="width: 100px; margin-right: 2px; background-color: whitesmoke; border: solid 1px black"></div>
<div id="myDiagramDiv" style="flex-grow: 1; height: 500px; border: solid 1px black"></div>
</div>
<p>
This sample allows the user to drag nodes, including groups, into and out of groups,
both from the Palette as well as from within the Diagram.
See the <a href="../intro/groups.html">Groups Intro page</a> for an explanation of GoJS Groups.
</p>
<p>
Highlighting to show feedback about potential addition to a group during a drag is implemented
using <a>GraphObject.mouseDragEnter</a> and <a>GraphObject.mouseDragLeave</a> event handlers.
Because <a>Group.computesBoundsAfterDrag</a> is true, the Group's <a>Placeholder</a>'s bounds are
not computed until the drop happens, so the group does not continuously expand as the user drags
a member of a group.
</p>
<p>
When a drop occurs on a Group or a regular Node, the <a>GraphObject.mouseDrop</a> event handler
adds the selection (the dragged Nodes) to the Group as new members.
</p>
<p>
The <a>TextBlock</a>s use the <a>GraphObject.opacity</a> property, which allows for the text
to somewhat match the color of what it's on top of.
</p>
<p>
The slider controls how many nested levels of Groups are expanded. </br>
Semantic zoom level: <input id="levelSlider" type="range" min="0" max="5" value="3" />
</p>
<div id="buttons">
<button id="saveModel" onclick="save()">Save</button>
<button id="loadModel" onclick="load()">Load</button>
Diagram Model saved in JSON format:
</div>
<textarea id="mySavedModel" style="width:100%;height:300px">
{ "class": "go.GraphLinksModel",
"nodeDataArray": [
{"key":1, "text":"Main 1", "isGroup":true, "category":"OfGroups"},
{"key":2, "text":"Main 2", "isGroup":true, "category":"OfGroups"},
{"key":3, "text":"Group A", "isGroup":true, "category":"OfNodes", "group":1},
{"key":4, "text":"Group B", "isGroup":true, "category":"OfNodes", "group":1},
{"key":5, "text":"Group C", "isGroup":true, "category":"OfNodes", "group":2},
{"key":6, "text":"Group D", "isGroup":true, "category":"OfNodes", "group":2},
{"key":7, "text":"Group E", "isGroup":true, "category":"OfNodes", "group":6},
{"text":"first A", "group":3, "key":-7},
{"text":"second A", "group":3, "key":-8},
{"text":"first B", "group":4, "key":-9},
{"text":"second B", "group":4, "key":-10},
{"text":"third B", "group":4, "key":-11},
{"text":"first C", "group":5, "key":-12},
{"text":"second C", "group":5, "key":-13},
{"text":"first D", "group":6, "key":-14},
{"text":"first E", "group":7, "key":-15}
],
"linkDataArray": [ ]}
</textarea>
</div>
</body>
</html>