Spaces:
Running
Running
Commit
·
8daace0
1
Parent(s):
278f515
enhanced ui
Browse files- css/style.css +72 -29
- js/main.js +70 -3
css/style.css
CHANGED
@@ -56,22 +56,24 @@ canvas#sigma_bg_1 {
|
|
56 |
display: none;
|
57 |
position: absolute;
|
58 |
height: auto;
|
59 |
-
|
60 |
-
top:
|
61 |
-
|
62 |
-
|
|
|
63 |
background-color: #fff;
|
64 |
margin: 0;
|
65 |
-
z-index:
|
66 |
-
border-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
box-shadow: -3px 0px 8px rgba(0, 0, 0, 0.15);
|
71 |
}
|
72 |
|
73 |
#attributepane .text {
|
74 |
-
|
|
|
|
|
75 |
}
|
76 |
|
77 |
#attributepane .headertext {
|
@@ -86,25 +88,31 @@ canvas#sigma_bg_1 {
|
|
86 |
}
|
87 |
|
88 |
#attributepane .returntext {
|
89 |
-
color: #
|
90 |
cursor: pointer;
|
91 |
-
margin
|
92 |
-
padding:
|
93 |
-
border-top: 1px solid #ddd;
|
94 |
font-weight: bold;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
95 |
}
|
96 |
|
97 |
#attributepane .returntext:hover {
|
98 |
-
|
99 |
}
|
100 |
|
101 |
.nodeattributes {
|
102 |
-
padding:
|
103 |
}
|
104 |
|
105 |
.nodeattributes .name {
|
106 |
-
font-size: 16px;
|
107 |
font-weight: bold;
|
|
|
108 |
margin-bottom: 10px;
|
109 |
}
|
110 |
|
@@ -147,11 +155,7 @@ canvas#sigma_bg_1 {
|
|
147 |
}
|
148 |
|
149 |
#attributepane .nodeattributes {
|
150 |
-
|
151 |
-
height: 85%;
|
152 |
-
overflow-y: auto;
|
153 |
-
overflow-x: hidden;
|
154 |
-
border-bottom: 1px solid #999;
|
155 |
}
|
156 |
|
157 |
#attributepane .name {
|
@@ -218,14 +222,15 @@ canvas#sigma_bg_1 {
|
|
218 |
|
219 |
#mainpanel {
|
220 |
position: absolute;
|
221 |
-
top:
|
|
|
222 |
left: 10px;
|
223 |
width: 250px;
|
224 |
padding: 10px;
|
225 |
background: rgba(255, 255, 255, 0.9);
|
226 |
box-shadow: 0 1px 3px rgba(0,0,0,0.2);
|
227 |
z-index: 20;
|
228 |
-
max-height:
|
229 |
overflow-y: auto;
|
230 |
}
|
231 |
|
@@ -412,9 +417,10 @@ canvas#sigma_bg_1 {
|
|
412 |
#zoom {
|
413 |
position: absolute;
|
414 |
bottom: 40px;
|
415 |
-
|
|
|
416 |
z-index: 20;
|
417 |
-
background: rgba(255, 255, 255, 0.
|
418 |
border: 1px solid #ccc;
|
419 |
border-radius: 3px;
|
420 |
padding: 5px;
|
@@ -506,18 +512,21 @@ canvas#sigma_bg_1 {
|
|
506 |
#attributepane .text .returntext {
|
507 |
color: #ffffff;
|
508 |
cursor: pointer;
|
509 |
-
margin:
|
510 |
padding: 12px;
|
511 |
font-weight: bold;
|
512 |
font-size: 14px;
|
513 |
text-align: center;
|
514 |
background-color: #007AFF;
|
515 |
-
border-radius: 4px;
|
|
|
516 |
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
|
|
|
517 |
}
|
518 |
|
519 |
#attributepane .text .returntext:hover {
|
520 |
background-color: #0056b3;
|
|
|
521 |
}
|
522 |
|
523 |
#attributepane .text .nodeattributes .nodetype {
|
@@ -525,4 +534,38 @@ canvas#sigma_bg_1 {
|
|
525 |
margin-bottom: 12px;
|
526 |
font-size: 13px;
|
527 |
display: block;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
528 |
}
|
|
|
56 |
display: none;
|
57 |
position: absolute;
|
58 |
height: auto;
|
59 |
+
max-height: 80vh;
|
60 |
+
top: 50%;
|
61 |
+
transform: translateY(-50%);
|
62 |
+
right: 20px;
|
63 |
+
width: 270px;
|
64 |
background-color: #fff;
|
65 |
margin: 0;
|
66 |
+
z-index: 20;
|
67 |
+
border-radius: 4px;
|
68 |
+
box-shadow: 0 2px 6px rgba(0,0,0,0.3);
|
69 |
+
overflow-y: auto;
|
70 |
+
overflow-x: hidden;
|
|
|
71 |
}
|
72 |
|
73 |
#attributepane .text {
|
74 |
+
height: 100%;
|
75 |
+
width: 100%;
|
76 |
+
padding: 0;
|
77 |
}
|
78 |
|
79 |
#attributepane .headertext {
|
|
|
88 |
}
|
89 |
|
90 |
#attributepane .returntext {
|
91 |
+
color: #ffffff;
|
92 |
cursor: pointer;
|
93 |
+
margin: 0;
|
94 |
+
padding: 12px;
|
|
|
95 |
font-weight: bold;
|
96 |
+
font-size: 14px;
|
97 |
+
text-align: center;
|
98 |
+
background-color: #007AFF;
|
99 |
+
border-top-left-radius: 4px;
|
100 |
+
border-top-right-radius: 4px;
|
101 |
+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
|
102 |
+
border-bottom: none;
|
103 |
}
|
104 |
|
105 |
#attributepane .returntext:hover {
|
106 |
+
background-color: #0056b3;
|
107 |
}
|
108 |
|
109 |
.nodeattributes {
|
110 |
+
padding: 15px;
|
111 |
}
|
112 |
|
113 |
.nodeattributes .name {
|
|
|
114 |
font-weight: bold;
|
115 |
+
font-size: 16px;
|
116 |
margin-bottom: 10px;
|
117 |
}
|
118 |
|
|
|
155 |
}
|
156 |
|
157 |
#attributepane .nodeattributes {
|
158 |
+
padding: 15px;
|
|
|
|
|
|
|
|
|
159 |
}
|
160 |
|
161 |
#attributepane .name {
|
|
|
222 |
|
223 |
#mainpanel {
|
224 |
position: absolute;
|
225 |
+
top: 50%;
|
226 |
+
transform: translateY(-50%);
|
227 |
left: 10px;
|
228 |
width: 250px;
|
229 |
padding: 10px;
|
230 |
background: rgba(255, 255, 255, 0.9);
|
231 |
box-shadow: 0 1px 3px rgba(0,0,0,0.2);
|
232 |
z-index: 20;
|
233 |
+
max-height: 80vh;
|
234 |
overflow-y: auto;
|
235 |
}
|
236 |
|
|
|
417 |
#zoom {
|
418 |
position: absolute;
|
419 |
bottom: 40px;
|
420 |
+
left: 50%;
|
421 |
+
transform: translateX(-50%);
|
422 |
z-index: 20;
|
423 |
+
background: rgba(255, 255, 255, 0.5);
|
424 |
border: 1px solid #ccc;
|
425 |
border-radius: 3px;
|
426 |
padding: 5px;
|
|
|
512 |
#attributepane .text .returntext {
|
513 |
color: #ffffff;
|
514 |
cursor: pointer;
|
515 |
+
margin: 0;
|
516 |
padding: 12px;
|
517 |
font-weight: bold;
|
518 |
font-size: 14px;
|
519 |
text-align: center;
|
520 |
background-color: #007AFF;
|
521 |
+
border-top-left-radius: 4px;
|
522 |
+
border-top-right-radius: 4px;
|
523 |
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
|
524 |
+
border-bottom: none;
|
525 |
}
|
526 |
|
527 |
#attributepane .text .returntext:hover {
|
528 |
background-color: #0056b3;
|
529 |
+
color: #ffffff;
|
530 |
}
|
531 |
|
532 |
#attributepane .text .nodeattributes .nodetype {
|
|
|
534 |
margin-bottom: 12px;
|
535 |
font-size: 13px;
|
536 |
display: block;
|
537 |
+
}
|
538 |
+
|
539 |
+
#attributepane .text .nodeattributes .p {
|
540 |
+
font-weight: bold;
|
541 |
+
font-size: 14px;
|
542 |
+
margin: 15px 0 5px 0;
|
543 |
+
}
|
544 |
+
|
545 |
+
#attributepane .text .nodeattributes .link {
|
546 |
+
margin-bottom: 5px;
|
547 |
+
}
|
548 |
+
|
549 |
+
#attributepane .text .nodeattributes .link ul {
|
550 |
+
margin: 0;
|
551 |
+
padding: 0;
|
552 |
+
list-style: none;
|
553 |
+
}
|
554 |
+
|
555 |
+
#attributepane .text .nodeattributes .link ul li {
|
556 |
+
padding: 4px 0;
|
557 |
+
border-bottom: 1px solid #eee;
|
558 |
+
}
|
559 |
+
|
560 |
+
#attributepane .text .nodeattributes .link ul li a {
|
561 |
+
color: #007AFF;
|
562 |
+
text-decoration: none;
|
563 |
+
display: block;
|
564 |
+
padding: 2px 0;
|
565 |
+
font-size: 13px;
|
566 |
+
}
|
567 |
+
|
568 |
+
#attributepane .text .nodeattributes .link ul li a:hover {
|
569 |
+
color: #0056b3;
|
570 |
+
text-decoration: underline;
|
571 |
}
|
js/main.js
CHANGED
@@ -190,7 +190,7 @@ function initializeGraph(data) {
|
|
190 |
|
191 |
// Configure drawing properties
|
192 |
sigmaInstance.drawingProperties({
|
193 |
-
labelThreshold:
|
194 |
defaultLabelColor: config.sigma?.drawingProperties?.defaultLabelColor || '#000',
|
195 |
defaultLabelSize: config.sigma?.drawingProperties?.defaultLabelSize || 14,
|
196 |
defaultEdgeType: config.sigma?.drawingProperties?.defaultEdgeType || 'curve',
|
@@ -307,6 +307,58 @@ function bindEvents() {
|
|
307 |
}
|
308 |
});
|
309 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
310 |
// When stage is clicked, close the attribute pane
|
311 |
document.getElementById('sigma-canvas').addEventListener('click', function(evt) {
|
312 |
// Only process if we didn't click on a node (checked by looking at sigma's settings)
|
@@ -366,11 +418,19 @@ function nodeActive(nodeId) {
|
|
366 |
n.attr = n.attr || {};
|
367 |
n.attr.originalColor = n.color;
|
368 |
|
|
|
|
|
|
|
369 |
if (n.id === nodeId) {
|
370 |
// Make selected node slightly larger based on config
|
371 |
n.attr.originalSize = n.size;
|
372 |
const sizeFactor = config.highlighting?.selectedNodeSizeFactor ?? 1.5;
|
373 |
n.size = n.size * sizeFactor;
|
|
|
|
|
|
|
|
|
|
|
374 |
} else if (!neighbors[n.id]) {
|
375 |
// For non-neighbor nodes, we use a custom attribute to track they should be dimmed
|
376 |
// (Sigma v0.1 doesn't support opacity directly)
|
@@ -379,6 +439,8 @@ function nodeActive(nodeId) {
|
|
379 |
var rgb = getRGBColor(n.color);
|
380 |
const opacity = config.highlighting?.nodeOpacity ?? 0.2;
|
381 |
n.color = 'rgba(' + rgb.r + ',' + rgb.g + ',' + rgb.b + ',' + opacity + ')';
|
|
|
|
|
382 |
}
|
383 |
});
|
384 |
|
@@ -574,17 +636,22 @@ function nodeNormal() {
|
|
574 |
n.attr = n.attr || {};
|
575 |
|
576 |
// Restore original color
|
577 |
-
if (n.attr.originalColor) {
|
578 |
n.color = n.attr.originalColor;
|
579 |
delete n.attr.originalColor;
|
580 |
}
|
581 |
|
582 |
// Restore original size if it was modified
|
583 |
-
if (n.attr.originalSize) {
|
584 |
n.size = n.attr.originalSize;
|
585 |
delete n.attr.originalSize;
|
586 |
}
|
587 |
|
|
|
|
|
|
|
|
|
|
|
588 |
// Remove dimmed flag
|
589 |
delete n.attr.dimmed;
|
590 |
});
|
|
|
190 |
|
191 |
// Configure drawing properties
|
192 |
sigmaInstance.drawingProperties({
|
193 |
+
labelThreshold: 3000, // Set to a high value to hide all labels by default
|
194 |
defaultLabelColor: config.sigma?.drawingProperties?.defaultLabelColor || '#000',
|
195 |
defaultLabelSize: config.sigma?.drawingProperties?.defaultLabelSize || 14,
|
196 |
defaultEdgeType: config.sigma?.drawingProperties?.defaultEdgeType || 'curve',
|
|
|
307 |
}
|
308 |
});
|
309 |
|
310 |
+
// Show label when hovering over a node
|
311 |
+
sigmaInstance.bind('overnodes', function(event) {
|
312 |
+
if (event.content && event.content.length > 0) {
|
313 |
+
var nodeId = event.content[0];
|
314 |
+
|
315 |
+
sigmaInstance.iterNodes(function(n) {
|
316 |
+
if (n.id === nodeId) {
|
317 |
+
// Allow hover label to appear for any node being hovered over
|
318 |
+
n.forceLabel = true;
|
319 |
+
|
320 |
+
// But in detail view, don't allow this to override the selected node's neighbors
|
321 |
+
if (sigmaInstance.detail && selectedNode && n.id !== selectedNode.id) {
|
322 |
+
// Store the hover state to know we need to reset this node specifically
|
323 |
+
n.attr = n.attr || {};
|
324 |
+
n.attr.isHovered = true;
|
325 |
+
}
|
326 |
+
}
|
327 |
+
});
|
328 |
+
|
329 |
+
sigmaInstance.draw(2, 2, 2, 2);
|
330 |
+
}
|
331 |
+
});
|
332 |
+
|
333 |
+
// Hide label when mouse leaves the node
|
334 |
+
sigmaInstance.bind('outnodes', function(event) {
|
335 |
+
// Handle nodes that were being hovered over
|
336 |
+
if (event.content && event.content.length > 0) {
|
337 |
+
var nodeId = event.content[0];
|
338 |
+
|
339 |
+
sigmaInstance.iterNodes(function(n) {
|
340 |
+
if (n.id === nodeId) {
|
341 |
+
// Remove hover flag
|
342 |
+
if (n.attr && n.attr.isHovered) {
|
343 |
+
delete n.attr.isHovered;
|
344 |
+
}
|
345 |
+
|
346 |
+
// In detail view, only the selected node should keep its label
|
347 |
+
if (sigmaInstance.detail) {
|
348 |
+
if (selectedNode && n.id !== selectedNode.id) {
|
349 |
+
n.forceLabel = false;
|
350 |
+
}
|
351 |
+
} else {
|
352 |
+
// In normal view, always hide the label when hover ends
|
353 |
+
n.forceLabel = false;
|
354 |
+
}
|
355 |
+
}
|
356 |
+
});
|
357 |
+
}
|
358 |
+
|
359 |
+
sigmaInstance.draw(2, 2, 2, 2);
|
360 |
+
});
|
361 |
+
|
362 |
// When stage is clicked, close the attribute pane
|
363 |
document.getElementById('sigma-canvas').addEventListener('click', function(evt) {
|
364 |
// Only process if we didn't click on a node (checked by looking at sigma's settings)
|
|
|
418 |
n.attr = n.attr || {};
|
419 |
n.attr.originalColor = n.color;
|
420 |
|
421 |
+
// Store original forceLabel state
|
422 |
+
n.attr.originalForceLabel = n.forceLabel;
|
423 |
+
|
424 |
if (n.id === nodeId) {
|
425 |
// Make selected node slightly larger based on config
|
426 |
n.attr.originalSize = n.size;
|
427 |
const sizeFactor = config.highlighting?.selectedNodeSizeFactor ?? 1.5;
|
428 |
n.size = n.size * sizeFactor;
|
429 |
+
// Force label to show for selected node
|
430 |
+
n.forceLabel = true;
|
431 |
+
} else if (neighbors[n.id]) {
|
432 |
+
// Do not show labels for neighbors, only keep them visible
|
433 |
+
n.forceLabel = false;
|
434 |
} else if (!neighbors[n.id]) {
|
435 |
// For non-neighbor nodes, we use a custom attribute to track they should be dimmed
|
436 |
// (Sigma v0.1 doesn't support opacity directly)
|
|
|
439 |
var rgb = getRGBColor(n.color);
|
440 |
const opacity = config.highlighting?.nodeOpacity ?? 0.2;
|
441 |
n.color = 'rgba(' + rgb.r + ',' + rgb.g + ',' + rgb.b + ',' + opacity + ')';
|
442 |
+
// Hide labels for non-neighbor nodes
|
443 |
+
n.forceLabel = false;
|
444 |
}
|
445 |
});
|
446 |
|
|
|
636 |
n.attr = n.attr || {};
|
637 |
|
638 |
// Restore original color
|
639 |
+
if (typeof n.attr.originalColor !== 'undefined') {
|
640 |
n.color = n.attr.originalColor;
|
641 |
delete n.attr.originalColor;
|
642 |
}
|
643 |
|
644 |
// Restore original size if it was modified
|
645 |
+
if (typeof n.attr.originalSize !== 'undefined') {
|
646 |
n.size = n.attr.originalSize;
|
647 |
delete n.attr.originalSize;
|
648 |
}
|
649 |
|
650 |
+
// When returning to full network, always hide all labels
|
651 |
+
// Don't rely on originalForceLabel as it may maintain visibility
|
652 |
+
n.forceLabel = false;
|
653 |
+
delete n.attr.originalForceLabel;
|
654 |
+
|
655 |
// Remove dimmed flag
|
656 |
delete n.attr.dimmed;
|
657 |
});
|