import { Component } from "./component.js";
import { Label } from "./label.js";
import { Style } from "./style.js";
/**
* Creates a clickable pushbutton with a text label.
* <div><img src="https://www.minicomps.org/images/button.png"/></div>
* @example
* const panel = new Panel(document.body, 20, 20, 200, 200);
* new Button(panel, 20, 20, "Click me", event => console.log("clicked!"));
* @extends Component
*/
export class Button extends Component {
/**
* Constructor
* @param {HTMLElement} parent - The element to add this button to.
* @param {number} x - The x position of the button. Default 0.
* @param {number} y - The y position of the button. Default 0.
* @param {string} label - The text label of the button. Default empty string.
* @param {function} defaultHandler - A function that will handle the "click" event.
*/
constructor(parent, x, y, label, defaultHandler) {
super(parent, x, y);
this._label = label || "";
this._createChildren();
this._createStyle();
this._createListeners();
this.setSize(Button.width, Button.height);
this.addEventListener("click", defaultHandler);
this._addToParent();
}
//////////////////////////////////
// Core
//////////////////////////////////
_createChildren() {
this._wrapper.tabIndex = 0;
this._setWrapperClass("MinimalButton");
this._textLabel = new Label(this._wrapper, 0, 0, this._label);
this._textLabel.autosize = false;
this._textLabel.align = "center";
}
_createStyle() {
const style = document.createElement("style");
style.textContent = Style.button;
this.shadowRoot.append(style);
}
_createListeners() {
this._onClick = this._onClick.bind(this);
this._onKeyUp = this._onKeyUp.bind(this);
this._wrapper.addEventListener("click", this._onClick);
this._wrapper.addEventListener("keyup", this._onKeyUp);
}
//////////////////////////////////
// Handlers
//////////////////////////////////
_onClick(event) {
event.stopPropagation();
if (this._enabled) {
this.dispatchEvent(new Event("click"));
}
}
_onKeyUp(event) {
if (event.keyCode === 13 && this._enabled) {
this._wrapper.click();
}
}
//////////////////////////////////
// Public
//////////////////////////////////
/**
* Adds a handler function for the "click" event on this button.
* @param {function} handler - A function that will handle the "click" event.
* @returns This instance, suitable for chaining.
*/
addHandler(handler) {
this.addEventListener("click", handler);
return this;
}
/**
* Gets the label of this button.
* @returns The text of the label.
*/
getLabel() {
return this._label;
}
setEnabled(enabled) {
if (this._enabled === enabled) {
return this;
}
super.setEnabled(enabled);
this._textLabel.enabled = enabled;
if (this._enabled) {
this._wrapper.setAttribute("class", "MinimalButton");
this._wrapper.tabIndex = 0;
} else {
this._wrapper.setAttribute("class", "MinimalButtonDisabled");
this._wrapper.tabIndex = -1;
}
return this;
}
setHeight(height) {
super.setHeight(height);
this._textLabel.height = height;
return this;
}
/**
* Sets the label of this button.
* @param {string} label - The label to set on this button.
* @returns this instance, suitable for chaining.
*/
setLabel(label) {
this._label = label;
this._textLabel.text = label;
return this;
}
setWidth(width) {
super.setWidth(width);
this._textLabel.width = width;
return this;
}
//////////////////////////////////
// Getters/Setters
// alphabetical. getter first.
//////////////////////////////////
/**
* Sets and gets the text shown in the button's label.
*/
get label() {
return this.getLabel();
}
set label(label) {
this.setLabel(label);
}
}
//////////////////////////////////
// Getters/Setters
// alphabetical. getter first.
//////////////////////////////////
/**
* Default width of all Buttons.
*/
Button.width = 100;
/**
* Default height of all Buttons.
*/
Button.height = 20;
customElements.define("minimal-button", Button);