import {Component_A} from './basic/as-component.js';
import {FP_Checkbox_A} from './fp-ext/fp-checkbox-ext.js';
import {ErrorCode} from './../exception/exceptionDesc.js';
/**
* @typedef TComponents.CheckboxProps
* @prop {object} [options] Additional options for the checkbox component
* Items in this object include:
* - **responsive** (boolean, default: false): Whether the checkbox should be responsive
* @prop {Function} [onCreated] Function to be called when the component is created
* @prop {Function} [onMounted] Function to be called when the component is mounted
* @prop {Function} [onChange] Function to be called when checkbox state changes
* @prop {string} [position] CSS position property
* @prop {number} [top] Top position in pixels
* @prop {number} [left] Left position in pixels
* @prop {number} [borderRadius] Border radius of the component
* @prop {number} [rotation] Rotation of the component in degrees
* @prop {number} [zIndex] Z-index of the component
* @prop {string} [text] Checkbox text
* @prop {string} [value] Checkbox value
* @prop {number} [selectedIndex] <span style="color:red; font-weight: bold;"> Invalid attribute.</span>
* @prop {string} [color] Color of the checkbox text
* @prop {object} [font] Font settings for the checkbox text
* This object controls text appearance:
* - **fontSize** (number, default: 12): Font size in pixels.
* - **fontFamily** (string, default: 'Segoe UI'): Font family name.
* - **style** (object): Font style configuration, containing `fontStyle`, `fontWeight`, `textDecoration`.
* @prop {object} [inputVar] Data binding configuration
* This object configures the bound input variable:
* - **type** (string): Input variable type. Default is `Component_A.INPUTVAR_TYPE.BOOL`
* - **func** (string): Binding behavior. Default is `Component_A.INPUTVAR_FUNC.CUSTOM`
* - **value** (*): Initial bound value, default is 0
* - **isHidden** (boolean, default: false): Whether the variable is hidden
* @prop {boolean} [enabled] Whether the checkbox is enabled
* @prop {boolean} [checked] Checked state of the checkbox
* @prop {string} [dataStruct] Data structure name for binding
* @memberof TComponents
*/
/**
* @ignore
*/
const logModule = 'as-checkbox-a';
/**
* @description Checkbox component that allows a single selection. Each checkbox can be separately checked or unchecked.
* This class focuses on the specific properties of the Checkbox component.
* Since it inherits from Accessor_A, all basic properties (e.g., height, width) are available but documented in the Accessor_A part.
* @class TComponents.Checkbox_A
* @extends TComponents.Component_A
* @memberof TComponents
* @param {HTMLElement} parent - HTML element that is going to be the parent of the component
* @param {TComponents.CheckboxProps} props - Properties of the checkbox component.
* @example
* const checkbox = new TComponents.Checkbox_A(document.body, {
* position: 'absolute',
* zIndex: 1000,
* text: 'Execute'
* });
*
* checkbox.render();
*/
export class Checkbox_A extends Component_A {
constructor(parent, props = {}) {
super(parent, props);
this._props;
this._bindData;
this._checkbox = new FP_Checkbox_A();
}
/**
* @description Returns the default values of class properties (excluding parent properties).
* @member TComponents.Checkbox_A#defaultProps
* @method
* @protected
* @returns {TComponents.CheckboxProps} - The default properties of the checkbox component.
*/
defaultProps() {
return {
options: {
responsive: false,
},
// lifecycle
onCreated: '',
onMounted: '',
onDispose: '',
onChange: '',
// X/Y/W/H/B/R
position: 'static',
top: 0,
left: 0,
borderRadius: 0,
rotation: 0,
zIndex: 0,
// description text label
text: '',
// checkbox value.
value: null,
selectedIndex: 0, // Invalid attribute
// font and color
color: '#000000',
font: {
fontSize: 12,
fontFamily: 'Segoe UI',
style: {
fontStyle: 'normal',
fontWeight: 'normal',
textDecoration: 'none',
},
},
// Bind input variable.
inputVar: {
type: Component_A.INPUTVAR_TYPE.BOOL,
func: Component_A.INPUTVAR_FUNC.CUSTOM,
value: 0,
isHidden: false,
},
// state properites
enabled: true,
checked: false,
dataStruct: '',
};
}
/**
* @description Initializes the component and sets up click event handling.
* @member TComponents.Checkbox_A#onInit
* @method
* @returns {void}
*/
onInit() {
/*
* If bound to web data, `this._bindData` will have the format: { type: 'webdata', key: 'xxx' }.
* If bound to digital signal data, `this._bindData` will have the format: { type: 'digitalsignal', key: 'xxxx' }.
* If bound to rapid data, `this._bindData` will have the format: { type: 'rapiddata', dataType: 'xxx', module: 'xxx', name: 'xxx', task: 'xxx' }.
*/
this._bindData = null;
}
/**
* @description Renders the component on the screen and applies the necessary styles and event listeners.
* @member TComponents.Checkbox_A#onRender
* @method
* @throws {Error} If an error occurs during rendering, it will throw an Error with a specific error code and message.
* @returns {void}
*/
onRender() {
try {
this.removeAllEventListeners();
const checkBoxContainer = this.find('.tc-checkbox-a');
if (checkBoxContainer) {
this._checkbox.desc = this._props.text;
this._checkbox.checked = this._props.checked;
this._checkbox.enabled = this._props.enabled;
this._checkbox.font = this._props.font;
this._checkbox.color = this._props.color;
if (this._props.inputVar && this._props.inputVar.func == Component_A.INPUTVAR_FUNC.SYNC) {
this._bindData = Component_A.getBindData(this._props.inputVar.value, this);
}
this._checkbox.onclick = this._cbOnChange.bind(this);
this._checkbox.attachToElement(checkBoxContainer);
}
} catch (e) {
// Runtime errors: write specific content to the log, throw error code
Logger.e(
logModule,
ErrorCode.FailedToRunOnRender,
`Error happens on onRender of checkbox component ${this.compId}.`,
e,
);
throw new Error(ErrorCode.FailedToRunOnRender, {cause: e});
}
}
/**
* @description Returns the HTML markup for the component.
* @member TComponents.Checkbox_A#markup
* @method
* @returns {string} The HTML markup for the component.
*/
markup() {
return /*html*/ `<div class="tc-checkbox-a"></div>`;
}
/**
* @description Adds a callback function that will be called when the checkbox state is changed.
* @member TComponents.Checkbox_A~_cbOnChange
* @method
* @private
* @async
* @returns {Promise<void>} A promise that resolves when the checkbox state is successfully changed.
*/
async _cbOnChange(value) {
if (!this._props.enabled) return;
try {
await this.syncInputData(value);
} catch (e) {
// Restore to the previous state.
this._checkbox.checked = !value;
this.commitProps({checked: !value});
Component_A.popupEventError(e, 'syncInputData', logModule);
return;
}
this.commitProps({checked: value});
try {
var fn = Component_A.genFuncTemplate(this._props.onChange, this);
fn && (await fn());
} catch (e) {
Component_A.popupEventError(e, 'onChange', logModule);
}
}
/**
* @returns {string}
*/
get checked() {
return this._props.checked;
}
/**
* @description Sets the checked state for the checkbox.
* @member {string} TComponents.Checkbox_A#checked
* @instance
* @param {string} t - The checked state.
* @example
* const checkbox = new TComponents.Checkbox_A(document.body, {
* position: 'absolute',
* zIndex: 1000,
* text: 'Execute'
* });
*
* checkbox.render();
* // Set the checkbox to checked state
* checkbox.checked = true;
*/
set checked(t) {
this.setProps({checked: t});
}
/**
* @returns {boolean}
*/
get enabled() {
return this._props.enabled;
}
/**
* @description Gets the enabled state for the component.
* @member {boolean} TComponents.Checkbox_A#enabled
* @instance
* @param {boolean} t - The enabled state.
* @example
* const checkbox = new TComponents.Checkbox_A(document.body, {
* position: 'absolute',
* zIndex: 1000,
* text: 'Execute'
* });
* checkbox.render();
* // Set the checkbox to enabled state
* checkbox.enabled = true;
*/
set enabled(t) {
this.setProps({enabled: t});
}
/**
* @returns {Function|undefined}
*/
get onChange() {
try {
var fn = Component_A.genFuncTemplateWithPopup(this._props.onChange, this);
} catch (e) {
return undefined;
}
if (typeof fn == 'function') return fn;
else return undefined;
}
/**
* @description Sets the `onChange` event handler for the checkbox component.
* The handler can either be a string representing a function to be executed or a function itself.
* 1. If you are using an arrow function, like `()=>{}`,
* the `this` property of the scope may not refer to the checkbox object.
* 2. If you are using string assignment to define code execution,
* the string should contain `only the body of the code (executable statements)`,
* not a complete function declaration. Therefore, including function keywords like function or async function is incorrect.
* - Correct (Statements Only): `xx.onChange = "console.log('Action done.');"`
* - Incorrect (Function Declaration): `xx.onChange = "function() { console.log('Action done.'); }"`
* @member {Function} TComponents.Checkbox_A#onChange
* @instance
* @param {string|Function} t - A string representing a function to be executed or a function itself to handle the `onChange` event.
* @example
* const checkbox = new TComponents.Checkbox_A(document.body, {
* position: 'absolute',
* zIndex: 1000,
* text: 'Execute'
* });
* checkbox.render();
* // Example 1: Using a string as the handler:
* checkbox.onChange = "console.log(this.checked);"
* @example
* // Example 2: Using a function as the handler:
* checkbox.onChange = function () {
* console.log(this.checked);
* };
* @example
* // Example 3: Using an arrow function as the handler:
* // Note that the `this` context will not refer to the checkbox object
* checkbox.onChange = () => {
* console.log(checkbox.checked);
* };
*/
set onChange(t) {
this.setProps({onChange: t});
}
/**
* @returns {string}
*/
get text() {
return this._props.text;
}
/**
* @description Sets the description text label for the checkbox.
* @member {string} TComponents.Checkbox_A#text
* @instance
* @param {string} t - The description label text content.
* @example
* const checkbox = new TComponents.Checkbox_A(document.body, {
* position: 'absolute',
* zIndex: 1000,
* text: 'Execute'
* });
* checkbox.render();
* // Set the description text label
* checkbox.text = 'Execute Task';
*/
set text(t) {
this.setProps({text: t});
}
/**
* @returns {string}
*/
get value() {
return this._props.text;
}
/**
* @todo This is an experimental interface; it is unstable and its use is not recommended.
* @description **it is unstable and its use is not recommended**,
* sets the binding value of the checkbox.
* @member {string} TComponents.Checkbox_A#value
* @instance
* @param {string} t - The binding value.
* @example
* const checkbox = new TComponents.Checkbox_A(document.body, {
* position: 'absolute',
* zIndex: 1000,
* text: 'Execute'
* });
* checkbox.render();
* // Set the binding value
* checkbox.value = 'execute';
*/
set value(t) {
this.commitProps({text: t});
}
/**
* @returns {string}
*/
get color() {
return this.props.color;
}
/**
* @description Sets the color of the description label.
* @member {string} TComponents.Checkbox_A#color
* @instance
* @param {string} s For example, '#ffffff'
* @example
* const checkbox = new TComponents.Checkbox_A(document.body, {
* position: 'absolute',
* zIndex: 1000,
* text: 'Execute'
* });
* checkbox.render();
* // Set the color of the description label
* checkbox.color = '#ff0000';
*/
set color(s) {
this.setProps({color: s});
}
/**
* @deprecated
* @returns {number}
*/
get selectedIndex() {
return this._props.selectedIndex;
}
/**
* @deprecated The interface has been deprecated.
* @description Sets the check box binding index.
* @member {number} TComponents.Checkbox_A#selectedIndex
* @instance
* @param {number} t - The new index binded by check box.
* @example
* const checkbox = new TComponents.Checkbox_A(document.body, {
* position: 'absolute',
* zIndex: 1000,
* text: 'Execute'
* });
* checkbox.render();
*
* checkbox.selectedIndex = 0;
*/
set selectedIndex(t) {
this.commitProps({selectedIndex: t});
}
}
/**
* Add css properties to the component
* @alias loadCssClassFromString
* @static
* @param {string} css - The css string to be loaded into style tag
*/
Checkbox_A.loadCssClassFromString(/*css*/ `
.tc-checkbox-a {
height: inherit;
width: 100%;
min-width: 0px;
min-height: 0px;
padding: 0px;
margin: 0px;
display:flex;
}
.tc-checkbox-a .fp-components-checkbox-root-disabled,
.tc-checkbox-a .fp-components-checkbox-root {
height: 100%;
width: 100%;
display: flex;
align-items: center;
overflow: hidden;
}
.tc-checkbox-a .fp-components-checkbox-disabled {
cursor: not-allowed !important;
border-color:var(--fp-color-BLACK-OPACITY-30);
}
.tc-checkbox-a .fp-components-checkbox:hover {
opacity:0.7;
}
.tc-checkbox-a .fp-components-checkbox-desc {
font-size: 14px;
color: inherit;
white-space: nowrap;
margin-left: 10px;
}
`);