Skip to content
Snippets Groups Projects
Commit 2ae69bbf authored by Maximilian Giller's avatar Maximilian Giller :squid:
Browse files

Merge branch 'master' of gitlab.ibr.cs.tu-bs.de:alg/knowledge-space-wp-plugin

parents c5bbc77d 9d155f17
No related branches found
No related tags found
No related merge requests found
Pipeline #55695 passed
......@@ -2,32 +2,17 @@
display: flex;
}
.detail-view-info-area::-webkit-scrollbar {
.fancy-scrollbar::-webkit-scrollbar {
width: 6px;
background-color: #f5f5f5;
}
.detail-view-info-area::-webkit-scrollbar-track {
.fancy-scrollbar::-webkit-scrollbar-track {
-webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
background-color: #f5f5f5;
}
.detail-view-info-area::-webkit-scrollbar-thumb {
background-color: darkgray;
}
.bottom-container-tab-content::-webkit-scrollbar {
width: 6px;
height: 8px;
background-color: #f5f5f5;
}
.bottom-container-tab-content::-webkit-scrollbar-track {
-webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
background-color: #f5f5f5;
}
.bottom-container-tab-content::-webkit-scrollbar-thumb {
.fancy-scrollbar::-webkit-scrollbar-thumb {
background-color: darkgray;
}
......@@ -196,81 +181,118 @@
width: 78px;
}
.bottom-container-tab-content {
display: none;
/*padding: 6px 0px;*/
/*border-top: none;*/
overflow-x: auto;
/*height: 100px;*/
height: 100%;
.neighbor-container {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
max-height: 50%;
overflow: auto;
background-color: #ffffff;
}
.active-tab-nav {
color: black;
/*New Section */
.neighbor-collapsible-title {
background-color: #ffffff;
color: #444;
cursor: pointer;
padding: 9px 9px 9px 0;
width: 100%;
display: flex;
font-weight: bold;
text-align: left;
font-size: 20px;
opacity: 100%;
border: 2px solid white;
outline: none;
flex-direction: column;
position: relative;
}
.active-tab-content {
.neighbor-collapsible-section {
background-color: #ffffff;
color: #444;
cursor: pointer;
padding: 9px 9px 9px 0;
width: 100%;
border: 2px solid white;
text-align: left;
outline: none;
font-size: 15px;
display: flex;
align-items: center;
flex-direction: column;
position: relative;
font-weight: bold;
opacity: 80%;
}
.hidden-tab {
display: none;
.activation-hover-title, .neighbor-collapsible-title:hover {
background-color: #ccc;
}
.bottom-container {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
.activation-hover-section, .neighbor-collapsible-section:hover {
background-color: #ccc;
}
.bottom-container-nav {
height: 35px;
.neighbor-content-tabs {
padding: 0 18px;
display: inline-block;
width: 100%;
top: 0;
overflow: hidden;
background-color: #ffffff;
flex-direction: column;
margin-bottom: 10px;
}
.neighbor-content-linksection {
padding-top: 0;
padding-left: 5px;
display: flex;
flex-direction: row;
background-color: #ffffff;
flex-direction: column;
overflow: hidden;
}
.neighbor-content-link {
cursor: pointer;
margin: 1px;
font-size: 14px;
}
.activation-hover, .neighbor-content-link:hover {
color: red;
}
.bottom-container-links {
.neighbor-collapsible-marker-div {
position: absolute;
width: 100%;
height: 100px;
display: block;
height: 2px;
border: 1px solid red;
bottom: 0;
left: 0;
}
.bottom-container-link-text {
font-size: 8px;
/*font-size: 10px;*/
max-width: 65px;
font-weight: bold;
text-align: center;
.neighbor-collapsible-open-status-marker {
position: absolute;
right: 20px;
font-size: 26px;
color: #595858;
top: 2px;
bottom: 2px;
}
.link-img {
min-width: 70px;
width: 70px;
height: 70px;
margin: 10px;
pointer-events: all;
cursor: pointer;
border-radius: 50%;
overflow: hidden;
background-color: white;
display: flex;
align-items: center;
justify-content: center;
.neighbor-tab-open-status-marker {
position: absolute;
right: 20px;
font-size: 15px;
color: #595858;
top: 10px;
bottom: 10px;
}
.bottom-container-nav-tab {
height: 100%;
display: flex;
padding: 0 8px;
min-width: 10%;
text-align: center;
line-height: 35px;
font-size: 0.7vw;
.neighbor-collapsible-wrapper {
transition:height 0.3s ease-out;
height:0;
overflow:hidden;
}
......@@ -74,5 +74,6 @@ class FilterOverlay {
} else {
target.style.opacity = 1.0;
}
this.graph.infoOverlay.bottomMenu.toggleCategory(target.type);
}
}
import * as Helpers from "../helpers";
import jQuery from "jquery";
import * as Config from "../../config";
import { createHTMLElement } from "../helpers";
export { NodeNeighborOverlay };
......@@ -14,12 +13,11 @@ class NodeNeighborOverlay {
this.parentNode = parentNode;
this.infoOverlay = infoOverlay;
this.type = type;
this.contentTab = null;
this.activeTabNav = null; // The currently selected tab handle
this.activeTabContent = null; // The currently selected tab content
this.tabContentPages = {};
this.tabNavHandles = {};
this.tabContentPages = {}; // Page content - links to other nodes
this.tabNavHandles = {}; // Top-level handles of the content pages
this.tabPageVisibility = {}; // Visibility of each content page
}
/**
......@@ -28,139 +26,145 @@ class NodeNeighborOverlay {
*/
create() {
const bottomContainerDiv = Helpers.createDiv(
"bottom-container",
"neighbor-container",
this.parentNode
);
const bottomContainerNavDiv = Helpers.createDiv(
"bottom-container-nav",
bottomContainerDiv
);
const bottomContainerLinkDiv = Helpers.createDiv(
"bottom-container-links",
bottomContainerDiv.classList.add("fancy-scrollbar");
// 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
const contentTab = Helpers.createDiv(
"neighbor-content-tabs",
bottomContainerDiv
);
//contentTab.classList.add("neighbor-collapsible-wrapper");
this.contentTab = contentTab;
coll.addEventListener("click", () => {
if (contentTab.style.height === "0px") {
contentTab.style.height = "auto";
} else {
contentTab.style.height = "0px";
}
});
const colors =
this.type === "link"
? this.graph.edgeColors
: this.graph.nodeColors;
for (const [cls, color] of Object.entries(colors)) {
const navTab = Helpers.createDiv(
"bottom-container-nav-tab",
bottomContainerNavDiv
);
navTab.innerText = cls.slice(0, 3);
navTab.style.backgroundColor = color;
navTab.type = cls; // Attach the edge type to the DOM object to retrieve it during click events
jQuery(navTab).click((event) => this.openTabFromEvent(event));
this.tabNavHandles[cls] = navTab;
const tabContent = Helpers.createDiv(
"bottom-container-tab-content",
bottomContainerLinkDiv
);
tabContent.style.backgroundColor = color;
this.tabContentPages[cls] = tabContent;
this.createCollapsibleTab(contentTab, cls, color);
}
this.initializeActive(bottomContainerNavDiv, bottomContainerLinkDiv);
}
/**
* Initializes the activeTabNav and activeTabContent variables to a random edge type.
* @param {Element} bottomContainerNavDiv
* @param {Element} bottomContainerLinkDiv
* Creates a new collapsible tab and content area for a specific node.
* @param {HTMLElement} parent Parent of the new tab.
* @param {string} name Name of the node type class
* @param {string} color Color of the node type class
*/
initializeActive(bottomContainerNavDiv, bottomContainerLinkDiv) {
this.activeTabNav = bottomContainerNavDiv.firstChild;
this.activeTabContent = bottomContainerLinkDiv.firstChild;
createCollapsibleTab(parent, name, color) {
// Creating the collapsible tabs for the different chapters
const collTab = Helpers.createDiv("button", parent);
collTab.className = "neighbor-collapsible-section";
collTab.innerText = name;
collTab.type = name;
this.tabNavHandles[name] = collTab;
this.tabPageVisibility[name] = false;
const collTabMarker = Helpers.createDiv(
"neighbor-collapsible-marker-div",
collTab
);
collTabMarker.style.borderColor = color;
collTabMarker.style.backgroundColor = color;
this.activeTabContent.classList.add("active-tab-content");
this.activeTabNav.classList.add("active-tab-nav");
this.activeTabNav.innerText = this.activeTabNav.type;
}
const openMarkerTabs = Helpers.createDiv(
"neighbor-tab-open-status-marker",
collTab
);
openMarkerTabs.innerText = "+";
collTab.marker = openMarkerTabs;
/**
* Click event handler for the tab headers of the bottom menu.
* @param event
*/
openTabFromEvent(event) {
const navTab = event.target;
const cls = navTab.type;
this.openTab(cls);
}
// Content of the different tabs
const collTabContent = Helpers.createDiv(
"neighbor-content-linksection",
parent
);
collTabContent.classList.add("neighbor-collapsible-wrapper");
collTabContent.type = name;
openTab(cls) {
this.activeTabNav.classList.remove("active-tab-nav");
this.activeTabNav.innerText = this.activeTabNav.innerText.slice(0, 3);
this.tabNavHandles[cls].classList.add("active-tab-nav");
this.tabNavHandles[cls].innerText = cls;
const list = createHTMLElement("ul", collTabContent);
list.style.margin = "0px";
this.activeTabContent.classList.remove("active-tab-content");
this.tabContentPages[cls].classList.add("active-tab-content");
collTabContent.list = list;
collTabContent.marker = openMarkerTabs;
this.tabContentPages[name] = collTabContent;
this.activeTabNav = this.tabNavHandles[cls];
this.activeTabContent = this.tabContentPages[cls];
collTab.addEventListener("click", () => {
this.toggleSectionVisibility(name);
});
}
toggleTabVisibility(cls) {
this.tabNavHandles[cls].classList.toggle("bottom-container-nav-tab");
this.tabNavHandles[cls].classList.toggle("hidden-tab");
const tcc = this.tabContentPages[cls].classList;
tcc.toggle("bottom-container-tab-content");
tcc.toggle("hidden-tab");
// If the tab gets hidden and is the active tab, search for an alternative nav tab to become the new active tab.
if (tcc.contains("hidden-tab")) {
if (tcc.contains("active-tab-nav")) {
for (const tab of Object.values(this.tabNavHandles)) {
if (!tab.classList.contains("hidden-tab")) {
this.openTab(tab.type);
break;
}
}
}
/**
* Toggles the visibility of a specific section
* @param {string} name Id of the section
*/
toggleSectionVisibility(name) {
if (this.tabPageVisibility[name]) {
this.collapseSection(name);
} else {
// If all tabs are hidden, the new tab should become the active tab.
if (this.activeTabNav.classList.contains("hidden-tab")) {
this.openTab(cls);
}
this.expandSection(name);
}
}
/**
* Clears the images from all tab content pages.
* Collapses the content area of a specific section
* @param {string} name Id of the section
*/
collapseSection(name) {
this.tabPageVisibility[name] = false;
const section = this.tabContentPages[name];
section.style.height = "0px";
section.marker.innerText = "+";
}
/**
* Expands the content area of a specific section
* @param {string} name Id of the section
*/
expandSection(name) {
this.tabPageVisibility[name] = true;
const section = this.tabContentPages[name];
section.style.height = `${section.scrollHeight}px`;
section.marker.innerText = "-";
}
/**
* 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();
page.list.replaceChildren();
}
}
/**
* Creates a new image (with link) for the given target node.
* Creates a new list element for the given target node.
* @param target
* @returns {HTMLDivElement}
* @returns {HTMLLIElement}
*/
createReference(target) {
const linkDiv = document.createElement("div");
linkDiv.className = "link-img";
if ("image" in target) {
const linkImage = document.createElement("img");
linkImage.src =
Config.PLUGIN_PATH + "datasets/images/" + target.image;
linkDiv.appendChild(linkImage);
}
if ("name" in target) {
Helpers.createHTMLElement("p", linkDiv, {
className: "bottom-container-link-text",
innerText: target.name,
});
}
jQuery(linkDiv).on("click", () => {
const linkDiv = document.createElement("li");
const linkText = document.createTextNode(target.name);
linkDiv.className = "neighbor-content-link";
linkDiv.appendChild(linkText);
linkDiv.addEventListener("click", () => {
this.graph.focusOnNode(target);
this.infoOverlay.updateInfoOverlay(target);
});
......@@ -173,15 +177,51 @@ class NodeNeighborOverlay {
*/
updateTabs(node) {
this.clearTabContentPages();
for (const link of node.links) {
const target = link.source == node ? link.target : link.source;
const target = link.source === node ? link.target : link.source;
const reference = this.createReference(target);
if (this.type === "link") {
this.tabContentPages[link.type].appendChild(reference);
this.tabContentPages[link.type].list.appendChild(reference);
} else {
this.tabContentPages[target.type].appendChild(reference);
this.tabContentPages[target.type].list.appendChild(reference);
}
}
this.updatePageVisibility();
}
/**
* Updates the content page visibility on node change.
* Hides all empty content pages.
*/
updatePageVisibility() {
for (const page of Object.values(this.tabContentPages)) {
if (!page.list.hasChildNodes()) {
this.tabNavHandles[page.type].style.display = "none";
page.style.display = "none";
} else {
this.tabNavHandles[page.type].style.display = "flex";
page.style.display = "flex";
if (this.tabPageVisibility[page.type]) {
page.style.height = `${page.list.scrollHeight}px`;
}
}
}
}
/**
* Toggle the visibility for a category
* @param {string} type The name of the category that should be toggled
*/
toggleCategory(type) {
const page = this.tabContentPages[type];
const handle = this.tabNavHandles[type];
if (handle.style.display === "flex") {
page.style.display = "none";
handle.style.display = "none";
} else if (page.list.hasChildNodes()) {
page.style.display = "flex";
handle.style.display = "flex";
}
}
}
import jQuery from "jquery";
// import { NodeNeighborOverlay } from "./neighbors";
import { NodeNeighborOverlay } from "./neighbors";
import * as Helpers from "../helpers";
import * as Config from "../../config";
......@@ -16,7 +16,7 @@ class NodeInfoOverlay {
*/
constructor(graph) {
this.graph = graph;
// this.bottomMenu = null;
this.bottomMenu = null;
}
/**
......@@ -26,13 +26,13 @@ class NodeInfoOverlay {
create() {
const overlayDiv = this.createOverlayMainDiv();
this.createOverlayElements(overlayDiv);
// this.bottomMenu = new NodeNeighborOverlay(
// this.graph,
// overlayDiv,
// this,
// "node"
// );
// this.bottomMenu.create();
this.bottomMenu = new NodeNeighborOverlay(
this.graph,
overlayDiv,
this,
"node"
);
this.bottomMenu.create();
jQuery("#infoOverlayCloseButton").click(function () {
jQuery("#infoOverlay").slideUp("fast");
......@@ -59,6 +59,7 @@ class NodeInfoOverlay {
"detail-view-info-area",
overlayNode
);
infoArea.classList.add("fancy-scrollbar");
const topArea = Helpers.createDiv("detail-view-top-area", infoArea);
......@@ -170,7 +171,7 @@ class NodeInfoOverlay {
linkArea.hide();
}
// this.bottomMenu.updateTabs(node);
this.bottomMenu.updateTabs(node);
jQuery("#infoOverlay").slideDown("fast");
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment