import * as Helpers from "../helpers"; import jQuery from "jquery"; export { NodeNeighborOverlay }; /** * Displays an overlay showing the neighbors of a node divided by the link type * that connects them. */ class NodeNeighborOverlay { constructor(graph, parentNode, infoOverlay, type = "link") { this.graph = graph; this.parentNode = parentNode; this.infoOverlay = infoOverlay; this.type = type; this.activeTabNav = null; // The currently selected tab handle this.activeTabContent = null; // The currently selected tab content this.tabContentPages = {}; this.tabNavHandles = {}; } /** * Creates the visible elements of the overlay. * Must be called after the graph has been initialized. */ create() { const bottomContainerDiv = Helpers.createDiv( "bottom-container", this.parentNode ); const coll = Helpers.createDiv( "button", bottomContainerDiv ); coll.className = "collapsible"; coll.innerText = "Verwandte Inhalte"; var contentTabs = Helpers.createDiv( "neighbor-content-tabs", bottomContainerDiv ); coll.style.display = "flex"; coll.style.textDecoration = "underline black"; this.contentTab = contentTabs; contentTabs.style.display = "flex"; coll.addEventListener("click", function() { if(contentTabs.style.display === "flex") { contentTabs.style.display = "none"; } else { contentTabs.style.display = "flex"; } }); const colors = this.type === "link" ? this.graph.edgeColors : this.graph.nodeColors; for (const [cls, color] of Object.entries(colors)) { const collTab = Helpers.createDiv( "button", contentTabs ); collTab.className = "collapsible"; collTab.innerText = cls; collTab.style.borderLeftColor = color; collTab.style.borderLeftWidth = "8px"; collTab.type = cls; this.tabNavHandles[cls] = collTab; const collTabContent = Helpers.createDiv( "neighbor-content-links", contentTabs ); collTabContent.type = cls; this.tabContentPages[cls] = collTabContent; collTab.addEventListener("click", function() { if(collTabContent.style.display === "flex") { collTabContent.style.display = "none"; } else { collTabContent.style.display = "flex"; } }); } } /** * Clears the images from all tab content pages and makes the object * invisible. */ clearTabContentPages() { for (const page of Object.values(this.tabContentPages)) { jQuery(page).empty(); if(page.style.display === "flex") { page.style.display = "none"; } } } /** * Creates a new image (with link) for the given target node. * @param target * @returns {HTMLDivElement} */ createReference(target) { const linkDiv = document.createElement("div"); var linkText = document.createTextNode("- " + target.name); linkDiv.appendChild(linkText); linkDiv.style.margin = "2px"; linkDiv.style.cursor = "pointer"; jQuery(linkDiv).on("click", () => { this.graph.focusOnNode(target); this.infoOverlay.updateInfoOverlay(target); }); return linkDiv; } /** * Updates all tabs to have content matching the given node. * @param node */ updateTabs(node) { this.clearTabContentPages(); for (const link of node.links) { const target = link.source == node ? link.target : link.source; const reference = this.createReference(target); if (this.type === "link") { this.tabContentPages[link.type].appendChild(reference); } else { this.tabContentPages[target.type].appendChild(reference); } } this.hideContentPages(); } /** * Hides all the categories of a node that are not represented by a link * to another neighbor. */ hideContentPages () { for (const page of Object.values(this.tabContentPages)) { if(!page.hasChildNodes()) { this.tabNavHandles[page.type].style.display = "none"; } else { this.tabNavHandles[page.type].style.display = "flex"; } } } }