Skip to content
Snippets Groups Projects
neighbors.js 4.71 KiB
Newer Older
  • Learn to ignore specific revisions
  • 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.activeTabNav = null; // The currently selected tab handle
            this.activeTabContent = null; // The currently selected tab content
    
    
            this.tabContentPages = {};
    
        /**
         * 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
            );
    
    Harm Kube's avatar
    Harm Kube committed
            coll.style.display = "flex";
    
            coll.style.textDecoration = "underline black";
    
    Harm Kube's avatar
    Harm Kube committed
            this.contentTab = contentTabs;
    
    Harm Kube's avatar
    Harm Kube committed
            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;
    
    Harm Kube's avatar
    Harm Kube committed
                this.tabNavHandles[cls] = collTab;
    
                const collTabContent = Helpers.createDiv(
    
                    "neighbor-content-links",
    
                    contentTabs
    
                collTabContent.type = cls;
    
    Harm Kube's avatar
    Harm Kube committed
                this.tabContentPages[cls] = collTabContent;
    
                collTab.addEventListener("click", function() {
                    if(collTabContent.style.display === "flex") {
                        collTabContent.style.display = "none";
                    } else {
                        collTabContent.style.display = "flex";
    
    Harm Kube's avatar
    Harm Kube committed
         * Clears the images from all tab content pages and makes the object
         * invisible.
    
        clearTabContentPages() {
    
    Harm Kube's avatar
    Harm Kube committed
            for (const page of Object.values(this.tabContentPages)) {
    
                jQuery(page).empty();
    
    Harm Kube's avatar
    Harm Kube committed
                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");
    
    Harm Kube's avatar
    Harm Kube committed
            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) {
    
    Harm Kube's avatar
    Harm Kube committed
            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);
                }
    
    Harm Kube's avatar
    Harm Kube committed
            }
    
            this.hideContentPages();
        }
    
    
    Harm Kube's avatar
    Harm Kube committed
        /**
         * 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";
                }
            }