mkdocs-nodegraph 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mkdocs_nodegraph/__init__.py +3 -0
- mkdocs_nodegraph/nodegraph/__init__.py +0 -0
- mkdocs_nodegraph/nodegraph/generate_graph.py +341 -0
- mkdocs_nodegraph/nodegraph/graph_opts.json +7 -0
- mkdocs_nodegraph/nodegraph/mdfile.py +14 -0
- mkdocs_nodegraph/nodegraph/mdparser.py +95 -0
- mkdocs_nodegraph/nodegraph/pyvis_opts.js +37 -0
- mkdocs_nodegraph/nodegraph/templates/__init__.py +0 -0
- mkdocs_nodegraph/nodegraph/templates/template.html +1158 -0
- mkdocs_nodegraph/plugin.py +89 -0
- mkdocs_nodegraph-0.1.0.dist-info/METADATA +16 -0
- mkdocs_nodegraph-0.1.0.dist-info/RECORD +15 -0
- mkdocs_nodegraph-0.1.0.dist-info/WHEEL +5 -0
- mkdocs_nodegraph-0.1.0.dist-info/entry_points.txt +2 -0
- mkdocs_nodegraph-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,1158 @@
|
|
|
1
|
+
<html>
|
|
2
|
+
<head>
|
|
3
|
+
<meta charset="utf-8">
|
|
4
|
+
{% if cdn_resources=="local" %}
|
|
5
|
+
|
|
6
|
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/vis-network/9.1.2/dist/dist/vis-network.min.css" integrity="sha512-WgxfT5LWjfszlPHXRmBWHkV2eceiWTOBvrKCNbdgDYTHrT2AeLCGbF4sZlZw3UMN3WtL0tGUoIAKsu8mllg/XA==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
|
7
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/vis-network/9.1.2/dist/vis-network.min.js" integrity="sha512-LnvoEWDFrqGHlHmDD2101OrLcbsfkrzoSpvtSQtxK3RMnRV0eOkhhBN2dXHKRrUU8p2DGRTk35n4O8nWSVe1mQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
|
8
|
+
{% if select_menu or filter_menu %}
|
|
9
|
+
<link href="lib/tom-select/tom-select.css" rel="stylesheet">
|
|
10
|
+
<script src="lib/tom-select/tom-select.complete.min.js"></script>
|
|
11
|
+
{% endif %}
|
|
12
|
+
{% elif cdn_resources=="in_line" %}
|
|
13
|
+
<style>{% include 'lib/vis-9.1.2/vis-network.css' %}</style>
|
|
14
|
+
<script>{% include 'lib/vis-9.1.2/vis-network.min.js' %}</script>
|
|
15
|
+
{% if select_menu or filter_menu %}
|
|
16
|
+
<style>{% include 'lib/tom-select/tom-select.css' %}</style>
|
|
17
|
+
<script>{% include 'lib/tom-select/tom-select.complete.min.js' %}</script>
|
|
18
|
+
{% endif %}
|
|
19
|
+
{% elif cdn_resources=="remote" %}
|
|
20
|
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/vis-network/9.1.2/dist/dist/vis-network.min.css" integrity="sha512-WgxfT5LWjfszlPHXRmBWHkV2eceiWTOBvrKCNbdgDYTHrT2AeLCGbF4sZlZw3UMN3WtL0tGUoIAKsu8mllg/XA==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
|
21
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/vis-network/9.1.2/dist/vis-network.min.js" integrity="sha512-LnvoEWDFrqGHlHmDD2101OrLcbsfkrzoSpvtSQtxK3RMnRV0eOkhhBN2dXHKRrUU8p2DGRTk35n4O8nWSVe1mQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
|
22
|
+
{# <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/vis-network/9.0.4/dist/dist/vis-network.min.css" integrity="sha512-+5tJeVsSE2tSnmKB5SWOD0GsYA5dOP0B/FSv7I2GYhdOcyjJq81Q1St3qgJgInwreAdNuw0KGJ0FOaxOJ0E4yw==" crossorigin="anonymous" referrerpolicy="no-referrer" />#}
|
|
23
|
+
{# <script src="https://cdnjs.cloudflare.com/ajax/libs/vis-network/9.0.4/dist/vis-network.js"#}
|
|
24
|
+
{# integrity="sha512-CEbUhbSq35hCqBH8ckfAkH1Tcua5NEywtEzwiJ+BUC4EIZkC7vyta3ivZu/WqJhK1qHTurO3hwHsErU3HHjwIA=="#}
|
|
25
|
+
{# crossorigin="anonymous"#}
|
|
26
|
+
{# referrerpolicy="no-referrer"></script>#}
|
|
27
|
+
{% if select_menu or filter_menu %}
|
|
28
|
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tom-select/2.0.0-rc.4/css/tom-select.min.css" integrity="sha512-43fHB3GLgZfz8QXl1RPQ8O66oIgv3po9cJ5erMt1c4QISq9dYb195T3vr5ImnJPXuVroKcGBPXBFKETW8jrPNQ==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
|
29
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/tom-select/2.0.0-rc.4/js/tom-select.complete.js" integrity="sha512-jeF9CfnvzDiw9G9xiksVjxR2lib44Gnovvkv+3CgCG6NXCD4gqlA5nDAVW5WjpA+i+/zKsUWV5xNEbW1X/HH0Q==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
|
30
|
+
{% endif %}
|
|
31
|
+
|
|
32
|
+
{% endif %}
|
|
33
|
+
<center>
|
|
34
|
+
<h1>{{heading}}</h1>
|
|
35
|
+
</center>
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
<script
|
|
39
|
+
src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/js/bootstrap.bundle.min.js"
|
|
40
|
+
integrity="sha384-JEW9xMcG8R+pH31jmWH6WWP0WintQrMb4s7ZOdauHnUtxwoG2vI5DkLtS3qm9Ekf"
|
|
41
|
+
crossorigin="anonymous"
|
|
42
|
+
></script>
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
<center>
|
|
46
|
+
<h1>{{heading}}</h1>
|
|
47
|
+
</center>
|
|
48
|
+
<style type="text/css">
|
|
49
|
+
|
|
50
|
+
#mynetwork {
|
|
51
|
+
width: {{width}};
|
|
52
|
+
height: {{height}};
|
|
53
|
+
background-color: {{bgcolor}};
|
|
54
|
+
position: absolute;
|
|
55
|
+
border: 1px solid {{bgcolor}};
|
|
56
|
+
float: left;
|
|
57
|
+
z-index: 1;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
{% if nodes|length > 100 and physics_enabled %}
|
|
61
|
+
|
|
62
|
+
#bar {
|
|
63
|
+
position:absolute;
|
|
64
|
+
top:0px;
|
|
65
|
+
left:0px;
|
|
66
|
+
width:20px;
|
|
67
|
+
height:20px;
|
|
68
|
+
margin:auto auto auto auto;
|
|
69
|
+
border-radius:11px;
|
|
70
|
+
border:2px solid rgba(30,30,30,0.05);
|
|
71
|
+
background: rgb(0, 173, 246); /* Old browsers */
|
|
72
|
+
box-shadow: 2px 0px 4px rgba(0,0,0,0.4);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
#border {
|
|
76
|
+
position:absolute;
|
|
77
|
+
top:10px;
|
|
78
|
+
left:10px;
|
|
79
|
+
width:500px;
|
|
80
|
+
height:23px;
|
|
81
|
+
margin:auto auto auto auto;
|
|
82
|
+
box-shadow: 0px 0px 4px rgba(0,0,0,0.2);
|
|
83
|
+
border-radius:10px;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
#text {
|
|
87
|
+
position:absolute;
|
|
88
|
+
top:8px;
|
|
89
|
+
left:530px;
|
|
90
|
+
width:30px;
|
|
91
|
+
height:50px;
|
|
92
|
+
margin:auto auto auto auto;
|
|
93
|
+
font-size:22px;
|
|
94
|
+
color: #000000;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
div.outerBorder {
|
|
98
|
+
position:relative;
|
|
99
|
+
top:400px;
|
|
100
|
+
width:600px;
|
|
101
|
+
height:44px;
|
|
102
|
+
margin:auto auto auto auto;
|
|
103
|
+
border:8px solid rgba(0,0,0,0.1);
|
|
104
|
+
background: rgb(252,252,252); /* Old browsers */
|
|
105
|
+
background: -moz-linear-gradient(top, rgba(252,252,252,1) 0%, rgba(237,237,237,1) 100%); /* FF3.6+ */
|
|
106
|
+
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(252,252,252,1)), color-stop(100%,rgba(237,237,237,1))); /* Chrome,Safari4+ */
|
|
107
|
+
background: -webkit-linear-gradient(top, rgba(252,252,252,1) 0%,rgba(237,237,237,1) 100%); /* Chrome10+,Safari5.1+ */
|
|
108
|
+
background: -o-linear-gradient(top, rgba(252,252,252,1) 0%,rgba(237,237,237,1) 100%); /* Opera 11.10+ */
|
|
109
|
+
background: -ms-linear-gradient(top, rgba(252,252,252,1) 0%,rgba(237,237,237,1) 100%); /* IE10+ */
|
|
110
|
+
background: linear-gradient(to bottom, rgba(252,252,252,1) 0%,rgba(237,237,237,1) 100%); /* W3C */
|
|
111
|
+
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#fcfcfc', endColorstr='#ededed',GradientType=0 ); /* IE6-9 */
|
|
112
|
+
border-radius:72px;
|
|
113
|
+
box-shadow: 0px 0px 10px rgba(0,0,0,0.2);
|
|
114
|
+
}
|
|
115
|
+
{% endif %}
|
|
116
|
+
|
|
117
|
+
{% if conf %}
|
|
118
|
+
#config {
|
|
119
|
+
float: left;
|
|
120
|
+
width: 400px;
|
|
121
|
+
height: 600px;
|
|
122
|
+
}
|
|
123
|
+
{% endif %}
|
|
124
|
+
|
|
125
|
+
{% if tooltip_link %}
|
|
126
|
+
/* position absolute is important and the container has to be relative or absolute as well. */
|
|
127
|
+
div.popup {
|
|
128
|
+
position:absolute;
|
|
129
|
+
top:0px;
|
|
130
|
+
left:0px;
|
|
131
|
+
display:none;
|
|
132
|
+
background-color:#f5f4ed;
|
|
133
|
+
-moz-border-radius: 3px;
|
|
134
|
+
-webkit-border-radius: 3px;
|
|
135
|
+
border-radius: 3px;
|
|
136
|
+
border: 1px solid #808074;
|
|
137
|
+
box-shadow: 3px 3px 10px rgba(0, 0, 0, 0.2);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/* hide the original tooltip */
|
|
141
|
+
.vis-tooltip {
|
|
142
|
+
display:none;
|
|
143
|
+
}
|
|
144
|
+
{% endif %}
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
body {
|
|
148
|
+
margin: 0;
|
|
149
|
+
padding: 0;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.card {
|
|
153
|
+
display: absolute;
|
|
154
|
+
min-height: 100vh;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.left-panel {
|
|
158
|
+
background: #222222a6;
|
|
159
|
+
width: 210px;
|
|
160
|
+
position: absolute;
|
|
161
|
+
z-index: 2;
|
|
162
|
+
border-radius: 10px;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.left-panel.collapsed {
|
|
166
|
+
width: 30px;
|
|
167
|
+
background: #22222200;
|
|
168
|
+
}
|
|
169
|
+
.left-panel.collapsed .panel-content {
|
|
170
|
+
opacity: 0;
|
|
171
|
+
visibility: hidden;
|
|
172
|
+
}
|
|
173
|
+
.collapse-btn {
|
|
174
|
+
position: absolute;
|
|
175
|
+
width: 30px;
|
|
176
|
+
height: 30px;
|
|
177
|
+
right: 0%;
|
|
178
|
+
padding: 2px 2px;
|
|
179
|
+
color: whitesmoke;
|
|
180
|
+
background: #222222a6;
|
|
181
|
+
border: none;
|
|
182
|
+
border-radius: 4px;
|
|
183
|
+
cursor: pointer;
|
|
184
|
+
transition: 0.3s;
|
|
185
|
+
user-select: none;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.collapse-btn:hover {
|
|
189
|
+
background: #747988;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
.panel-content {
|
|
193
|
+
flex-direction: column;
|
|
194
|
+
padding: 5px;
|
|
195
|
+
gap: 10px;
|
|
196
|
+
margin-bottom: 20px;
|
|
197
|
+
margin-top: 30px;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.physics-btn {
|
|
201
|
+
font-size: 13px;
|
|
202
|
+
position: relative;
|
|
203
|
+
z-index: 1000;
|
|
204
|
+
padding: 9px 9px;
|
|
205
|
+
margin: 3px;
|
|
206
|
+
background-color: hsl(122, 39%, 49%);
|
|
207
|
+
color: white;
|
|
208
|
+
border: none;
|
|
209
|
+
border-radius: 2px;
|
|
210
|
+
width: 200px;
|
|
211
|
+
cursor: pointer;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
.physics-btn:hover {
|
|
215
|
+
background-color:hsl(121, 47%, 57%);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.save-btn {
|
|
219
|
+
font-size: 13px;
|
|
220
|
+
position: relative;
|
|
221
|
+
z-index: 1000;
|
|
222
|
+
padding: 9px 9px;
|
|
223
|
+
margin: 3px;
|
|
224
|
+
background-color: hsl(194, 42%, 45%);
|
|
225
|
+
color: white;
|
|
226
|
+
border: none;
|
|
227
|
+
border-radius: 2px;
|
|
228
|
+
width: 200px;
|
|
229
|
+
cursor: pointer;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.save-btn:hover {
|
|
233
|
+
background-color: hsl(194, 41%, 53%);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
.reset-btn {
|
|
237
|
+
font-size: 14px;
|
|
238
|
+
position: relative;
|
|
239
|
+
z-index: 1000;
|
|
240
|
+
padding: 9px 9px;
|
|
241
|
+
margin: 3px;
|
|
242
|
+
background-color: hsl(0, 0%, 40%);
|
|
243
|
+
color: white;
|
|
244
|
+
border: none;
|
|
245
|
+
width: 200px;
|
|
246
|
+
border-radius: 2px;
|
|
247
|
+
cursor: pointer;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
.reset-btn:hover {
|
|
251
|
+
background-color: hsl(0, 0%, 50%);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
input {
|
|
255
|
+
accent-color: gray;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
</style>
|
|
259
|
+
</head>
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
<body>
|
|
263
|
+
<div class="card" style="width: 100%">
|
|
264
|
+
{% if select_menu %}
|
|
265
|
+
<div id="select-menu" class="card-header">
|
|
266
|
+
<div class="row no-gutters">
|
|
267
|
+
<div class="col-10 pb-2">
|
|
268
|
+
<select
|
|
269
|
+
class="form-select"
|
|
270
|
+
aria-label="Default select example"
|
|
271
|
+
onchange="selectNode([value]);"
|
|
272
|
+
id="select-node"
|
|
273
|
+
placeholder="Select node..."
|
|
274
|
+
>
|
|
275
|
+
<option selected>Select a Node by ID</option>
|
|
276
|
+
{% for node in nodes %}
|
|
277
|
+
<option value="{{ node.id }}">{{node.id}}</option>
|
|
278
|
+
{% endfor %}
|
|
279
|
+
</select>
|
|
280
|
+
</div>
|
|
281
|
+
<div class="col-2 pb-2">
|
|
282
|
+
<button type="button" class="btn btn-primary btn-block" onclick="neighbourhoodHighlight({nodes: []});">Reset Selection</button>
|
|
283
|
+
</div>
|
|
284
|
+
</div>
|
|
285
|
+
</div>
|
|
286
|
+
{% endif %}
|
|
287
|
+
{% if filter_menu %}
|
|
288
|
+
<div id="filter-menu" class="card-header">
|
|
289
|
+
<div class="row no-gutters">
|
|
290
|
+
<div class="col-3 pb-2">
|
|
291
|
+
<select
|
|
292
|
+
class="form-select"
|
|
293
|
+
aria-label="Default select example"
|
|
294
|
+
onchange="updateFilter(value, 'item')"
|
|
295
|
+
id="select-item"
|
|
296
|
+
>
|
|
297
|
+
<option value="">Select a network item</option>
|
|
298
|
+
<option value="edge">edge</option>
|
|
299
|
+
<option value="node">node</option>
|
|
300
|
+
</select>
|
|
301
|
+
</div>
|
|
302
|
+
<div class="col-3 pb-2">
|
|
303
|
+
<select
|
|
304
|
+
class="form-select"
|
|
305
|
+
aria-label="Default select example"
|
|
306
|
+
onchange="updateFilter(value, 'property')"
|
|
307
|
+
id="select-property"
|
|
308
|
+
>
|
|
309
|
+
<option value="">Select a property...</option>
|
|
310
|
+
</select>
|
|
311
|
+
</div>
|
|
312
|
+
<div class="col-3 pb-2">
|
|
313
|
+
<select
|
|
314
|
+
class="form-select"
|
|
315
|
+
aria-label="Default select example"
|
|
316
|
+
id="select-value"
|
|
317
|
+
>
|
|
318
|
+
<option value="">Select value(s)...</option>
|
|
319
|
+
</select>
|
|
320
|
+
</div>
|
|
321
|
+
<div class="col-1 pb-2">
|
|
322
|
+
<button type="button" class="btn btn-primary btn-block" onclick="highlightFilter(filter);">Filter</button>
|
|
323
|
+
</div>
|
|
324
|
+
<div class="col-2 pb-2">
|
|
325
|
+
<button type="button" class="btn btn-primary btn-block" onclick="clearFilter(true)">Reset Selection</button>
|
|
326
|
+
</div>
|
|
327
|
+
</div>
|
|
328
|
+
</div>
|
|
329
|
+
{% endif %}
|
|
330
|
+
|
|
331
|
+
<div class="left-panel" id="leftPanel">
|
|
332
|
+
<button class="collapse-btn" onclick="togglePanel('leftPanel')">
|
|
333
|
+
<svg width="28px" height="28px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
334
|
+
<path d="M 11 3.9 V 20.3 M 6 7.4 H 8 M 6 10.9 H 8 M 6 14.5 H 8 M 6.2 20.3 H 17.8 C 18.9 20.3 19.5 20.3 19.9 20.1 C 20.3 19.8 20.6 19.5 20.8 19 C 21 18.6 21 17.9 21 16.6 V 7.7 C 21 6.4 21 5.7 20.8 5.2 C 20.6 4.7 20.3 4.4 19.9 4.1 C 19.5 3.9 18.9 3.9 17.8 3.9 H 6.2 C 5.1 3.9 4.5 3.9 4.1 4.1 C 3.7 4.4 3.4 4.7 3.2 5.2 C 3 5.7 3 6.4 3 7.7 V 16.6 C 3 17.9 3 18.6 3.2 19 C 3.4 19.5 3.7 19.8 4.1 20.1 C 4.5 20.3 5.1 20.3 6.2 20.3 Z" stroke="whitesmoke" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
335
|
+
</svg>
|
|
336
|
+
</button>
|
|
337
|
+
|
|
338
|
+
<div class="panel-content">
|
|
339
|
+
|
|
340
|
+
<button class="physics-btn" id="btn_physics" >Physics: ON</button>
|
|
341
|
+
<button class="save-btn" id="btn_save_node_positions" >Save</button>
|
|
342
|
+
<button class="reset-btn" id="btn_reset_preferences" >Reset</button>
|
|
343
|
+
|
|
344
|
+
<span id="text_gravitationalConstant" style="
|
|
345
|
+
opacity: 0.9;
|
|
346
|
+
top: 0px;
|
|
347
|
+
left: 0px;
|
|
348
|
+
position: relative;
|
|
349
|
+
font-size: 16px;
|
|
350
|
+
font-weight: bold;
|
|
351
|
+
color: #4CAF50;">
|
|
352
|
+
Gravitational Constant
|
|
353
|
+
</span>
|
|
354
|
+
<input id="slider_gravitationalConstant"
|
|
355
|
+
type="range"
|
|
356
|
+
min="-5000"
|
|
357
|
+
max="1100"
|
|
358
|
+
style="
|
|
359
|
+
color: gray;
|
|
360
|
+
opacity: 0.5;
|
|
361
|
+
width: 200px;">
|
|
362
|
+
</input>
|
|
363
|
+
|
|
364
|
+
<span id="text_centralGravity" style="
|
|
365
|
+
opacity: 0.9;
|
|
366
|
+
top: 0px;
|
|
367
|
+
left: 0px;
|
|
368
|
+
position: relative;
|
|
369
|
+
font-size: 16px;
|
|
370
|
+
font-weight: bold;
|
|
371
|
+
color: #4CAF50;">
|
|
372
|
+
CentralGravity
|
|
373
|
+
</span>
|
|
374
|
+
<input id="slider_centralGravity"
|
|
375
|
+
type="range"
|
|
376
|
+
min="0"
|
|
377
|
+
max="100"
|
|
378
|
+
style="
|
|
379
|
+
opacity: 0.5;
|
|
380
|
+
width: 200px;">
|
|
381
|
+
</input>
|
|
382
|
+
|
|
383
|
+
<span id="text_springConstant" style="
|
|
384
|
+
opacity: 0.9;
|
|
385
|
+
top: 0px;
|
|
386
|
+
left: 0px;
|
|
387
|
+
position: relative;
|
|
388
|
+
font-size: 16px;
|
|
389
|
+
font-weight: bold;
|
|
390
|
+
color: #4CAF50;">
|
|
391
|
+
Spring Constant
|
|
392
|
+
</span>
|
|
393
|
+
<input id="slider_springConstant"
|
|
394
|
+
type="range"
|
|
395
|
+
min="0"
|
|
396
|
+
max="100"
|
|
397
|
+
style="
|
|
398
|
+
opacity: 0.5;
|
|
399
|
+
width: 200px;">
|
|
400
|
+
</input>
|
|
401
|
+
|
|
402
|
+
<span id="text_damping" style="
|
|
403
|
+
opacity: 0.9;
|
|
404
|
+
top: 0px;
|
|
405
|
+
left: 0px;
|
|
406
|
+
position: relative;
|
|
407
|
+
font-size: 16px;
|
|
408
|
+
font-weight: bold;
|
|
409
|
+
color: #4CAF50;">
|
|
410
|
+
Damping
|
|
411
|
+
</span>
|
|
412
|
+
<input id="slider_damping"
|
|
413
|
+
type="range"
|
|
414
|
+
min="0"
|
|
415
|
+
max="50"
|
|
416
|
+
style="
|
|
417
|
+
opacity: 0.5;
|
|
418
|
+
width: 200px;">
|
|
419
|
+
</input>
|
|
420
|
+
|
|
421
|
+
<span id="text_fontSize" style="
|
|
422
|
+
opacity: 0.9;
|
|
423
|
+
top: 0px;
|
|
424
|
+
left: 0px;
|
|
425
|
+
position: relative;
|
|
426
|
+
font-size: 16px;
|
|
427
|
+
font-weight: bold;
|
|
428
|
+
color: #4CAF50;">
|
|
429
|
+
Font Size
|
|
430
|
+
</span>
|
|
431
|
+
<input id="slider_fontSize"
|
|
432
|
+
type="range"
|
|
433
|
+
min="30"
|
|
434
|
+
max="200"
|
|
435
|
+
style="
|
|
436
|
+
opacity: 0.5;
|
|
437
|
+
width: 200px;">
|
|
438
|
+
</input>
|
|
439
|
+
|
|
440
|
+
<span id="text_nodeSize" style="
|
|
441
|
+
opacity: 0.9;
|
|
442
|
+
top: 0px;
|
|
443
|
+
left: 0px;
|
|
444
|
+
position: relative;
|
|
445
|
+
font-size: 16px;
|
|
446
|
+
font-weight: bold;
|
|
447
|
+
color: #4CAF50;">
|
|
448
|
+
Node Size
|
|
449
|
+
</span>
|
|
450
|
+
<input id="slider_nodeSize"
|
|
451
|
+
type="range"
|
|
452
|
+
min="1"
|
|
453
|
+
max="100"
|
|
454
|
+
style="
|
|
455
|
+
opacity: 0.5;
|
|
456
|
+
width: 200px;">
|
|
457
|
+
</input>
|
|
458
|
+
|
|
459
|
+
<span id="text_edgeLength" style="
|
|
460
|
+
opacity: 0.9;
|
|
461
|
+
top: 0px;
|
|
462
|
+
left: 0px;
|
|
463
|
+
position: relative;
|
|
464
|
+
font-size: 16px;
|
|
465
|
+
font-weight: bold;
|
|
466
|
+
color: #4CAF50;">
|
|
467
|
+
Edge Length
|
|
468
|
+
</span>
|
|
469
|
+
<input id="slider_edgeLength"
|
|
470
|
+
type="range"
|
|
471
|
+
min="1"
|
|
472
|
+
max="100"
|
|
473
|
+
style="
|
|
474
|
+
opacity: 0.5;
|
|
475
|
+
width: 200px;">
|
|
476
|
+
</input>
|
|
477
|
+
|
|
478
|
+
|
|
479
|
+
<span id="text_edgeWidth" style="
|
|
480
|
+
opacity: 0.9;
|
|
481
|
+
top: 0px;
|
|
482
|
+
left: 0px;
|
|
483
|
+
position: relative;
|
|
484
|
+
font-size: 16px;
|
|
485
|
+
font-weight: bold;
|
|
486
|
+
color: #4CAF50;">
|
|
487
|
+
Edge Width
|
|
488
|
+
</span>
|
|
489
|
+
<input id="slider_edgeWidth"
|
|
490
|
+
type="range"
|
|
491
|
+
min="1"
|
|
492
|
+
max="100"
|
|
493
|
+
style="
|
|
494
|
+
opacity: 0.5;
|
|
495
|
+
width: 200px;">
|
|
496
|
+
</input>
|
|
497
|
+
|
|
498
|
+
</div>
|
|
499
|
+
</div>
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
<div id="mynetwork" class="card-body"></div>
|
|
503
|
+
</div>
|
|
504
|
+
|
|
505
|
+
|
|
506
|
+
{% if conf %}
|
|
507
|
+
<div id="config"></div>
|
|
508
|
+
{% endif %}
|
|
509
|
+
|
|
510
|
+
<script>
|
|
511
|
+
function togglePanel(panelId) {
|
|
512
|
+
const panel = document.getElementById(panelId);
|
|
513
|
+
panel.classList.toggle('collapsed');
|
|
514
|
+
|
|
515
|
+
//// Update button text based on panel state
|
|
516
|
+
// const button = panel.querySelector('.collapse-btn');
|
|
517
|
+
// if (panelId === 'leftPanel') {
|
|
518
|
+
// button.image = "./_sources/svgs/sidebar.svg";
|
|
519
|
+
// // button.textContent = panel.classList.contains('collapsed') ? '' : '';
|
|
520
|
+
// } else {
|
|
521
|
+
// button.image = "./_sources/svgs/sidebar.svg";
|
|
522
|
+
// // button.textContent = panel.classList.contains('collapsed') ? '' : '';
|
|
523
|
+
// }
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
togglePanel('leftPanel');
|
|
527
|
+
</script>
|
|
528
|
+
|
|
529
|
+
<script type="text/javascript">
|
|
530
|
+
|
|
531
|
+
// initialize global variables.
|
|
532
|
+
var edges;
|
|
533
|
+
var nodes;
|
|
534
|
+
var allNodes;
|
|
535
|
+
var allEdges;
|
|
536
|
+
var nodeColors;
|
|
537
|
+
var originalNodes;
|
|
538
|
+
var network;
|
|
539
|
+
var container;
|
|
540
|
+
var options, data;
|
|
541
|
+
var filter = {
|
|
542
|
+
item : '',
|
|
543
|
+
property : '',
|
|
544
|
+
value : []
|
|
545
|
+
};
|
|
546
|
+
|
|
547
|
+
{% if select_menu %}
|
|
548
|
+
new TomSelect("#select-node",{
|
|
549
|
+
create: false,
|
|
550
|
+
sortField: {
|
|
551
|
+
field: "text",
|
|
552
|
+
direction: "asc"
|
|
553
|
+
}
|
|
554
|
+
});
|
|
555
|
+
{% endif %}
|
|
556
|
+
|
|
557
|
+
{% if filter_menu %}
|
|
558
|
+
// explicitly using onItemAdd and this function as we need to save multiple values
|
|
559
|
+
let updateValueFilter = function() {
|
|
560
|
+
return function () {
|
|
561
|
+
filter['value'].push(arguments[0])
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
let valueControl = new TomSelect("#select-value",{
|
|
566
|
+
maxItems: null,
|
|
567
|
+
valueField: 'id',
|
|
568
|
+
labelField: 'title',
|
|
569
|
+
searchField: 'title',
|
|
570
|
+
create: false,
|
|
571
|
+
sortField: {
|
|
572
|
+
field: "text",
|
|
573
|
+
direction: "asc"
|
|
574
|
+
},
|
|
575
|
+
onItemAdd: updateValueFilter()
|
|
576
|
+
});
|
|
577
|
+
|
|
578
|
+
let addValues = function() {
|
|
579
|
+
return function () {
|
|
580
|
+
// clear the current value options and add the selected attribute values
|
|
581
|
+
// tom-select handles duplicates
|
|
582
|
+
let selectedProperty = arguments[0];
|
|
583
|
+
valueControl.clear();
|
|
584
|
+
valueControl.clearOptions();
|
|
585
|
+
filter['value'] = []
|
|
586
|
+
if (filter['item'] === 'node') {
|
|
587
|
+
for (let each in allNodes) {
|
|
588
|
+
valueControl.addOption({
|
|
589
|
+
id:allNodes[each][selectedProperty],
|
|
590
|
+
title:allNodes[each][selectedProperty]
|
|
591
|
+
})
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
else if (filter['item'] === 'edge') {
|
|
595
|
+
for (let each in allEdges) {
|
|
596
|
+
valueControl.addOption({
|
|
597
|
+
id:allEdges[each][selectedProperty],
|
|
598
|
+
title:allEdges[each][selectedProperty]
|
|
599
|
+
})
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
};
|
|
604
|
+
|
|
605
|
+
let propControl = new TomSelect("#select-property",{
|
|
606
|
+
valueField: 'id',
|
|
607
|
+
labelField: 'title',
|
|
608
|
+
searchField: 'title',
|
|
609
|
+
create: false,
|
|
610
|
+
sortField: {
|
|
611
|
+
field: "text",
|
|
612
|
+
direction: "asc"
|
|
613
|
+
},
|
|
614
|
+
onItemAdd: addValues()
|
|
615
|
+
});
|
|
616
|
+
|
|
617
|
+
let addProperties = function() {
|
|
618
|
+
return function () {
|
|
619
|
+
// loops through the selected network item and adds the attributes to dropdown
|
|
620
|
+
// tom-select handles duplicates
|
|
621
|
+
clearFilter(false)
|
|
622
|
+
if (arguments[0] === 'edge') {
|
|
623
|
+
for (let each in allEdges) {
|
|
624
|
+
if (allEdges.hasOwnProperty(each)) {
|
|
625
|
+
for (let eachProp in allEdges[each]) {
|
|
626
|
+
if (allEdges[each].hasOwnProperty(eachProp)) {
|
|
627
|
+
propControl.addOption({id: eachProp, title: eachProp})
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
else if (arguments[0] === 'node') {
|
|
634
|
+
for (let each in allNodes) {
|
|
635
|
+
if (allNodes.hasOwnProperty(each)) {
|
|
636
|
+
for (let eachProp in allNodes[each]) {
|
|
637
|
+
if (allNodes[each].hasOwnProperty(eachProp)
|
|
638
|
+
&& (eachProp !== 'hidden' && eachProp !== 'savedLabel'
|
|
639
|
+
&& eachProp !== 'hiddenLabel')) {
|
|
640
|
+
propControl.addOption({id: eachProp, title: eachProp})
|
|
641
|
+
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
};
|
|
649
|
+
|
|
650
|
+
let itemControl = new TomSelect("#select-item",{
|
|
651
|
+
create: false,
|
|
652
|
+
sortField:{
|
|
653
|
+
field: "text",
|
|
654
|
+
direction: "asc"
|
|
655
|
+
},
|
|
656
|
+
onItemAdd: addProperties()
|
|
657
|
+
});
|
|
658
|
+
|
|
659
|
+
function clearFilter(reset) {
|
|
660
|
+
// utility function to clear all the selected filter options
|
|
661
|
+
// if reset is set to true, the existing filter will be removed
|
|
662
|
+
// else, only the dropdown options are cleared
|
|
663
|
+
propControl.clear();
|
|
664
|
+
propControl.clearOptions();
|
|
665
|
+
valueControl.clear();
|
|
666
|
+
valueControl.clearOptions();
|
|
667
|
+
filter = {
|
|
668
|
+
item : '',
|
|
669
|
+
property : '',
|
|
670
|
+
value : []
|
|
671
|
+
}
|
|
672
|
+
if (reset) {
|
|
673
|
+
itemControl.clear();
|
|
674
|
+
filterHighlight({nodes: []})
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
function updateFilter(value, key) {
|
|
679
|
+
// key could be 'item' or 'property' and value is as selected in dropdown
|
|
680
|
+
filter[key] = value
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
{% endif %}
|
|
684
|
+
|
|
685
|
+
// This method is responsible for drawing the graph, returns the drawn network
|
|
686
|
+
function drawGraph() {
|
|
687
|
+
var container = document.getElementById('mynetwork');
|
|
688
|
+
|
|
689
|
+
{% if use_DOT %}
|
|
690
|
+
|
|
691
|
+
var DOTstring = "{{dot_lang|safe}}";
|
|
692
|
+
var parsedData = vis.network.convertDot(DOTstring);
|
|
693
|
+
|
|
694
|
+
data = {
|
|
695
|
+
nodes: parsedData.nodes,
|
|
696
|
+
edges: parsedData.edges
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
var options = parsedData.options;
|
|
700
|
+
options.nodes = {
|
|
701
|
+
shape: "dot"
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
{% else %}
|
|
705
|
+
|
|
706
|
+
// parsing and collecting nodes and edges from the python
|
|
707
|
+
nodes = new vis.DataSet({{nodes|tojson}});
|
|
708
|
+
edges = new vis.DataSet({{edges|tojson}});
|
|
709
|
+
|
|
710
|
+
nodeColors = {};
|
|
711
|
+
allNodes = nodes.get({ returnType: "Object" });
|
|
712
|
+
for (nodeId in allNodes) {
|
|
713
|
+
nodeColors[nodeId] = allNodes[nodeId].color;
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
// load node positions
|
|
717
|
+
var node_positions = {};
|
|
718
|
+
function saveNodePositions(){
|
|
719
|
+
localStorage.setItem('node_positions', JSON.stringify(node_positions));
|
|
720
|
+
}
|
|
721
|
+
const savedPositions = localStorage.getItem('node_positions');
|
|
722
|
+
if (savedPositions) {
|
|
723
|
+
const positions = JSON.parse(savedPositions);
|
|
724
|
+
// Update each node with its saved po
|
|
725
|
+
Object.keys(positions).forEach(nodeId => {
|
|
726
|
+
if (nodeId in allNodes){
|
|
727
|
+
allNodes[nodeId].x = positions[nodeId].x;
|
|
728
|
+
allNodes[nodeId].y = positions[nodeId].y;
|
|
729
|
+
}
|
|
730
|
+
});
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
allEdges = edges.get({ returnType: "Object" });
|
|
734
|
+
// adding nodes and edges to the graph
|
|
735
|
+
data = {nodes: nodes, edges: edges};
|
|
736
|
+
|
|
737
|
+
var options = {{options|safe}};
|
|
738
|
+
|
|
739
|
+
{% endif %}
|
|
740
|
+
|
|
741
|
+
|
|
742
|
+
{% if conf %}
|
|
743
|
+
// if this network requires displaying the configure window,
|
|
744
|
+
// put it in its div
|
|
745
|
+
options.configure["container"] = document.getElementById("config");
|
|
746
|
+
{% endif %}
|
|
747
|
+
|
|
748
|
+
|
|
749
|
+
var viewState = {};
|
|
750
|
+
|
|
751
|
+
var default_preferences = {
|
|
752
|
+
"centralGravity": 8,
|
|
753
|
+
"damping": 20,
|
|
754
|
+
"edgeLength": 4,
|
|
755
|
+
"edgeWidth": 6,
|
|
756
|
+
"fontSize": 43,
|
|
757
|
+
"gravitationalConstant": 437,
|
|
758
|
+
"nodeSize": 11,
|
|
759
|
+
"physics": true,
|
|
760
|
+
"springConstant": 5,
|
|
761
|
+
};
|
|
762
|
+
|
|
763
|
+
var preferences = {
|
|
764
|
+
"centralGravity": 8,
|
|
765
|
+
"damping": 20,
|
|
766
|
+
"edgeLength": 4,
|
|
767
|
+
"edgeWidth": 6,
|
|
768
|
+
"fontSize": 43,
|
|
769
|
+
"gravitationalConstant": 437,
|
|
770
|
+
"nodeSize": 11,
|
|
771
|
+
"physics": true,
|
|
772
|
+
"springConstant": 5,
|
|
773
|
+
};
|
|
774
|
+
|
|
775
|
+
storedPreferences = localStorage.getItem('preferences');
|
|
776
|
+
if (storedPreferences !== null) {
|
|
777
|
+
var savedPreferences = JSON.parse(storedPreferences);
|
|
778
|
+
preferences = savedPreferences;
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
const left_panel = document.getElementById('leftPanel');
|
|
782
|
+
const left_panel_content = left_panel.querySelector('.panel-content');
|
|
783
|
+
|
|
784
|
+
network = new vis.Network(container, data, options);
|
|
785
|
+
network.on("click", function(params) {
|
|
786
|
+
if (params.nodes.length > 0) {
|
|
787
|
+
var node = this.body.data.nodes.get(params.nodes[0]);
|
|
788
|
+
if (node.url) {
|
|
789
|
+
if (params.event.srcEvent.ctrlKey) {
|
|
790
|
+
window.open(node.url, '_blank');
|
|
791
|
+
}else {
|
|
792
|
+
window.location.href = node.url;
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
toggleSaveNodePositions()
|
|
797
|
+
});
|
|
798
|
+
|
|
799
|
+
function loadViewState(){
|
|
800
|
+
var savedState = JSON.parse(localStorage.getItem('networkViewState'));
|
|
801
|
+
if (savedState) {
|
|
802
|
+
network.moveTo({
|
|
803
|
+
position: savedState.position,
|
|
804
|
+
scale: savedState.scale
|
|
805
|
+
});
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
function saveViewState(){
|
|
810
|
+
var viewPosition = network.getViewPosition();
|
|
811
|
+
var scale = network.getScale();
|
|
812
|
+
var viewState = {
|
|
813
|
+
position: viewPosition,
|
|
814
|
+
scale: scale
|
|
815
|
+
};
|
|
816
|
+
localStorage.setItem('networkViewState', JSON.stringify(viewState));
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
function savePreferences(){
|
|
820
|
+
localStorage.setItem('preferences', JSON.stringify(preferences));
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
function loadPhysics(){
|
|
824
|
+
var btn = document.getElementById('btn_physics');
|
|
825
|
+
if (preferences.physics == true) {
|
|
826
|
+
network.setOptions( { physics: true } );
|
|
827
|
+
btn.innerHTML = 'Physics: ON';
|
|
828
|
+
} else {
|
|
829
|
+
network.setOptions( { physics: false } );
|
|
830
|
+
btn.innerHTML = 'Physics: OFF';
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
// Add Button and Slider to Control the Physics
|
|
835
|
+
function togglePhysics() {
|
|
836
|
+
var btn = document.getElementById('btn_physics');
|
|
837
|
+
var physics = !network.physics.options.enabled;
|
|
838
|
+
network.physics.enabled = physics;
|
|
839
|
+
|
|
840
|
+
if (physics) {
|
|
841
|
+
preferences.physics = true;
|
|
842
|
+
network.setOptions( { physics: true } );
|
|
843
|
+
btn.innerHTML = 'Physics: ON';
|
|
844
|
+
} else {
|
|
845
|
+
preferences.physics = false;
|
|
846
|
+
network.setOptions( { physics: false } );
|
|
847
|
+
btn.innerHTML = 'Physics: OFF';
|
|
848
|
+
}
|
|
849
|
+
savePreferences();
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
// Physics
|
|
853
|
+
const btn_physics = document.getElementById('btn_physics');
|
|
854
|
+
btn_physics.onclick = togglePhysics;
|
|
855
|
+
|
|
856
|
+
// Save as Startup
|
|
857
|
+
const btn_save_node_positions = document.getElementById('btn_save_node_positions');
|
|
858
|
+
btn_save_node_positions.onclick = toggleSaveNodePositions;
|
|
859
|
+
|
|
860
|
+
function toggleSaveNodePositions() {
|
|
861
|
+
node_positions = network.getPositions();
|
|
862
|
+
saveNodePositions();
|
|
863
|
+
savePreferences();
|
|
864
|
+
saveViewState();
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
// Reset
|
|
868
|
+
const btn_reset_preferences = document.getElementById('btn_reset_preferences');
|
|
869
|
+
btn_reset_preferences.onclick = resetPreferences;
|
|
870
|
+
|
|
871
|
+
// gravitationalConstant
|
|
872
|
+
const slider_gravitationalConstant = document.getElementById('slider_gravitationalConstant');
|
|
873
|
+
slider_gravitationalConstant.value = preferences.gravitationalConstant;
|
|
874
|
+
slider_gravitationalConstant.oninput = on_slider_gravitationalConstant_input;
|
|
875
|
+
|
|
876
|
+
function on_slider_gravitationalConstant_input() {
|
|
877
|
+
var gravitationalConstant = document.getElementById('slider_gravitationalConstant').value;
|
|
878
|
+
preferences.gravitationalConstant = gravitationalConstant;
|
|
879
|
+
value = gravitationalConstant -1100;
|
|
880
|
+
network.setOptions( { physics: {"forceAtlas2Based": {gravitationalConstant: value} }} );
|
|
881
|
+
savePreferences();
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
// centralGravity
|
|
885
|
+
const slider_centralGravity = document.getElementById('slider_centralGravity');
|
|
886
|
+
slider_centralGravity.value = preferences.centralGravity;
|
|
887
|
+
slider_centralGravity.oninput = on_slider_centralGravity_input;
|
|
888
|
+
|
|
889
|
+
function on_slider_centralGravity_input() {
|
|
890
|
+
var centralGravity = document.getElementById('slider_centralGravity').value;
|
|
891
|
+
preferences.centralGravity = centralGravity;
|
|
892
|
+
value = centralGravity * 0.001;
|
|
893
|
+
network.setOptions( { physics: {"forceAtlas2Based": {centralGravity: value} }} );
|
|
894
|
+
savePreferences();
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
// sprintConstant
|
|
898
|
+
const slider_springConstant = document.getElementById('slider_springConstant');
|
|
899
|
+
slider_springConstant.value = preferences.springConstant;
|
|
900
|
+
slider_springConstant.oninput = on_slider_springConstant_input;
|
|
901
|
+
|
|
902
|
+
function on_slider_springConstant_input() {
|
|
903
|
+
var springConstant = document.getElementById('slider_springConstant').value;
|
|
904
|
+
preferences.springConstant = springConstant;
|
|
905
|
+
value = springConstant * 0.01;
|
|
906
|
+
network.setOptions( { physics: {"forceAtlas2Based": {springConstant: value} }} );
|
|
907
|
+
savePreferences();
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
// Damping
|
|
911
|
+
const slider_damping = document.getElementById('slider_damping');
|
|
912
|
+
slider_damping.value = preferences.damping;
|
|
913
|
+
slider_damping.oninput = on_slider_damping_input;
|
|
914
|
+
|
|
915
|
+
function on_slider_damping_input() {
|
|
916
|
+
var damping = document.getElementById('slider_damping').value;
|
|
917
|
+
preferences.damping = damping;
|
|
918
|
+
value = damping * 0.01;
|
|
919
|
+
network.setOptions( { physics: {"forceAtlas2Based": {damping: value} }} );
|
|
920
|
+
savePreferences();
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
// fontSize
|
|
924
|
+
const slider_fontSize = document.getElementById('slider_fontSize');
|
|
925
|
+
slider_fontSize.value = preferences.fontSize;
|
|
926
|
+
slider_fontSize.oninput = on_slider_fontSize_input;
|
|
927
|
+
|
|
928
|
+
function on_slider_fontSize_input() {
|
|
929
|
+
var font_size = document.getElementById('slider_fontSize').value;
|
|
930
|
+
preferences.fontSize = font_size;
|
|
931
|
+
network.setOptions( { nodes: {"font": {size: parseFloat(font_size)} }} );
|
|
932
|
+
savePreferences();
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
// nodeSize
|
|
936
|
+
const slider_nodeSize = document.getElementById('slider_nodeSize');
|
|
937
|
+
slider_nodeSize.value = preferences.nodeSize;
|
|
938
|
+
slider_nodeSize.oninput = on_slider_nodeSize_input;
|
|
939
|
+
|
|
940
|
+
var nodes_backup = data.nodes.get();
|
|
941
|
+
|
|
942
|
+
function on_slider_nodeSize_input() {
|
|
943
|
+
var node_size = document.getElementById('slider_nodeSize').value;
|
|
944
|
+
preferences.nodeSize = node_size;
|
|
945
|
+
value = node_size * 0.1;
|
|
946
|
+
data.nodes.update(nodes_backup);
|
|
947
|
+
var nodes = data.nodes.get();
|
|
948
|
+
for (var i = 0; i < nodes.length; i++) {
|
|
949
|
+
mysize = nodes[i].size * value
|
|
950
|
+
nodes[i].size = mysize;
|
|
951
|
+
}
|
|
952
|
+
data.nodes.update(nodes);
|
|
953
|
+
savePreferences();
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
// edgeLength
|
|
957
|
+
const slider_edgeLength = document.getElementById('slider_edgeLength');
|
|
958
|
+
slider_edgeLength.value = preferences.edgeLength;
|
|
959
|
+
slider_edgeLength.oninput = on_slider_edge_input;
|
|
960
|
+
|
|
961
|
+
// edgeWidth
|
|
962
|
+
const slider_edgeWidth = document.getElementById('slider_edgeWidth');
|
|
963
|
+
slider_edgeWidth.value = preferences.edgeWidth;
|
|
964
|
+
slider_edgeWidth.oninput = on_slider_edge_input;
|
|
965
|
+
|
|
966
|
+
var edges_backup = data.edges.get();
|
|
967
|
+
|
|
968
|
+
function on_slider_edge_input() {
|
|
969
|
+
var edge_length = document.getElementById('slider_edgeLength').value;
|
|
970
|
+
var edge_width = document.getElementById('slider_edgeWidth').value;
|
|
971
|
+
preferences.edgeLength = edge_length;
|
|
972
|
+
preferences.edgeWidth = edge_width;
|
|
973
|
+
data.edges.update(edges_backup);
|
|
974
|
+
var edges = data.edges.get();
|
|
975
|
+
for (var i = 0; i < edges.length; i++) {
|
|
976
|
+
edges[i].length = edges[i].length * edge_length * 0.1;
|
|
977
|
+
edges[i].width = edges[i].width * edge_width * 0.1;
|
|
978
|
+
}
|
|
979
|
+
data.edges.update(edges);
|
|
980
|
+
savePreferences();
|
|
981
|
+
};
|
|
982
|
+
|
|
983
|
+
function loadPreferences(){
|
|
984
|
+
on_slider_gravitationalConstant_input();
|
|
985
|
+
on_slider_centralGravity_input();
|
|
986
|
+
on_slider_springConstant_input();
|
|
987
|
+
on_slider_damping_input();
|
|
988
|
+
on_slider_fontSize_input();
|
|
989
|
+
on_slider_nodeSize_input();
|
|
990
|
+
on_slider_edge_input();
|
|
991
|
+
loadPhysics();
|
|
992
|
+
loadViewState();
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
function resetPreferences(){
|
|
996
|
+
document.getElementById('btn_physics').value = default_preferences.physics;
|
|
997
|
+
document.getElementById('slider_gravitationalConstant').value = default_preferences.gravitationalConstant;
|
|
998
|
+
document.getElementById('slider_centralGravity').value = default_preferences.centralGravity;
|
|
999
|
+
document.getElementById('slider_springConstant').value = default_preferences.springConstant;
|
|
1000
|
+
document.getElementById('slider_damping').value = default_preferences.damping;
|
|
1001
|
+
document.getElementById('slider_fontSize').value = default_preferences.fontSize;
|
|
1002
|
+
document.getElementById('slider_nodeSize').value = default_preferences.nodeSize;
|
|
1003
|
+
document.getElementById('slider_edgeLength').value = default_preferences.edgeLength;
|
|
1004
|
+
document.getElementById('slider_edgeWidth').value = default_preferences.edgeWidth;
|
|
1005
|
+
|
|
1006
|
+
allNodes = nodes.get({ returnType: "Object" });
|
|
1007
|
+
for (nodeId in allNodes) {
|
|
1008
|
+
nodeColors[nodeId] = allNodes[nodeId].color;
|
|
1009
|
+
}
|
|
1010
|
+
data = {nodes: nodes, edges: edges};
|
|
1011
|
+
|
|
1012
|
+
network = new vis.Network(container, data, options);
|
|
1013
|
+
network.on("click", function(params) {
|
|
1014
|
+
if (params.nodes.length > 0) {
|
|
1015
|
+
var node = this.body.data.nodes.get(params.nodes[0]);
|
|
1016
|
+
if (node.url) {
|
|
1017
|
+
if (params.event.srcEvent.ctrlKey) {
|
|
1018
|
+
window.open(node.url, '_blank');
|
|
1019
|
+
}else {
|
|
1020
|
+
window.location.href = node.url;
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
toggleSaveNodePositions()
|
|
1025
|
+
});
|
|
1026
|
+
|
|
1027
|
+
viewState = {"position":{"x":122.26498687735877,"y":1344.4657619150016},"scale":0.14563667453404308}
|
|
1028
|
+
localStorage.setItem('networkViewState', JSON.stringify(viewState));
|
|
1029
|
+
network.moveTo({
|
|
1030
|
+
position: viewState.position,
|
|
1031
|
+
scale: viewState.scale
|
|
1032
|
+
});
|
|
1033
|
+
|
|
1034
|
+
// preferences.physics = true;
|
|
1035
|
+
|
|
1036
|
+
node_positions = {};
|
|
1037
|
+
saveNodePositions();
|
|
1038
|
+
|
|
1039
|
+
preferences = {
|
|
1040
|
+
"centralGravity": 8,
|
|
1041
|
+
"damping": 20,
|
|
1042
|
+
"edgeLength": 4,
|
|
1043
|
+
"edgeWidth": 6,
|
|
1044
|
+
"fontSize": 43,
|
|
1045
|
+
"gravitationalConstant": 437,
|
|
1046
|
+
"nodeSize": 11,
|
|
1047
|
+
"physics": true,
|
|
1048
|
+
"springConstant": 5,
|
|
1049
|
+
};
|
|
1050
|
+
savePreferences();
|
|
1051
|
+
|
|
1052
|
+
loadPreferences();
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
loadPreferences();
|
|
1056
|
+
|
|
1057
|
+
// seet physic on / off by dragStart dragEnd
|
|
1058
|
+
// network.on("dragStart", function(params) {
|
|
1059
|
+
// if (params.nodes.length > 0) {
|
|
1060
|
+
// network.setOptions( { physics: true } );
|
|
1061
|
+
// }
|
|
1062
|
+
// });
|
|
1063
|
+
|
|
1064
|
+
// network.on("dragEnd", function(params) {
|
|
1065
|
+
// if (params.nodes.length > 0) {
|
|
1066
|
+
|
|
1067
|
+
// network.setOptions( { physics: false } );
|
|
1068
|
+
|
|
1069
|
+
// }
|
|
1070
|
+
// });
|
|
1071
|
+
|
|
1072
|
+
// setTimeout(function() {
|
|
1073
|
+
// network.setOptions( { physics: false } );
|
|
1074
|
+
// }, 12000);
|
|
1075
|
+
|
|
1076
|
+
|
|
1077
|
+
|
|
1078
|
+
|
|
1079
|
+
{% if neighborhood_highlight %}
|
|
1080
|
+
network.on("click", neighbourhoodHighlight);
|
|
1081
|
+
{% endif %}
|
|
1082
|
+
|
|
1083
|
+
{% if select_menu %}
|
|
1084
|
+
network.on("selectNode", neighbourhoodHighlight);
|
|
1085
|
+
{% endif %}
|
|
1086
|
+
|
|
1087
|
+
{% if tooltip_link %}
|
|
1088
|
+
// make a custom popup
|
|
1089
|
+
var popup = document.createElement("div");
|
|
1090
|
+
popup.className = 'popup';
|
|
1091
|
+
popupTimeout = null;
|
|
1092
|
+
popup.addEventListener('mouseover', function () {
|
|
1093
|
+
console.log(popup)
|
|
1094
|
+
if (popupTimeout !== null) {
|
|
1095
|
+
clearTimeout(popupTimeout);
|
|
1096
|
+
popupTimeout = null;
|
|
1097
|
+
}
|
|
1098
|
+
});
|
|
1099
|
+
popup.addEventListener('mouseout', function () {
|
|
1100
|
+
if (popupTimeout === null) {
|
|
1101
|
+
hidePopup();
|
|
1102
|
+
}
|
|
1103
|
+
});
|
|
1104
|
+
container.appendChild(popup);
|
|
1105
|
+
|
|
1106
|
+
|
|
1107
|
+
// use the popup event to show
|
|
1108
|
+
network.on("showPopup", function (params) {
|
|
1109
|
+
showPopup(params);
|
|
1110
|
+
});
|
|
1111
|
+
|
|
1112
|
+
// use the hide event to hide it
|
|
1113
|
+
network.on("hidePopup", function (params) {
|
|
1114
|
+
hidePopup();
|
|
1115
|
+
});
|
|
1116
|
+
|
|
1117
|
+
// hiding the popup through css
|
|
1118
|
+
function hidePopup() {
|
|
1119
|
+
popupTimeout = setTimeout(function () { popup.style.display = 'none'; }, 500);
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
// showing the popup
|
|
1123
|
+
function showPopup(nodeId) {
|
|
1124
|
+
// get the data from the vis.DataSet
|
|
1125
|
+
var nodeData = nodes.get([nodeId]);
|
|
1126
|
+
popup.innerHTML = nodeData[0].title;
|
|
1127
|
+
|
|
1128
|
+
// get the position of the node
|
|
1129
|
+
var posCanvas = network.getPositions([nodeId])[nodeId];
|
|
1130
|
+
|
|
1131
|
+
// get the bounding box of the node
|
|
1132
|
+
var boundingBox = network.getBoundingBox(nodeId);
|
|
1133
|
+
|
|
1134
|
+
//position tooltip:
|
|
1135
|
+
posCanvas.x = posCanvas.x + 0.5 * (boundingBox.right - boundingBox.left);
|
|
1136
|
+
|
|
1137
|
+
// convert coordinates to the DOM space
|
|
1138
|
+
var posDOM = network.canvasToDOM(posCanvas);
|
|
1139
|
+
|
|
1140
|
+
// Give it an offset
|
|
1141
|
+
posDOM.x += 10;
|
|
1142
|
+
posDOM.y -= 20;
|
|
1143
|
+
|
|
1144
|
+
// show and place the tooltip.
|
|
1145
|
+
popup.style.display = 'block';
|
|
1146
|
+
popup.style.top = posDOM.y + 'px';
|
|
1147
|
+
popup.style.left = posDOM.x + 'px';
|
|
1148
|
+
}
|
|
1149
|
+
{% endif %}
|
|
1150
|
+
|
|
1151
|
+
|
|
1152
|
+
return network;
|
|
1153
|
+
|
|
1154
|
+
}
|
|
1155
|
+
drawGraph();
|
|
1156
|
+
</script>
|
|
1157
|
+
</body>
|
|
1158
|
+
</html>
|