import { UiElement } from "../UiElement.js";
import "./SliderHeader.css";
export { SliderHeader };
/**
* Helper class for creating a header for the sliders with an operator Dropdown
*
* options = {
* title: string,
* operators: string[],
* defaultOperator: string,
* useInput: boolean,
* inputPattern: string,
* inputlength: number,
* inputType: string
* }
*
* @author rhess <robin.hess@awi.de>
* @memberof vef.ui.slider
*/
class SliderHeader extends UiElement {
constructor(target, options) {
super(target, {
"select": [],
"input": [],
"change": [],
"arrow_up": [],
"arrow_down": [],
"arrow_up_shift": [],
"arrow_down_shift": [],
"arrow_up_shift_ctrl": [],
"arrow_down_shift_ctrl": [],
"pos1": [],
"end": []
});
this.activeOperator_ = null
this.useInput_ = options.useInput;
this.inputType_ = options.inputType;
this.inputLength_ = options.inputLength;
this.initElement_(options.title || "");
this.setOperators(options.operators || ["=", "<", "≤", ">", "≥", "-"]);
this.select(options.defaultOperator || this.operators_[0]);
if (this.useInput_) this.initInputEvents_();
if (options.inputPattern) this.setPattern(options.inputPattern);
}
/**
* @param {string} title
* @private
*/
initElement_(title) {
this.setClass("slider-header");
this.setHtml(`
<div class="header-title">${title}:</div>
<${this.useInput_ ? ("input type='" + (this.inputType_ || "text") + "' required") : "div"}
${this.inputLength_ ? (" maxlength='" + this.inputLength_ + "'") : ""}
class="value-left"></${this.useInput_ ? "input" : "div"}>
<div class="operator-dropdown">
<div class="drop-down-title"></div>
<div class="drop-down-list"></div>
</div>
<${this.useInput_ ? ("input type='" + (this.inputType_ || "text") + "' required") : "div"}
${this.inputLength_ ? (" maxlength='" + this.inputLength_ + "'") : ""}
class="value-right"></${this.useInput_ ? "input" : "div"}>
`);
}
fireChange_(inputType, e) {
if (e.currentTarget.checkValidity()) {
this.fire("change", {
"type": inputType,
"value": e.currentTarget.value
});
}
}
fireInput_(inputType, e) {
this.fire("input", {
"type": inputType,
"value": e.currentTarget.value
});
}
/**
* Init the input events
* @private
*/
initInputEvents_() {
if (this.useInput_) {
// generator function for keypress event
const _keydown = (type) => {
return (e) => {
if (( e.ctrlKey && e.shiftKey && e.code == "ArrowUp")) {
e.preventDefault();
this.fire("arrow_up_shift_ctrl", type);
}else if ((e.ctrlKey && e.shiftKey && e.code == "ArrowDown")) {
e.preventDefault();
this.fire("arrow_down_shift_ctrl", type);
}else if ((e.shiftKey && e.code == "ArrowUp")) {
e.preventDefault();
this.fire("arrow_up_shift", type);
}else if ((e.shiftKey && e.code == "ArrowDown")) {
e.preventDefault();
this.fire("arrow_down_shift", type);
}else if ((e.code === "Home")) {
e.preventDefault();
this.fire("pos1", type);
}else if ((e.code === "End")) {
e.preventDefault();
this.fire("end", type);
}else if (e.code == "ArrowUp") {
e.preventDefault();
this.fire("arrow_up", type);
} else if ((e.code == "ArrowDown")) {
e.preventDefault();
this.fire("arrow_down", type);
}
}
};
const begin = this.query(".value-left");
begin.addEventListener("input", e => this.fireInput_("begin", e));
begin.addEventListener("change", e => this.fireChange_("begin", e));
begin.addEventListener("keydown", _keydown("begin"));
const end = this.query(".value-right");
end.addEventListener("input", e => this.fireInput_("end", e));
end.addEventListener("change", e => this.fireChange_("end", e));
end.addEventListener("keydown", _keydown("end"));
}
}
/**
* get the currently selected operator
*
* @returns {string}
*/
getOperator() {
return this.activeOperator_;
}
/**
* select an operator
*
* @param {string} operator
*/
select(operator) {
const dropdown = this.query(".operator-dropdown");
const items = dropdown.querySelectorAll(".list-item");
for (let i = 0; i < items.length; ++i) {
let item = items[i];
if (item.dataset.value == operator) {
item.style.display = "none";
} else {
item.style.display = "block";
}
}
dropdown.querySelector(".drop-down-title").innerText = operator;
this.activeOperator_ = operator;
this.fire("select", operator);
}
/**
* Set regex for string validation in the input
*
* @param {string} regex
*/
setPattern(regex) {
if (this.useInput_) {
this.query(".value-left").pattern = regex;
this.query(".value-right").pattern = regex;
}
}
/**
* populate the operator dropdown
*
* @param {string[]} operators
*/
setOperators(operators) {
this.operators_ = operators;
const tooltips = {
"-": "time range",
"=": "exact match",
"<": "less than",
"≤": "less than or equal to",
">": "greater than",
"≥": "greater than or equal to"
};
const list = this.query(".operator-dropdown .drop-down-list");
list.innerHTML = "";
for (let i = 0; i < operators.length; ++i) {
const operator = operators[i];
if (tooltips[operator]) {
const item = document.createElement("div");
item.innerText = operator;
item.title = tooltips[operator];
item.dataset.value = operator;
item.classList.add("list-item");
item.addEventListener("click", (e) => {
e.preventDefault();
this.select(operator);
});
list.appendChild(item);
}
}
}
/**
* Set a single value
*
* @param {string} type begin or end
* @param {*} value
*/
setValue(type, value) {
const selector = (type == "begin") ? "left" : "right";
const el = this.query(".value-" + selector);
const isSet = (value !== null) && (value !== undefined);
if (el.nodeName == "INPUT") {
el.value = (isSet) ? value : "";
el.disabled = !isSet;
} else {
el.innerText = (isSet) ? value : "";
}
}
/**
* set the values in the header
*
* @param {object} val {begin, end}
*/
setValues(val) {
if ([">", "<", "="].includes(this.activeOperator_)) {
this.setValue("begin", null);
this.setValue("end", val.begin);
} else {
this.setValue("begin", val.begin);
this.setValue("end", val.end);
}
}
}