<!DOCTYPE html>
<html>
<head>
<title>Network Graph in JavaScript</title>
<style type="text/css">
html,
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
#container {
width: 100%;
height: 100%;
position: relative;
}
#infoPanel {
position: absolute;
top: 0;
right: 0;
width: 300px;
height: 100%;
background-color: white;
border-left: 1px solid #ddd;
box-shadow: -2px 0 5px rgba(0, 0, 0, 0.1);
padding: 16px;
box-sizing: border-box;
display: none;
overflow-y: auto;
}
#infoPanel h3 {
margin: 0 0 10px;
font-size: 18px;
}
#infoPanel p {
margin: 0;
color: #333;
}
.image-grid-container {
max-height: 200px;
overflow-y: auto;
}
.image-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(50px, 1fr));
gap: 5px;
}
.image-grid img {
width: 100%;
height: auto;
display: block;
}
.comments-list {
margin: 10px 0;
padding: 0;
list-style-type: none;
}
.comments-list li {
margin-bottom: 5px;
padding: 5px;
border-bottom: 1px solid #ddd;
}
.inputs-list {
margin: 10px 0;
padding: 0;
list-style-type: none;
}
.inputs-list li {
margin-bottom: 5px;
padding: 5px;
border-bottom: 1px solid #ddd;
}
</style>
<script src="https://cdn.anychart.com/releases/8.12.1/js/anychart-core.min.js"></script>
<script src="https://cdn.anychart.com/releases/8.12.1/js/anychart-graph.min.js"></script>
</head>
<body>
<div id="container"></div>
<div id="infoPanel">
<h3>Node Info</h3>
<div id="infoContent"></div>
</div>
<script>
anychart.onDocumentReady(function () {
function escapeHtml(text) {
return text
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
const data = {{graph| json | safe}};
var chart = anychart.graph(data);
var nodes = chart.nodes();
nodes.labels().enabled(true);
nodes.labels().fontSize(15);
nodes.labels().fontColor("black");
nodes.tooltip().useHtml(true);
nodes.tooltip().format(function (e) {
const name = e.getData("id");
const value = e.getData("value");
return `<b>${name}<br>${value}</b> km in diameter`;
});
var edges = chart.edges();
edges.tooltip().useHtml(true);
edges.tooltip().format(function (e) {
const from = e.getData("from");
const to = e.getData("to");
const distance = e.getData("distance") * 1000000;
return `From <b>${from}</b> to <b>${to}<br>${distance}</b> km`;
});
edges.stroke("lightblue", 2, "10 5");
chart.title("Coma Network Graph");
chart.container("container");
chart.draw();
var infoPanel = document.getElementById("infoPanel");
var infoContent = document.getElementById("infoContent");
var lastClickedNode = null;
chart.listen('click', function (e) {
var id = e.domTarget.tag?.id;
var node;
for (var n of data.nodes) {
if (n.id == id) {
node = n;
break;
}
}
if (!node) {
infoPanel.style.display = "none";
return
}
let commentsHtml = '<ul class="comments-list">';
if (node.comments && node.comments.length > 0) {
node.comments.forEach(comment => {
commentsHtml += `<li>${escapeHtml(comment)}</li>`;
});
} else {
commentsHtml += '<li>No comments available</li>';
}
commentsHtml += '</ul>';
let inputsHtml = '<ul class="inputs-list">';
if (node.inputs && node.inputs.length > 0) {
node.inputs.forEach(input => {
inputsHtml += `<li>${escapeHtml(input)}</li>`;
});
} else {
inputsHtml += '<li>No inputs available</li>';
}
inputsHtml += '</ul>';
console.log(node.images)
let imagesHtml = '';
if (node.images && node.images.length > 0) {
imagesHtml = '<div class="image-grid-container"><div class="image-grid">';
node.images.forEach(url => {
imagesHtml += `<a href="${url}" target="_blank"><img src="${url}" alt="Image"></a>`;
});
imagesHtml += '</div></div>';
}
infoContent.innerHTML = `<strong>ID:</strong> ${node.id}<br>` +
`<strong>Label:</strong> ${node.label}<br>` +
(node.images.length > 0 ? `<strong>Images:</strong>${imagesHtml}` : "") +
(node.comments.length > 0 ? `<strong>Comments:</strong>${commentsHtml}` : "") +
(node.inputs.length > 0 ? `<strong>Inputs:</strong>${inputsHtml}` : "");
infoPanel.style.display = "block";
lastClickedNode = node;
});
document.addEventListener('click', function (e) {
if (infoPanel.style.display === "block" && !infoPanel.contains(e.target) && !e.target.closest('#container')) {
infoPanel.style.display = "none";
}
});
});
</script>
</body>
</html>