diff --git a/backgrounds/background_4.jpg b/backgrounds/background_4.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..13cda86339e4850f794e8f147133db01c3020dbb
Binary files /dev/null and b/backgrounds/background_4.jpg differ
diff --git a/display/graph.js b/display/graph.js
new file mode 100644
index 0000000000000000000000000000000000000000..c339031d0591db90fc5ab23731f9d567de5c5fdc
--- /dev/null
+++ b/display/graph.js
@@ -0,0 +1,281 @@
+const colorPallette = ['rgb(104, 169, 77)', 'rgb(102, 75, 154)', 'rgb(41, 171, 226)', 'rgb(224, 133, 35)',
+    'rgb(214, 207, 126)', 'rgb(239, 65, 35)', 'rgb(255, 255, 255)'];
+const edgeColors = {};
+var graph_element = document.getElementById('3d-graph');
+
+
+
+class Graph {
+    constructor(dataUrl) {
+        this.graph = null;
+        this.highlightNodes = new Set();
+        this.highlightLinks = new Set();
+        this.hoverNode = null;
+        this.firstTick = true;
+        this.infooverlay = null;
+        this.loadGraph(dataUrl);
+    }
+
+    async loadGraph(dataUrl) {
+        const gData = await fetch(dataUrl).then(res => res.json())
+        this.graph = ForceGraph3D({extraRenderers: [new THREE.CSS2DRenderer(), new THREE.CSS3DRenderer()]})
+        (document.getElementById('3d-graph'))
+            .graphData(gData)
+            .nodeLabel('id')
+            .nodeAutoColorBy('group')
+            .nodeColor(node => this.getNodeColor(node))
+            .linkWidth(link => this.getLinkWidth(link))
+            .onNodeClick(node => {
+                this.focusOnNode(node);
+                this.infooverlay.updateInfoOverlay(node);
+            })
+            .onNodeHover(node => {
+                this.onNodeHover(node);
+                this.updateHighlight();
+            })
+            .onLinkHover(link => this.onLinkHover(link))
+            .linkColor(link => this.getLinkColor(link))
+            .linkOpacity(0.8)
+            .nodeThreeObjectExtend(false)
+            .nodeThreeObject(node => this.drawNode(node))
+            .onEngineTick(() => this.initializeModel())
+            .width(getWidth())
+            .height(getHeight());
+    }
+
+    getNodeColor(node) {
+        return this.highlightNodes.has(node) ? node === hoverNode ? 'rgb(255,0,0,1)' : 'rgba(255,160,0,0.8)' : 'rgba(0,255,255,0.6)';
+    }
+
+    getLinkColor(link) {
+        if ('type' in link) {
+            return edgeColors[link.type]
+        }
+        return 'rgb(255, 255, 255)'
+    }
+
+    getLinkWidth(link) {
+        return this.highlightLinks.has(link) ? 2 : 0.8;
+    }
+
+    onNodeHover(node) {
+        // no state change
+        if ((!node && !this.highlightNodes.size) || (node && this.hoverNode === node)) return;
+
+        this.highlightNodes.clear();
+        this.highlightLinks.clear();
+        if (node) {
+            this.highlightNodes.add(node);
+            node.neighbors.forEach(neighbor => this.highlightNodes.add(neighbor));
+            node.links.forEach(link => this.highlightLinks.add(link));
+        }
+
+        this.hoverNode = node || null;
+    }
+
+    onLinkHover(link) {
+        this.highlightNodes.clear();
+        this.highlightLinks.clear();
+
+        if (link) {
+            this.highlightLinks.add(link);
+            this.highlightNodes.add(link.source);
+            this.highlightNodes.add(link.target);
+        }
+
+        this.updateHighlight();
+    }
+
+    getLinkClasses() {
+        const linkClasses = [];
+        this.graph.graphData().links.forEach(link => linkClasses.push(link.type));
+        return [... new Set(linkClasses)];
+    }
+
+    mapEdgeColors() {
+        const linkClasses = this.getLinkClasses()
+        for (let i = 0; i < linkClasses.length; i++) {
+            edgeColors[linkClasses[i]] = colorPallette[i % colorPallette.length]
+        }
+    }
+
+    updateLinks() {
+        const gData = this.graph.graphData()
+        // cross-link node objects
+        gData.links.forEach(link => {
+            const a = link.source;
+            const b = link.target;
+            if (!a.neighbors) a.neighbors = [];
+            if (!b.neighbors) b.neighbors = [];
+            a.neighbors.push(b);
+            b.neighbors.push(a);
+
+            if (!a.links) a.links = [];
+            if (!b.links) b.links = [];
+            a.links.push(link);
+            b.links.push(link);
+        });
+        this.graph.graphData(gData)
+    }
+
+    updateHighlight() {
+        // trigger update of highlighted objects in scene
+        this.graph
+            .nodeColor(this.graph.nodeColor())
+            .linkWidth(this.graph.linkWidth())
+            .linkDirectionalParticles(this.graph.linkDirectionalParticles());
+    }
+
+    addBackground() {
+        const sphereGeometry = new THREE.SphereGeometry(20000, 32, 32);
+        //const planeGeometry = new THREE.PlaneGeometry(1000, 1000, 1, 1);
+        const loader = new THREE.TextureLoader();
+        //const planeMaterial = new THREE.MeshLambertMaterial({color: 0xFF0000, side: THREE.DoubleSide}); //THREE.BackSide
+        const planeMaterial = new THREE.MeshBasicMaterial({map: loader.load(plugin_path + 'backgrounds/background_4.jpg'), side: THREE.DoubleSide}); //THREE.BackSide
+        const mesh = new THREE.Mesh(sphereGeometry, planeMaterial);
+        mesh.position.set(0, 0, 0);
+        //mesh.rotation.set(0.5 * Math.PI, 0, 0);
+
+        this.graph.scene().add(mesh);
+    }
+
+    focusOnNode(node) {
+        // Aim at node from outside it
+        const distance = 250;
+        const distRatio = 1 + distance/Math.hypot(node.x, node.y, node.z);
+
+        this.graph.cameraPosition(
+            { x: node.x * distRatio, y: node.y * distRatio, z: node.z * distRatio }, // new position
+            node, // lookAt ({ x, y, z })
+            1000  // ms transition duration
+        );
+    }
+
+    focusOnNodeId(id) {
+        const gData = this.graph.graphData();
+
+        gData.nodes.forEach(node => {
+            if (node.id === id) {
+                this.onNodeClick(node);
+            }
+        })
+    }
+
+    resizeGraph() {
+        this.graph.width(getWidth());
+        this.graph.height(getHeight());
+    }
+
+    initializeModel() {
+        if (this.firstTick) {
+            this.mapEdgeColors();
+            this.updateLinks();
+            this.addBackground();
+            loadComponents();
+            this.firstTick = false;
+        }
+    }
+
+    drawNode(node) {
+        // Draw node as label + image
+        const nodeDiv = document.createElement('div');
+        const group = new THREE.Group();
+
+        const labelDiv = document.createElement('div')
+        labelDiv.textContent = node.name;
+        labelDiv.style.color = node.color;
+        labelDiv.className = 'node-label';
+        nodeDiv.appendChild(labelDiv);
+
+        const cssobj = new THREE.CSS3DSprite(nodeDiv);
+        cssobj.scale.set(0.25, 0.25, 0.25);
+        cssobj.position.set(0, -6, 0);
+        group.add(cssobj)
+
+        // Draw node circle image
+        const textureLoader = new THREE.TextureLoader();
+        const imageAlpha = textureLoader.load(plugin_path + 'datasets/images/alpha.png');
+        let imageTexture = null;
+
+        if ('image' in node) {
+            imageTexture = textureLoader.load(plugin_path + 'datasets/images/' + node.image);
+        } else {
+            imageTexture = textureLoader.load(plugin_path + 'datasets/images/default.jpg');
+        }
+
+        const material = new THREE.SpriteMaterial({map: imageTexture, alphaMap: imageAlpha, transparent: true,
+            alphaTest: 0.2, depthWrite:false, depthTest: false});
+        const sprite = new THREE.Sprite(material);
+        sprite.renderOrder = 999; // This may not be optimal. But it allows us to render the sprite on top of everything else.
+
+        if ('image' in node) {
+            sprite.scale.set(20, 20);
+        } else {
+            sprite.scale.set(5, 5);
+        }
+
+        group.add(sprite)
+
+        return group;
+    }
+
+}
+
+
+const dataUrl = plugin_path + 'datasets/aud1.json'
+G = new Graph(dataUrl);
+linkoverlay = new LinkOverlay(G);
+infooverlay = new InfoOverlay();
+G.infooverlay = infooverlay;
+
+function loadComponents() {
+        linkoverlay.create();
+        infooverlay.create();
+        add_fullscreen_mode_button();
+        add_fullscreen_Listener();
+        window.onresize = G.resizeGraph();
+}
+
+function getWidth() {
+    return document.getElementById('3d-graph').offsetWidth;
+}
+
+function getHeight() {
+    return window.innerHeight - 200
+}
+
+
+function getCanvasDivNode() {
+    const domNode = document.getElementById('3d-graph');
+    return domNode.firstChild.firstChild.firstChild;
+}
+
+function add_fullscreen_mode_button() {
+    const sceneNode = document.getElementById('3d-graph');
+    const overlayNode = document.createElement('button');
+    overlayNode.className = 'fullscreen_button';
+    overlayNode.innerText = 'fullscreen';
+    overlayNode.addEventListener("click", fullscreen_mode);
+    sceneNode.appendChild(overlayNode);
+}
+
+function fullscreen_mode(){
+    if(getCanvasDivNode().requestFullscreen) {
+        getCanvasDivNode().requestFullscreen().catch();
+    }
+}
+
+function resize_canvas() {
+    if(document.fullscreenElement == getCanvasDivNode()) {
+        G.graph.height(screen.height);
+        G.graph.width(screen.width);
+    } else {
+        G.graph.height(window.innerHeight - 200);
+        G.graph.width(getWidth());
+    }
+}
+
+function add_fullscreen_Listener() {
+    getCanvasDivNode().addEventListener("fullscreenchange", resize_canvas);
+}
+
diff --git a/display/infooverlay.js b/display/infooverlay.js
new file mode 100644
index 0000000000000000000000000000000000000000..854d07ee46ea1e590b9d7e3918c2399c00d39429
--- /dev/null
+++ b/display/infooverlay.js
@@ -0,0 +1,184 @@
+
+
+
+
+class InfoOverlay {
+    constructor() {
+
+    }
+
+    create() {
+        const sceneNode = getCanvasDivNode();
+        const overlayNode = document.createElement('div');
+        overlayNode.id = 'infoOverlay'
+        overlayNode.className = 'detail-view';
+        //overlayNode.innerText = 'Hello there!';
+        sceneNode.insertBefore(overlayNode, sceneNode.childNodes[2]);
+
+        const close = document.createElement('div');
+        close.innerHTML = '<p>&#10006;</p>';
+        close.id = 'infoOverlayCloseButton';
+        close.className = 'close-button';
+        overlayNode.appendChild(close);
+
+        const topArea = document.createElement('div');
+        topArea.className = 'detail-view-top-area';
+        overlayNode.appendChild(topArea);
+
+        const nodeImage = document.createElement('img');
+        nodeImage.id = 'infoOverlayImage';
+        nodeImage.src = plugin_path + 'datasets/images/default.jpg';
+        nodeImage.className = 'detail-view-image';
+        topArea.appendChild(nodeImage);
+
+        const headline = document.createElement('h2');
+        headline.id = 'infoOverlayHeadline';
+        headline.innerText = 'Default Text';
+        headline.className = 'detail-view-headline';
+        topArea.appendChild(headline);
+
+        const textArea = document.createElement('div');
+        textArea.className = 'detail-view-text-area';
+        overlayNode.appendChild(textArea);
+
+        const description = document.createElement('p');
+        description.id = 'infoOverlayDescription';
+        description.innerText = 'Default Text'
+        description.setAttribute("overflow-y", "scroll");
+        textArea.appendChild(description);
+
+        const link_container = document.createElement('div');
+        const links = document.createElement('div');
+        const linkClasses = G.getLinkClasses();
+
+        link_container.id = 'link_container';
+        link_container.className = 'bottom container';
+        links.className = 'tab';
+        links.id = 'links';
+
+        for(let i = 0; i < linkClasses.length; i++){
+
+            const linkType = linkClasses[i];
+            const tablink = document.createElement('button');
+            tablink.className = 'tablinks';
+            tablink.id = linkType + "_id";
+            tablink.innerHTML = linkType[0] + linkType[1] + linkType[2];
+            tablink.style = "background-color: " + edgeColors[linkClasses[i]];
+            tablink.setAttribute("onclick", "openTab(event, " + linkType + "_id)"); //unusual function call
+            links.appendChild(tablink);
+
+        }
+
+        link_container.appendChild(links);
+
+        for(let i = 0; i < linkClasses.length; i++){
+
+            const linkType = linkClasses[i];
+            const tabcontent = document.createElement('div');
+            tabcontent.className = "tabcontent";
+            tabcontent.id = linkType + "_id_content";
+            tabcontent.style = "background-color: " + edgeColors[linkClasses[i]];
+            link_container.appendChild(tabcontent);
+
+        }
+
+        overlayNode.appendChild(link_container);
+
+        jQuery('#infoOverlayCloseButton').click(function () {
+            jQuery('#infoOverlay').slideUp('fast');
+        });
+
+        //sceneNode.appendChild(overlayNode);
+
+    }
+
+    updateInfoOverlay(node) {
+        jQuery('#infoOverlayHeadline').text(node.name);
+        if ('image' in node) {
+            jQuery('#infoOverlayImage').attr('src', plugin_path + 'datasets/images/' + node.image);
+        } else {
+            jQuery('#infoOverlayImage').attr('src', plugin_path + 'datasets/images/default.jpg');
+        }
+
+        if ('description' in node) {
+            jQuery('#infoOverlayDescription').text(node.description);
+        } else {
+            jQuery('#infoOverlayDescription').text('Default Text');
+        }
+
+        this.updateTabs(node);
+
+        jQuery('#infoOverlay').slideDown('fast');
+    }
+
+    updateTabs(node){
+        //tabs of the links to other nodes:
+        //delete old nodes from tabcontent
+        const tabcontent = document.getElementsByClassName("tabcontent");
+        for (let i = 0; i < tabcontent.length; i++) {
+            while (tabcontent[i].firstChild){
+                tabcontent[i].removeChild(tabcontent[i].lastChild);
+            }
+        }
+        //add new nodes to tabcontent
+        for (let i = 0; i < tabcontent.length; i++) {                                   //for every type of link
+            node.links.forEach(link => {                                            //and for every link
+                if(link.type + '_id_content' == tabcontent[i].id){                  //is checked if the type is equal
+                    const linkButton = document.createElement('div');      //and if so a new element is created
+                    linkButton.className = "link img";
+                    var node2;
+                    if(link.source == node){
+                        node2 = link.target;
+                    }
+                    else if(link.target == node){
+                        node2 = link.source;
+                    }
+                    linkButton.id = "linkButton_" + node2.id;
+                    const nodeID = node2.id;
+
+                    const linkImage = document.createElement('img');
+                    const linkTitle = document.createElement('div');
+
+                    if ('image' in node2) {
+                        linkImage.src = plugin_path + 'datasets/images/' + node2.image;
+                    } else if(!('image' in node2) && ('id' in node2)) {
+                        linkImage.src = plugin_path + 'datasets/images/default.jpg';
+                    }
+
+                    linkTitle.className = "link title";
+                    linkTitle.innerHTML = node2.name;
+
+                    //linkButton.appendChild(linkTitle);
+                    linkButton.appendChild(linkImage);
+
+                    linkButton.addEventListener('click', function (){focusOnNodeId(nodeID)});
+                    tabcontent[i].appendChild(linkButton);
+                }
+            });
+        }
+    }
+
+
+
+}
+
+//is used in createInfoOverlay, as an unusual function call to open link-tabs
+function openTab (event, tab) {
+    var i, tabcontent, tablinks;
+
+    // Get all elements with class="tabcontent" and hide them
+    tabcontent = document.getElementsByClassName("tabcontent");
+    for (i = 0; i < tabcontent.length; i++) {
+        tabcontent[i].style.display = "none";
+    }
+
+    // Get all elements with class="tablinks" and remove the class "active"
+    tablinks = document.getElementsByClassName("tablinks");
+    for (i = 0; i < tablinks.length; i++) {
+        tablinks[i].className = tablinks[i].className.replace(" active", "");
+    }
+
+    // Show the current tab, and add an "active" class to the button that opened the tab
+    document.getElementById(tab.id + "_content").style.display = "flex";
+    event.currentTarget.className += " active";
+}
\ No newline at end of file
diff --git a/display/linkoverlay.js b/display/linkoverlay.js
new file mode 100644
index 0000000000000000000000000000000000000000..5c3acaa72e130648d1c44c34136744c5ffc69bd0
--- /dev/null
+++ b/display/linkoverlay.js
@@ -0,0 +1,31 @@
+
+
+class LinkOverlay {
+    constructor(graph) {
+        this.graph = graph
+    }
+
+    create() {
+        const sceneNode = getCanvasDivNode();
+        const overlayNode = document.createElement('div');
+        overlayNode.className = 'link-overlay';
+        //overlayNode.innerText = 'Hello there!';
+        sceneNode.insertBefore(overlayNode, sceneNode.childNodes[2])
+
+        const linkClasses = this.graph.getLinkClasses();
+        const chars = Math.max.apply(Math, linkClasses.map(function (c) { return c.length; }));
+
+        for (let i=0; i<linkClasses.length; i++) {
+            const relation = document.createElement('div');
+            relation.className = 'relation';
+            relation.innerHTML = "<p>" + linkClasses[i] + "</p>";
+            overlayNode.appendChild(relation);
+
+            const colorStrip = document.createElement('div');
+            colorStrip.className = 'rel-container';
+            colorStrip.style = "background-color: " + edgeColors[linkClasses[i]] + "; width: " + 10 * chars + "px;";
+            relation.appendChild(colorStrip);
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/graph.js b/graph.js
deleted file mode 100644
index 65439fc86c0aa703c62c9ef84b9566f11eae9f31..0000000000000000000000000000000000000000
--- a/graph.js
+++ /dev/null
@@ -1,462 +0,0 @@
-const highlightNodes = new Set();
-const highlightLinks = new Set();
-let hoverNode = null;
-let Graph = null;
-let firstTick = true;
-
-const colorPallette = ['rgb(104, 169, 77)', 'rgb(102, 75, 154)', 'rgb(41, 171, 226)', 'rgb(224, 133, 35)',
-    'rgb(214, 207, 126)', 'rgb(239, 65, 35)', 'rgb(255, 255, 255)'];
-const edgeColors = {};
-var graph_element = document.getElementById('3d-graph');
-
-loadGraph();
-
-async function loadGraph() {
-    const dataUrl = plugin_path + 'datasets/aud1.json'
-    const gData = await fetch(dataUrl).then(res => res.json())
-    Graph = ForceGraph3D({extraRenderers: [new THREE.CSS2DRenderer(), new THREE.CSS3DRenderer()]})
-    (document.getElementById('3d-graph'))
-        .graphData(gData)
-        .nodeLabel('id')
-        .nodeAutoColorBy('group')
-        .nodeColor(node => highlightNodes.has(node) ? node === hoverNode ? 'rgb(255,0,0,1)' : 'rgba(255,160,0,0.8)' : 'rgba(0,255,255,0.6)')
-        .linkWidth(link => highlightLinks.has(link) ? 2 : 0.8)
-        .onNodeClick(handleNodeClick)
-        .onNodeHover(nodeHover)
-        .onLinkHover(linkHover)
-        .linkColor(linkColor)
-        .linkOpacity(0.8)
-        .nodeThreeObjectExtend(false)
-        .nodeThreeObject(drawNode)
-        .onEngineTick(loadComponents)
-        .width(getWidth())
-        .height(getHeight());
-    //Graph.renderer().sortObjects = true;
-}
-
-
-function loadComponents() {
-    if (firstTick) {
-        mapEdgeColors();
-        updateLinks();
-        add_background();
-        createLinkOverlay();
-        createInfoOverlay();
-        add_fullscreen_mode_button();
-        add_fullscreen_Listener();
-        window.onresize = resize_graph();
-        firstTick = false;
-    }
-}
-
-function resize_graph() {
-    Graph.width(getWidth());
-    Graph.height(getHeight());
-}
-
-function getWidth() {
-    return document.getElementById('3d-graph').offsetWidth;
-}
-
-function getHeight() {
-    return window.innerHeight - 200
-}
-
-function mapEdgeColors() {
-    const linkClasses = getLinkClasses()
-    for (let i = 0; i < linkClasses.length; i++) {
-        edgeColors[linkClasses[i]] = colorPallette[i % colorPallette.length]
-    }
-}
-
-
-function getLinkClasses() {
-    const linkClasses = [];
-    Graph.graphData().links.forEach(link => linkClasses.push(link.type));
-    return [... new Set(linkClasses)];
-}
-
-function getCanvasDivNode() {
-    const domNode = document.getElementById('3d-graph');
-    return domNode.firstChild.firstChild.firstChild;
-}
-
-function drawNode(node) {
-    // Draw node as label + image
-    const nodeDiv = document.createElement('div');
-    group = new THREE.Group();
-
-    const labelDiv = document.createElement('div')
-    labelDiv.textContent = node.name;
-    labelDiv.style.color = node.color;
-    labelDiv.className = 'node-label';
-    nodeDiv.appendChild(labelDiv);
-
-    const cssobj = new THREE.CSS3DSprite(nodeDiv);
-    cssobj.scale.set(0.25, 0.25, 0.25);
-    cssobj.position.set(0, -6, 0);
-    group.add(cssobj)
-
-    // Draw node circle image
-    const textureLoader = new THREE.TextureLoader();
-    const imageAlpha = textureLoader.load(plugin_path + 'datasets/images/alpha.png');
-    let imageTexture = null;
-
-    if ('image' in node) {
-        imageTexture = textureLoader.load(plugin_path + 'datasets/images/' + node.image);
-    } else {
-        imageTexture = textureLoader.load(plugin_path + 'datasets/images/default.jpg');
-    }
-
-    const material = new THREE.SpriteMaterial({map: imageTexture, alphaMap: imageAlpha, transparent: true,
-        alphaTest: 0.2, depthWrite:false, depthTest: false});
-    const sprite = new THREE.Sprite(material);
-    sprite.renderOrder = 999; // This may not be optimal. But it allows us to render the sprite on top of everything else.
-
-    if ('image' in node) {
-        sprite.scale.set(20, 20);
-    } else {
-        sprite.scale.set(5, 5);
-    }
-
-    group.add(sprite)
-
-    return group;
-}
-
-
-function createInfoOverlay() {
-    const sceneNode = getCanvasDivNode();
-    const overlayNode = document.createElement('div');
-    overlayNode.id = 'infoOverlay'
-    overlayNode.className = 'detail-view';
-    //overlayNode.innerText = 'Hello there!';
-    sceneNode.insertBefore(overlayNode, sceneNode.childNodes[2]);
-
-    const close = document.createElement('div');
-    close.innerHTML = '<p>&#10006;</p>';
-    close.id = 'infoOverlayCloseButton';
-    close.className = 'close-button';
-    overlayNode.appendChild(close);
-
-    const topArea = document.createElement('div');
-    topArea.className = 'detail-view-top-area';
-    overlayNode.appendChild(topArea);
-
-    const nodeImage = document.createElement('img');
-    nodeImage.id = 'infoOverlayImage';
-    nodeImage.src = plugin_path + 'datasets/images/default.jpg';
-    nodeImage.className = 'detail-view-image';
-    topArea.appendChild(nodeImage);
-
-    const headline = document.createElement('h2');
-    headline.id = 'infoOverlayHeadline';
-    headline.innerText = 'Default Text';
-    headline.className = 'detail-view-headline';
-    topArea.appendChild(headline);
-
-    const textArea = document.createElement('div');
-    textArea.className = 'detail-view-text-area';
-    overlayNode.appendChild(textArea);
-
-    const description = document.createElement('p');
-    description.id = 'infoOverlayDescription';
-    description.innerText = 'Default Text'
-    description.setAttribute("overflow-y", "scroll");
-    textArea.appendChild(description);
-
-    const link_container = document.createElement('div');
-    const links = document.createElement('div');
-    const linkClasses = getLinkClasses();
-
-    link_container.id = 'link_container';
-    link_container.className = 'bottom container';
-    links.className = 'tab';
-    links.id = 'links';
-
-    for(i = 0; i < linkClasses.length; i++){
-
-        const linkType = linkClasses[i];
-        const tablink = document.createElement('button');
-        tablink.className = 'tablinks';
-        tablink.id = linkType + "_id";
-        tablink.innerHTML = linkType[0] + linkType[1] + linkType[2];
-        tablink.style = "background-color: " + edgeColors[linkClasses[i]];
-        tablink.setAttribute("onclick", "openTab(event, " + linkType + "_id)"); //unusual function call
-        links.appendChild(tablink);
-
-    }
-
-    link_container.appendChild(links);
-
-    for(i = 0; i < linkClasses.length; i++){
-
-        const linkType = linkClasses[i];
-        const tabcontent = document.createElement('div');
-        tabcontent.className = "tabcontent";
-        tabcontent.id = linkType + "_id_content";
-        tabcontent.style = "background-color: " + edgeColors[linkClasses[i]];
-        link_container.appendChild(tabcontent);
-
-    }
-
-    overlayNode.appendChild(link_container);
-
-    jQuery('#infoOverlayCloseButton').click(function () {
-        jQuery('#infoOverlay').slideUp('fast');
-    });
-
-    //sceneNode.appendChild(overlayNode);
-
-}
-
-
-function createLinkOverlay() {
-    const sceneNode = getCanvasDivNode();
-    const overlayNode = document.createElement('div');
-    overlayNode.className = 'link-overlay';
-    //overlayNode.innerText = 'Hello there!';
-    sceneNode.insertBefore(overlayNode, sceneNode.childNodes[2])
-
-    const linkClasses = getLinkClasses();
-    const chars = Math.max.apply(Math, linkClasses.map(function (c) { return c.length; }));
-
-    for (let i=0; i<linkClasses.length; i++) {
-        const relation = document.createElement('div');
-        relation.className = 'relation';
-        relation.innerHTML = "<p>" + linkClasses[i] + "</p>";
-        overlayNode.appendChild(relation);
-
-        const colorStrip = document.createElement('div');
-        colorStrip.className = 'rel-container';
-        colorStrip.style = "background-color: " + edgeColors[linkClasses[i]] + "; width: " + 10 * chars + "px;";
-        relation.appendChild(colorStrip);
-    }
-}
-
-function add_fullscreen_mode_button() {
-    const sceneNode = document.getElementById('3d-graph');
-    const overlayNode = document.createElement('button');
-    overlayNode.className = 'fullscreen_button';
-    overlayNode.innerText = 'fullscreen';
-    overlayNode.addEventListener("click", fullscreen_mode);
-    sceneNode.appendChild(overlayNode);
-}
-
-function fullscreen_mode(){
-    if(getCanvasDivNode().requestFullscreen) {
-        getCanvasDivNode().requestFullscreen().catch();
-    }
-}
-
-function resize_canvas() {
-    if(document.fullscreenElement == getCanvasDivNode()) {
-        Graph.height(screen.height);
-        Graph.width(screen.width);
-    } else {
-        Graph.height(window.innerHeight - 200);
-        Graph.width(getWidth());
-    }
-}
-
-function add_fullscreen_Listener() {
-    getCanvasDivNode().addEventListener("fullscreenchange", resize_canvas);
-}
-
-function add_background() {
-    const sphereGeometry = new THREE.SphereGeometry(20000, 32, 32);
-    //const planeGeometry = new THREE.PlaneGeometry(1000, 1000, 1, 1);
-    const loader = new THREE.TextureLoader();
-    //const planeMaterial = new THREE.MeshLambertMaterial({color: 0xFF0000, side: THREE.DoubleSide}); //THREE.BackSide
-    const planeMaterial = new THREE.MeshBasicMaterial({map: loader.load(plugin_path + 'backgrounds/background_3.jpg'), side: THREE.DoubleSide}); //THREE.BackSide
-    const mesh = new THREE.Mesh(sphereGeometry, planeMaterial);
-    mesh.position.set(0, 0, 0);
-    //mesh.rotation.set(0.5 * Math.PI, 0, 0);
-
-    Graph.scene().add(mesh);
-}
-
-
-function updateLinks() {
-    const gData = Graph.graphData()
-    // cross-link node objects
-    gData.links.forEach(link => {
-        const a = link.source;
-        const b = link.target;
-        if (!a.neighbors) a.neighbors = [];
-        if (!b.neighbors) b.neighbors = [];
-        a.neighbors.push(b);
-        b.neighbors.push(a);
-
-        if (!a.links) a.links = [];
-        if (!b.links) b.links = [];
-        a.links.push(link);
-        b.links.push(link);
-    });
-    Graph.graphData(gData)
-}
-
-
-
-function handleNodeClick(node) {
-    focusOnNode(node);
-    updateInfoOverlay(node);
-}
-
-
-function updateInfoOverlay(node) {
-    jQuery('#infoOverlayHeadline').text(node.name);
-    if ('image' in node) {
-        jQuery('#infoOverlayImage').attr('src', plugin_path + 'datasets/images/' + node.image);
-    } else {
-        jQuery('#infoOverlayImage').attr('src', plugin_path + 'datasets/images/default.jpg');
-    }
-
-    if ('description' in node) {
-        jQuery('#infoOverlayDescription').text(node.description);
-    } else {
-        jQuery('#infoOverlayDescription').text('Default Text');
-    }
-
-    updateTabs(node);
-
-    jQuery('#infoOverlay').slideDown('fast');
-}
-
-function updateTabs(node){
-    //tabs of the links to other nodes:
-    //delete old nodes from tabcontent
-    tabcontent = document.getElementsByClassName("tabcontent");
-    for (i = 0; i < tabcontent.length; i++) {
-        while (tabcontent[i].firstChild){
-            tabcontent[i].removeChild(tabcontent[i].lastChild);
-        }
-    }
-    //add new nodes to tabcontent
-    for (i = 0; i < tabcontent.length; i++) {                                   //for every type of link
-        node.links.forEach(link => {                                            //and for every link
-            if(link.type + '_id_content' == tabcontent[i].id){                  //is checked if the type is equal
-                const linkButton = document.createElement('div');      //and if so a new element is created
-                linkButton.className = "link img";
-                var node2;
-                if(link.source == node){
-                    node2 = link.target;
-                }
-                else if(link.target == node){
-                    node2 = link.source;
-                }
-                linkButton.id = "linkButton_" + node2.id;
-                const nodeID = node2.id;
-
-                const linkImage = document.createElement('img');
-                const linkTitle = document.createElement('div');
-
-                if ('image' in node2) {
-                    linkImage.src = plugin_path + 'datasets/images/' + node2.image;
-                } else if(!('image' in node2) && ('id' in node2)) {
-                    linkImage.src = plugin_path + 'datasets/images/default.jpg';
-                }
-
-                linkTitle.className = "link title";
-                linkTitle.innerHTML = node2.name;
-
-                //linkButton.appendChild(linkTitle);
-                linkButton.appendChild(linkImage);
-
-                linkButton.addEventListener('click', function (){focusOnNodeId(nodeID)});
-                tabcontent[i].appendChild(linkButton);
-            }
-        });
-    }
-}
-
-function focusOnNodeId(id) {
-    const gData = Graph.graphData();
-
-    gData.nodes.forEach(node => {
-        if (node.id === id) {
-            handleNodeClick(node);
-        }
-    })
-}
-
-function focusOnNode(node) {
-    // Aim at node from outside it
-    const distance = 250;
-    const distRatio = 1 + distance/Math.hypot(node.x, node.y, node.z);
-
-    Graph.cameraPosition(
-        { x: node.x * distRatio, y: node.y * distRatio, z: node.z * distRatio }, // new position
-        node, // lookAt ({ x, y, z })
-        1000  // ms transition duration
-    );
-}
-
-
-function nodeHover(node) {
-
-    // no state change
-    if ((!node && !highlightNodes.size) || (node && hoverNode === node)) return;
-
-    highlightNodes.clear();
-    highlightLinks.clear();
-    if (node) {
-        highlightNodes.add(node);
-        node.neighbors.forEach(neighbor => highlightNodes.add(neighbor));
-        node.links.forEach(link => highlightLinks.add(link));
-    }
-
-    hoverNode = node || null;
-    updateHighlight();
-}
-
-
-function linkHover(link) {
-    highlightNodes.clear();
-    highlightLinks.clear();
-
-    if (link) {
-        highlightLinks.add(link);
-        highlightNodes.add(link.source);
-        highlightNodes.add(link.target);
-    }
-
-    updateHighlight();
-}
-
-function linkColor(link) {
-    if ('type' in link) {
-        return edgeColors[link.type]
-    }
-    return 'rgb(255, 255, 255)'
-}
-
-
-function updateHighlight() {
-    // trigger update of highlighted objects in scene
-    Graph
-        .nodeColor(Graph.nodeColor())
-        .linkWidth(Graph.linkWidth())
-        .linkDirectionalParticles(Graph.linkDirectionalParticles());
-}
-
-//is used in createInfoOverlay, as an unusual function call to open link-tabs
-function openTab (event, tab) {
-    var i, tabcontent, tablinks;
-
-    // Get all elements with class="tabcontent" and hide them
-    tabcontent = document.getElementsByClassName("tabcontent");
-    for (i = 0; i < tabcontent.length; i++) {
-        tabcontent[i].style.display = "none";
-    }
-
-    // Get all elements with class="tablinks" and remove the class "active"
-    tablinks = document.getElementsByClassName("tablinks");
-    for (i = 0; i < tablinks.length; i++) {
-        tablinks[i].className = tablinks[i].className.replace(" active", "");
-    }
-
-    // Show the current tab, and add an "active" class to the button that opened the tab
-    document.getElementById(tab.id + "_content").style.display = "flex";
-    event.currentTarget.className += " active";
-}
\ No newline at end of file
diff --git a/knowledge-space.php b/knowledge-space.php
index c9f5abddfec9eaa94051c5d975d75a21688d93ab..65aaf3d59d26d35f95229e5c1757c7c8bf64b97f 100644
--- a/knowledge-space.php
+++ b/knowledge-space.php
@@ -19,10 +19,16 @@ function ks_add_graph(): string
     $variables = "<script> 
                   var plugin_path = '$plugin_dir';
                   </script>";
-    $script_path = $plugin_dir.'graph.js';
-    $script = "<script src='$script_path'></script>";
+    $script_path1 = $plugin_dir.'display'.DIRECTORY_SEPARATOR.'infooverlay.js';
+    $script_path2 = $plugin_dir.'display'.DIRECTORY_SEPARATOR.'linkoverlay.js';
+    $script_path3 = $plugin_dir.'display'.DIRECTORY_SEPARATOR.'graph.js';
 
-    return $three . $renderer .$renderer2 . $graph . $div . $variables . $script;
+    $script1 = "<script src='$script_path1'></script>";
+    $script2 = "<script src='$script_path2'></script>";
+    $script3 = "<script src='$script_path3'></script>";
+
+
+    return $three . $renderer .$renderer2 . $graph . $div . $variables . $script1 . $script2 .$script3;
 }
 
 function ks_add_editor(): string