import * as Helpers from "../helpers"; import jQuery from "jquery"; import { createHTMLElement } from "../helpers"; 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 ); // Create the collapsible of the entire menu const coll = Helpers.createDiv( "button", bottomContainerDiv ); coll.className = "neighbor-collapsible-title"; coll.innerText = "Verwandte Inhalte"; coll.style.textAlign = "center"; // Div that displays the information about all the chapters var contentTabs = Helpers.createDiv( "neighbor-content-tabs", bottomContainerDiv ); 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 slideDown = elem => elem.style.height = `${elem.scrollHeight}px`; const slideUp = elem => elem.style.height = '0'; const colors = this.type === "link" ? this.graph.edgeColors : this.graph.nodeColors; for (const [cls, color] of Object.entries(colors)) { // Creating the collapsible tabs for the different chapters const collTab = Helpers.createDiv( "button", contentTabs ); collTab.className = "neighbor-collapsible-section"; collTab.innerText = cls; collTab.type = cls; this.tabNavHandles[cls] = collTab; const collTabMarker = Helpers.createDiv( "neighbor-collapsible-marker-div", collTab ); collTabMarker.style.borderColor = color; collTabMarker.style.backgroundColor = color; const openMarkerTabs = Helpers.createDiv( "neighbor-tab-open-status-marker", collTab ); openMarkerTabs.innerText = '+'; collTab.marker = openMarkerTabs; // Content of the different tabs const collTabContent = Helpers.createDiv( "neighbor-content-linksection", contentTabs ); collTabContent.type = cls; const list = createHTMLElement( "ul", collTabContent ); list.style.margin = 0; collTabContent.list = list; this.tabContentPages[cls] = collTabContent; collTab.addEventListener("click", function() { if(collTabContent.style.display === "flex") { slideUp(collTabContent); collTabContent.style.display = "none"; openMarkerTabs.innerText = '+'; } else { collTabContent.style.display = "flex"; openMarkerTabs.innerText = '-'; slideDown(collTabContent); } }); } } /** * Clears the images from all tab content pages and makes the object * invisible. */ clearTabContentPages() { for (const page of Object.values(this.tabContentPages)) { jQuery(page.list).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("li"); var linkText = document.createTextNode(target.name); linkDiv.className = "neighbor-content-link"; linkDiv.appendChild(linkText); 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].list.appendChild(reference); } else { this.tabContentPages[target.type].list.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.list.hasChildNodes()) { this.tabNavHandles[page.type].style.display = "none"; } else { this.tabNavHandles[page.type].style.display = "flex"; this.tabNavHandles[page.type].marker.innerText = '+'; } } } }