import { UiElement } from "../UiElement.js";
import "./SidebarElement.css";
export { SidebarElement };
/**
* Extension of UiElement to be used as a baseclass
* for Elements inside a sidebar. A title and a
* collapse feature is added to the element.
*
* @author rhess <robin.hess@awi.de>
* @memberof vef.ui.sidebar
*/
class SidebarElement extends UiElement {
class = "sidebar-element";
html = `
<div class="sidebar-element-header">
<div class="sidebar-element-header-inner">
<span class="sidebar-element-title-span">
<span class="sidebar-element-collapse fas fa-chevron-down"></span>
<span class="sidebar-element-title"></span>
</span>
<span class="notification-counter"></span>
<span class="sidebar-element-tools"></span>
</div>
</div>
<div class="sidebar-element-content"></div>
`;
/**
* @param {string/HTMLElement} target id or HTMLElement (optional)
* @param {Object} events events for the EventObject (optional)
*/
constructor(target, events) {
super(target, Object.assign({
"collapse": [],
"expand": []
}, events || {}));
this.setClass(this.class);
this.setHtml(this.html);
this.content_ = this.query(".sidebar-element-content");
this.title_ = this.query(".sidebar-element-title");
this.collapseButton_ = this.query(".sidebar-element-collapse");
this.toolContainer_ = this.query(".sidebar-element-tools");
this.notificationCounter_ = this.query(".notification-counter");
this.timeout_ = null;
this.currentHeight_ = null;
this.initEvents_();
}
/**
* init the element base structure
*
* @private
*/
initEvents_() {
this.collapseButton_.addEventListener("click", () => {
(this.content_.classList.contains("hidden"))
? this.expand()
: this.collapse();
}, false);
}
/**
* return the content DOM-element
*/
getContentContainer() {
return this.content_;
}
/**
* set the content of the element
*/
setContent(content) {
if (typeof content === "string") {
this.content_.innerHTML = content;
} else if (content instanceof HTMLElement) {
this.content_.innerHTML = "";
this.content_.appendChild(content);
}
}
/**
* change the title displayed in the
* header of the element
*/
setTitle(title) {
if(title == undefined) return
this.title_.innerText = title;
this.title_.title = title;
}
/**
* collapse the content of the element
*/
collapse() {
if (this.timeout_) clearTimeout(this.timeout_);
this.content_.classList.add("hidden");
this.content_.style.overflow = "hidden";
// set max height to current height for animation
const rect = this.content_.getBoundingClientRect();
this.currentHeight_ = rect.height + "px";
this.content_.style.maxHeight = this.currentHeight_;
// reflows DOM element before playing animation;
this.content_.getClientRects();
this.content_.style.maxHeight = "0px";
// set "collapsed" state when animation is finished
this.timeout_ = setTimeout(() => {
this.content_.classList.add("collapsed");
this.timeout_ = null;
}, 333);
this.collapseButton_.classList.remove("fa-chevron-down");
this.collapseButton_.classList.add("fa-chevron-right");
this.fire("collapse", this);
}
/**
* expand the content of the element
*/
expand() {
if (this.timeout_) clearTimeout(this.timeout_);
this.content_.style.maxHeight = "0px";
this.content_.classList.remove("hidden", "collapsed");
// reflows DOM element before playing animation;
this.content_.getClientRects();
this.content_.style.maxHeight = this.currentHeight_ || (window.innerHeight + "px");
// remove max-height after the animation is finished
this.timeout_ = setTimeout(() => {
this.content_.style.maxHeight = "unset";
this.content_.style.overflow = "unset";
this.timeout_ = null;
}, 333);
this.collapseButton_.classList.remove("fa-chevron-right");
this.collapseButton_.classList.add("fa-chevron-down");
this.fire("expand", this);
}
/**
* add a tool to the header as html or string.
* If a customElement is defined, the other arguments have no effect
*
* @param {string} icon icon css classes
* @param {string} onClick callback function for click event. boolean payload defines enabled-state
* @param {string} tooltip (optional) tooltip when hovering the mouse
* @param {boolean} toggleMode switching between two states on each click
* @param {HTMLElement} customElement (optional) custom element
*/
addTool(icon, onClick, tooltip, toggleMode, customElement) {
if (customElement instanceof HTMLElement) {
this.toolContainer_.insertAdjacentElement("afterbegin", customElement);
} else {
const tool = document.createElement("div");
tool.setAttribute("tabindex", "0");
tool.classList.add("sidebar-element-tool", ...icon.split(" "));
if (typeof tooltip == "string") {
tool.title = tooltip.trim();
}
tool.addEventListener("click", e => {
if (toggleMode) {
if (tool.classList.contains("enabled")) {
tool.classList.remove("enabled");
onClick(false, e);
} else {
tool.classList.add("enabled");
onClick(true, e);
}
} else {
onClick(true, e);
}
});
tool.addEventListener("keydown", e => {
if(e.key != "Enter") return;
if (toggleMode) {
if (tool.classList.contains("enabled")) {
tool.classList.remove("enabled");
onClick(false, e);
} else {
tool.classList.add("enabled");
onClick(true, e);
}
} else {
onClick(true, e);
}
});
this.toolContainer_.insertAdjacentElement("afterbegin", tool);
}
}
/**
* Set value for the notification bubble in the elements header
* @param {number} cnt
*/
setNotificationCount(cnt) {
if (Number.isFinite(cnt) && (cnt > 0)) {
this.notificationCounter_.innerText = cnt;
} else {
this.notificationCounter_.innerText = "";
}
}
/**
* disable pointer events and make content transparent
*/
disable() {
this.setClass("disabled");
}
/**
* enable pointer events and remove transparency of the content
*/
enable() {
this.removeClass("disabled");
}
}