pvbemu/web/toolkit/Checkbox.js

158 lines
4.2 KiB
JavaScript

let register = Toolkit => Toolkit.Checkbox =
// Check box
class Checkbox extends Toolkit.Component {
///////////////////////// Initialization Methods //////////////////////////
constructor(app, options = {}) {
super(app, options = Object.assign({
class : "tk checkbox",
role : "checkbox",
tabIndex: "0"
}, options, { style: Object.assign({
alignItems : "center",
display : "inline-grid",
gridTemplateColumns: "max-content auto"
}, options.style || {}) }));
// Configure element
this.element.setAttribute("aria-checked", "false");
this.addEventListener("keydown" , e=>this.onKeyDown (e));
this.addEventListener("pointerdown", e=>this.onPointerDown(e));
this.addEventListener("pointermove", e=>this.onPointerMove(e));
this.addEventListener("pointerup" , e=>this.onPointerUp (e));
// Icon area
this.box = document.createElement("div");
this.box.className = "tk box";
this.append(this.box);
// Display text
this.uiLabel = new Toolkit.Label(app);
this.add(this.uiLabel);
// Configure options
this.checked = options.checked;
this.disabled = !!options.disabled;
this.instant = !!options.instant;
}
///////////////////////////// Event Handlers //////////////////////////////
// Key press
onKeyDown(e) {
if (
!(e.altKey || e.ctrlKey || e.shiftKey || this.disabled) &&
(e.key == " " || e.key == "Enter")
) this.setChecked(!this.checked);
}
// Pointer down
onPointerDown(e) {
// Gain focus
if (!this.disabled)
this.element.focus();
else e.preventDefault();
// Do not drag
if (
e.button != 0 ||
this.disabled ||
this.element.hasPointerCapture(e.pointerId)
) return;
// Begin dragging
this.element.setPointerCapture(e.pointerId);
// Use instant activation
if (this.instant)
return this.onPointerUp(e);
// Do not use instant activation
this.element.classList.add("pushed");
Toolkit.handle(e);
}
// Pointer move
onPointerMove(e) {
// Do not drag
if (!this.element.hasPointerCapture(e.pointerId))
return;
// Process dragging
this.element.classList[this.isWithin(e) ? "add" : "remove"]("pushed");
Toolkit.handle(e);
}
// Pointer up
onPointerUp(e) {
// Do not activate
if (e.button != 0 || !this.element.hasPointerCapture(e.pointerId))
return;
// End dragging
this.element.releasePointerCapture(e.pointerId);
this.element.classList.remove("pushed");
Toolkit.handle(e);
// Activate the check box if applicable
if (this.isWithin(e))
this.setChecked(this.checked !== true);
}
///////////////////////////// Public Methods //////////////////////////////
// The check box is checked
get checked() {
let ret = this.element.getAttribute("aria-checked");
return ret == "mixed" ? ret : ret == "true";
}
set checked(checked) {
checked = checked == "mixed" ? checked : !!checked;
if (checked == this.checked)
return;
this.element.setAttribute("aria-checked", checked);
}
// Specify the display text
setText(text, localize) {
this.uiLabel.setText(text, localize);
}
///////////////////////////// Package Methods /////////////////////////////
// Update localization strings
localize() {
this.uiLabel.localize();
this.localizeTitle();
}
///////////////////////////// Private Methods /////////////////////////////
// Specify the checked state
setChecked(checked) {
checked = !!checked;
if (checked == this.checked)
return;
let previous = this.checked
this.checked = checked;
this.element.dispatchEvent(
Object.assign(new Event("input"), { previous: previous }));
}
}
export { register };