import { extend } from '../Helpers/Extend';
import { wrap } from '../DOM/Wrap';
const defaultOptions: FLib.SkinCheckbox.Options = {
"wrap": "",
"invalidClass": "invalid",
"disabledClass": "disabled",
"checkedClass": "checked"
}
/**
* Skin an HTML input checkbox element.
* You can access the skin API in the __skinAPI property of the $checkbox HTMLElement or its wrapper.
*/
export default class SkinCheckbox implements FLib.SkinCheckbox.SkinCheckbox {
#$checkbox: FLib.SkinCheckbox.CustomCheckbox;
#options: FLib.SkinCheckbox.Options;
#$parent: FLib.SkinCheckbox.CustomCheckboxParent;
constructor( $checkbox: HTMLInputElement, userOptions: Partial = {} ) {
// Already skinned
if ( ($checkbox as FLib.SkinCheckbox.CustomCheckbox).__skinAPI ) {
throw 'SkinSelect: Select already skinned';
}
this.#$checkbox = $checkbox;
this.#options = extend( defaultOptions, userOptions );
// Add the skin
wrap( this.#$checkbox, this.#options.wrap );
this.#$parent = this.#$checkbox.parentNode as FLib.SkinCheckbox.CustomCheckboxParent;
this.#$parent.__skinAPI = this.#$checkbox.__skinAPI = this;
if ( this.#$checkbox.hasAttribute( 'data-has-error' ) ) {
this.setInvalid();
}
this.#$checkbox.addEventListener( 'click', this.#changeHandler );
this.#update();
}
// Change the display
#update = (): void => {
this.#$checkbox.__skinAPI?.[ this.#$checkbox.checked ? 'check' : 'uncheck' ]();
}
#changeHandler = (): void => {
this.#update();
}
#checkUncheck = ( fnName: string, checked: boolean ): void => {
this.#$checkbox.checked = checked;
this.#$parent.classList[ fnName ]( this.#options.checkedClass );
}
#enableDisable = ( fnName: string, disabled: boolean ): void => {
this.#$checkbox.disabled = disabled;
this.#$parent.classList[ fnName ]( this.#options.disabledClass );
}
#validInvalid = ( fnName: string ): void => {
this.#$parent.classList[ fnName ]( this.#options.invalidClass );
}
/**
* Force the checkbox to be check
*/
check(): this {
this.#checkUncheck( 'add', true );
return this;
}
/**
* Force the checkbox to be uncheck
*/
uncheck(): this {
this.#checkUncheck( 'remove', false );
return this;
}
/**
* Force the checkbox to be enable
*/
enable(): this {
this.#enableDisable( 'remove', false );
return this;
}
/**
* Force the checkbox to be disable
*/
disable(): this {
this.#enableDisable( 'add', true );
return this;
}
/**
* Force the state of the checkbox to invalid
*/
setInvalid(): this {
this.#validInvalid( 'add' );
return this;
}
/**
* Force the state of the checkbox to valid
*/
setValid(): this {
this.#validInvalid( 'remove' );
return this;
}
}
/**
* Skin a checkbox DOM element
*
* @example
* ```ts
* // Call with default options:
* skinCheckbox( $input, {
* "wrap": "<span class=\"cb-skin\"></span>",
* "invalidClass": "invalid",
* "disabledClass": "disabled",
* "checkedClass": "checked"
* });
* ```
*/
export function skinCheckbox( $checkbox: HTMLInputElement, options?: Partial ): SkinCheckbox {
return new SkinCheckbox( $checkbox, options );
}
/**
* Skin all checkbox DOM element in a wrapper
*
* @example
* ```ts
* // Call with default options:
* skinCheckboxAll( $wrapper,
* "selector": "input[type="checkbox"]",
* "wrap": "<span class=\"cb-skin\"></span>",
* "invalidClass": "invalid",
* "disabledClass": "disabled",
* "checkedClass": "checked"
* });
* ```
*/
export function skinCheckboxAll( $wrapper: HTMLElement, options: Partial = {} ): SkinCheckbox[] {
const $checkboxes = $wrapper.querySelectorAll( options.selector || 'input[type="checkbox"]' );
const skinList: SkinCheckbox[] = [];
$checkboxes.forEach( $checkbox => {
skinList.push( skinCheckbox( $checkbox as HTMLInputElement, options ) );
} );
return skinList;
}