Spaces:
Running
Running
Commit
·
1df1529
1
Parent(s):
7c3814c
node highlighting is fixed
Browse files- config.json +8 -0
- css/style.css +21 -0
- index.html +2 -2
- js/main.js +88 -35
config.json
CHANGED
@@ -28,6 +28,14 @@
|
|
28 |
"defaultColorAttribute": "type",
|
29 |
"labelThreshold": 8
|
30 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
31 |
"informationPanel": {
|
32 |
"groupByEdgeDirection": false,
|
33 |
"imageAttribute": false
|
|
|
28 |
"defaultColorAttribute": "type",
|
29 |
"labelThreshold": 8
|
30 |
},
|
31 |
+
"highlighting": {
|
32 |
+
"nodeOpacity": 0.2,
|
33 |
+
"edgeOpacity": 0.05,
|
34 |
+
"selectedNodeSizeFactor": 1.5,
|
35 |
+
"highlightConnections": true,
|
36 |
+
"highlightedEdgeColor": "#000000",
|
37 |
+
"highlightedEdgeSizeFactor": 5
|
38 |
+
},
|
39 |
"informationPanel": {
|
40 |
"groupByEdgeDirection": false,
|
41 |
"imageAttribute": false
|
css/style.css
CHANGED
@@ -495,4 +495,25 @@ canvas#sigma_bg_1 {
|
|
495 |
|
496 |
.col {
|
497 |
margin-bottom: 20px;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
498 |
}
|
|
|
495 |
|
496 |
.col {
|
497 |
margin-bottom: 20px;
|
498 |
+
}
|
499 |
+
|
500 |
+
#attributepane .text .nodeattributes {
|
501 |
+
display: block;
|
502 |
+
padding: 10px;
|
503 |
+
color: #333;
|
504 |
+
}
|
505 |
+
|
506 |
+
#attributepane .text .returntext {
|
507 |
+
color: #007AFF;
|
508 |
+
cursor: pointer;
|
509 |
+
margin: 10px 0;
|
510 |
+
padding: 10px 10px 5px 10px;
|
511 |
+
font-weight: bold;
|
512 |
+
border-bottom: 1px solid #ddd;
|
513 |
+
}
|
514 |
+
|
515 |
+
#attributepane .text .nodeattributes .nodetype {
|
516 |
+
font-style: italic;
|
517 |
+
color: #666;
|
518 |
+
margin-bottom: 8px;
|
519 |
}
|
index.html
CHANGED
@@ -72,16 +72,16 @@
|
|
72 |
|
73 |
<div id="attributepane">
|
74 |
<div class="text">
|
75 |
-
<div class="
|
76 |
<div class="nodeattributes">
|
77 |
<div class="name">Select a node to see details</div>
|
|
|
78 |
<div class="data"></div>
|
79 |
<div class="p">Connections:</div>
|
80 |
<div class="link">
|
81 |
<ul></ul>
|
82 |
</div>
|
83 |
</div>
|
84 |
-
<div class="returntext">Return to the full network</div>
|
85 |
</div>
|
86 |
</div>
|
87 |
|
|
|
72 |
|
73 |
<div id="attributepane">
|
74 |
<div class="text">
|
75 |
+
<div class="returntext">Return to the full network</div>
|
76 |
<div class="nodeattributes">
|
77 |
<div class="name">Select a node to see details</div>
|
78 |
+
<div class="nodetype"></div>
|
79 |
<div class="data"></div>
|
80 |
<div class="p">Connections:</div>
|
81 |
<div class="link">
|
82 |
<ul></ul>
|
83 |
</div>
|
84 |
</div>
|
|
|
85 |
</div>
|
86 |
</div>
|
87 |
|
js/main.js
CHANGED
@@ -362,64 +362,111 @@ function nodeActive(nodeId) {
|
|
362 |
n.attr.originalColor = n.color;
|
363 |
|
364 |
if (n.id === nodeId) {
|
365 |
-
// Make selected node slightly larger
|
366 |
n.attr.originalSize = n.size;
|
367 |
-
|
|
|
368 |
} else if (!neighbors[n.id]) {
|
369 |
// For non-neighbor nodes, we use a custom attribute to track they should be dimmed
|
370 |
// (Sigma v0.1 doesn't support opacity directly)
|
371 |
n.attr.dimmed = true;
|
372 |
-
// Apply a transparent version of the original color
|
373 |
var rgb = getRGBColor(n.color);
|
374 |
-
|
|
|
375 |
}
|
376 |
});
|
377 |
|
378 |
// Apply the same to edges
|
|
|
|
|
|
|
|
|
|
|
379 |
sigmaInstance.iterEdges(function(e) {
|
|
|
380 |
e.attr = e.attr || {};
|
381 |
|
382 |
-
// First, store the original color
|
383 |
-
if (
|
384 |
e.attr.originalColor = e.color;
|
|
|
|
|
|
|
|
|
|
|
|
|
385 |
}
|
386 |
|
387 |
-
//
|
388 |
-
let
|
389 |
|
390 |
-
//
|
391 |
if (typeof e.source === 'object' && e.source !== null) {
|
392 |
-
|
393 |
-
} else
|
394 |
-
|
395 |
}
|
396 |
|
397 |
-
//
|
398 |
if (typeof e.target === 'object' && e.target !== null) {
|
399 |
-
|
400 |
-
} else
|
401 |
-
|
402 |
}
|
403 |
|
404 |
-
// For
|
|
|
|
|
|
|
|
|
|
|
|
|
405 |
if (isConnected) {
|
406 |
-
|
407 |
-
"Source:", (typeof e.source === 'object' ? e.source.id : e.source),
|
408 |
-
"Target:", (typeof e.target === 'object' ? e.target.id : e.target));
|
409 |
-
|
410 |
-
// IMPORTANT: Make sure the color is the original (non-dimmed) color
|
411 |
-
// In Sigma.js v0.1, we need to completely reset the color property
|
412 |
-
e.color = e.attr.originalColor;
|
413 |
} else {
|
414 |
-
|
415 |
-
|
416 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
417 |
}
|
418 |
});
|
419 |
|
|
|
|
|
420 |
// Force redraw
|
421 |
sigmaInstance.draw(2, 2, 2, 2);
|
422 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
423 |
// Show node details panel and populate it
|
424 |
try {
|
425 |
$('#attributepane')
|
@@ -430,16 +477,16 @@ function nodeActive(nodeId) {
|
|
430 |
'opacity': '1'
|
431 |
});
|
432 |
|
|
|
433 |
$('.nodeattributes .name').text(selected.label || selected.id);
|
434 |
|
|
|
|
|
|
|
|
|
435 |
let dataHTML = '';
|
436 |
-
|
437 |
-
|
438 |
-
attr !== 'label' && attr !== 'hidden' && attr !== 'attr' &&
|
439 |
-
typeof selected[attr] !== 'function' && attr !== 'displayX' && attr !== 'displayY' &&
|
440 |
-
attr !== 'displaySize' && !attr.startsWith('_')) {
|
441 |
-
dataHTML += '<div><strong>' + attr + ':</strong> ' + selected[attr] + '</div>';
|
442 |
-
}
|
443 |
}
|
444 |
|
445 |
if (dataHTML === '') dataHTML = '<div>No additional attributes</div>';
|
@@ -508,10 +555,16 @@ function nodeNormal() {
|
|
508 |
// Restore original edge colors
|
509 |
sigmaInstance.iterEdges(function(e) {
|
510 |
e.attr = e.attr || {};
|
511 |
-
|
|
|
512 |
e.color = e.attr.originalColor;
|
513 |
delete e.attr.originalColor;
|
514 |
}
|
|
|
|
|
|
|
|
|
|
|
515 |
});
|
516 |
|
517 |
// Reset selected node
|
|
|
362 |
n.attr.originalColor = n.color;
|
363 |
|
364 |
if (n.id === nodeId) {
|
365 |
+
// Make selected node slightly larger based on config
|
366 |
n.attr.originalSize = n.size;
|
367 |
+
const sizeFactor = config.highlighting?.selectedNodeSizeFactor ?? 1.5;
|
368 |
+
n.size = n.size * sizeFactor;
|
369 |
} else if (!neighbors[n.id]) {
|
370 |
// For non-neighbor nodes, we use a custom attribute to track they should be dimmed
|
371 |
// (Sigma v0.1 doesn't support opacity directly)
|
372 |
n.attr.dimmed = true;
|
373 |
+
// Apply a transparent version of the original color using configured opacity
|
374 |
var rgb = getRGBColor(n.color);
|
375 |
+
const opacity = config.highlighting?.nodeOpacity ?? 0.2;
|
376 |
+
n.color = 'rgba(' + rgb.r + ',' + rgb.g + ',' + rgb.b + ',' + opacity + ')';
|
377 |
}
|
378 |
});
|
379 |
|
380 |
// Apply the same to edges
|
381 |
+
let debugCounts = { connected: 0, notConnected: 0 };
|
382 |
+
let edgeCount = 0;
|
383 |
+
|
384 |
+
console.log("Starting edge processing for node:", nodeId);
|
385 |
+
|
386 |
sigmaInstance.iterEdges(function(e) {
|
387 |
+
edgeCount++;
|
388 |
e.attr = e.attr || {};
|
389 |
|
390 |
+
// First, ensure we store the original color (only once)
|
391 |
+
if (typeof e.attr.originalColor === 'undefined') {
|
392 |
e.attr.originalColor = e.color;
|
393 |
+
console.log("Storing original color for edge:", e.id, "Color:", e.color);
|
394 |
+
}
|
395 |
+
|
396 |
+
// Store original size for edges (only once)
|
397 |
+
if (typeof e.attr.originalSize === 'undefined') {
|
398 |
+
e.attr.originalSize = e.size || 1;
|
399 |
}
|
400 |
|
401 |
+
// Get the actual source and target IDs from the edge
|
402 |
+
let sourceId, targetId;
|
403 |
|
404 |
+
// Handle source ID extraction
|
405 |
if (typeof e.source === 'object' && e.source !== null) {
|
406 |
+
sourceId = e.source.id;
|
407 |
+
} else {
|
408 |
+
sourceId = String(e.source);
|
409 |
}
|
410 |
|
411 |
+
// Handle target ID extraction
|
412 |
if (typeof e.target === 'object' && e.target !== null) {
|
413 |
+
targetId = e.target.id;
|
414 |
+
} else {
|
415 |
+
targetId = String(e.target);
|
416 |
}
|
417 |
|
418 |
+
// For safe comparison, convert nodeId to string as well
|
419 |
+
const selectedNodeId = String(nodeId);
|
420 |
+
|
421 |
+
// Check if this edge is connected to the selected node
|
422 |
+
const isConnected = (sourceId === selectedNodeId || targetId === selectedNodeId);
|
423 |
+
|
424 |
+
// Track counts for debugging
|
425 |
if (isConnected) {
|
426 |
+
debugCounts.connected++;
|
|
|
|
|
|
|
|
|
|
|
|
|
427 |
} else {
|
428 |
+
debugCounts.notConnected++;
|
429 |
+
}
|
430 |
+
|
431 |
+
// Apply different styles based on connection status
|
432 |
+
if (isConnected) {
|
433 |
+
// Connected edge: make black and increase size
|
434 |
+
const highlightColor = config.highlighting?.highlightedEdgeColor ?? '#000000';
|
435 |
+
const sizeFactor = config.highlighting?.highlightedEdgeSizeFactor ?? 2;
|
436 |
+
e.color = highlightColor;
|
437 |
+
e.size = (e.attr.originalSize) * sizeFactor;
|
438 |
+
console.log("Edge highlighted:", e.id, "Source:", sourceId, "Target:", targetId, "Color set to:", e.color);
|
439 |
+
} else {
|
440 |
+
// For non-connected edges, use a very light gray that's almost invisible
|
441 |
+
// RGBA doesn't seem to work consistently in Sigma.js v0.1
|
442 |
+
e.color = '#ededed'; // Very light gray
|
443 |
+
e.size = e.attr.originalSize * 0.5; // Make non-connected edges thinner
|
444 |
}
|
445 |
});
|
446 |
|
447 |
+
console.log("Edge processing complete. Total edges:", edgeCount, "Connected:", debugCounts.connected, "Not connected:", debugCounts.notConnected);
|
448 |
+
|
449 |
// Force redraw
|
450 |
sigmaInstance.draw(2, 2, 2, 2);
|
451 |
|
452 |
+
// Add debug check after redraw to verify edge colors
|
453 |
+
setTimeout(function() {
|
454 |
+
console.log("Verifying edge colors after redraw:");
|
455 |
+
let colorCount = { black: 0, transparent: 0, other: 0 };
|
456 |
+
|
457 |
+
sigmaInstance.iterEdges(function(e) {
|
458 |
+
if (e.color === '#000000') {
|
459 |
+
colorCount.black++;
|
460 |
+
} else if (e.color.includes('rgba')) {
|
461 |
+
colorCount.transparent++;
|
462 |
+
} else {
|
463 |
+
colorCount.other++;
|
464 |
+
}
|
465 |
+
});
|
466 |
+
|
467 |
+
console.log("Edge color counts:", colorCount);
|
468 |
+
}, 100);
|
469 |
+
|
470 |
// Show node details panel and populate it
|
471 |
try {
|
472 |
$('#attributepane')
|
|
|
477 |
'opacity': '1'
|
478 |
});
|
479 |
|
480 |
+
// Set the node name/title
|
481 |
$('.nodeattributes .name').text(selected.label || selected.id);
|
482 |
|
483 |
+
// Display the node type
|
484 |
+
$('.nodeattributes .nodetype').text(selected.type ? 'Type: ' + selected.type : '');
|
485 |
+
|
486 |
+
// Simplify data display to only show degree
|
487 |
let dataHTML = '';
|
488 |
+
if (typeof selected.degree !== 'undefined') {
|
489 |
+
dataHTML = '<div><strong>Degree:</strong> ' + selected.degree + '</div>';
|
|
|
|
|
|
|
|
|
|
|
490 |
}
|
491 |
|
492 |
if (dataHTML === '') dataHTML = '<div>No additional attributes</div>';
|
|
|
555 |
// Restore original edge colors
|
556 |
sigmaInstance.iterEdges(function(e) {
|
557 |
e.attr = e.attr || {};
|
558 |
+
// Restore color with explicit check for undefined
|
559 |
+
if (typeof e.attr.originalColor !== 'undefined') {
|
560 |
e.color = e.attr.originalColor;
|
561 |
delete e.attr.originalColor;
|
562 |
}
|
563 |
+
// Restore size with explicit check for undefined
|
564 |
+
if (typeof e.attr.originalSize !== 'undefined') {
|
565 |
+
e.size = e.attr.originalSize;
|
566 |
+
delete e.attr.originalSize;
|
567 |
+
}
|
568 |
});
|
569 |
|
570 |
// Reset selected node
|