gd-bs
Version:
Bootstrap JavaScript, TypeScript and Web Components library.
247 lines (201 loc) • 8.08 kB
text/typescript
import { ICheckboxGroup, ICheckboxGroupItem, ICheckboxGroupProps } from "./types";
import { Base } from "../base";
import { CheckboxItem } from "./item";
import { HTML } from "./templates";
/**
* Checkbox Group Types
*/
export enum CheckboxGroupTypes {
Checkbox = 1,
Radio = 2,
Switch = 3
}
/**
* Checkbox Group
*/
class _CheckboxGroup extends Base<ICheckboxGroupProps> implements ICheckboxGroup {
private _cbTemplate: string = null;
private _checkboxes: Array<CheckboxItem> = null;
private _elCheckboxes: HTMLElement = null;
private _initFl: boolean = false;
// Constructor
constructor(props: ICheckboxGroupProps, template: string = HTML, cbTemplate?: string) {
super(template, props);
// Set the template
this._cbTemplate = cbTemplate;
// Configure the checkbox group
this.configure();
// Configure the parent
this.configureParent();
// Set the flag
this._initFl = true;
}
// Configure the card group
private configure() {
let renderRow = typeof (this.props.colSize) === "number" ? this.props.colSize > 0 : false;
// See if a label is defined
let label = this.el.querySelector("legend");
if (label) {
if (this.props.label && this.props.hideLabel != true) {
// Add the label
label.innerHTML = this.props.label;
} else {
// Remove the label
this.el.removeChild(label);
}
}
// Get the group and configure the size
let group = this.el.querySelector("div");
if (group) {
if (!renderRow) {
// Remove the group element
this.el.removeChild(group);
// Set the checkboxes element
this._elCheckboxes = this.el;
} else {
// Set the checkboxes element
this._elCheckboxes = group;
}
}
// Render the checkboxes
this.renderItems();
// Parse the items
let valueSet: boolean = false;
let items = this.props.items || [];
for (let i = 0; i < items.length; i++) {
// See if the item is using the isSelected property
if (typeof (items[i].isSelected) === "boolean") {
// Set the flag
valueSet = true;
break;
}
}
// Set the value if we need to
valueSet ? null : this.setValue(this.props.value);
}
// Configure the events
private configureEvents(item: CheckboxItem) {
// See if we are not allowing multiple selections
if (this.props.multi != true) {
// Add a click event
item.checkbox.addEventListener("click", ev => {
// Parse the checkboxes
for (let i = 0; i < this._checkboxes.length; i++) {
let checkbox = this._checkboxes[i];
// Ensure this item is checked
if (!checkbox.isChecked) { continue; }
// Skip this item
if (checkbox.el.outerHTML == item.el.outerHTML) { continue; }
// Toggle the checkbox
checkbox.toggle();
}
});
}
// See if there is a change event defined
if (this.props.onChange) {
// Add a click event
item.checkbox.addEventListener("click", ev => {
let value = this.getValue();
// Call the event
this.props.onChange(value.selectedItems, value.allItems, ev);
});
}
}
// Render the checkboxes
private renderItems() {
// Clear the checkboxes
this._checkboxes = [];
// Set the items
let items = this.props.items;
if (items == null || typeof (items.length) !== "number") {
// Clear the items
items = [];
// Create an item based on the label
items.push({
label: this.props.label || ""
});
}
// Parse the items
for (let i = 0; i < items.length; i++) {
let item = items[i];
// Create the checkbox
let checkbox = new CheckboxItem(item, this.props, this._cbTemplate);
this._checkboxes.push(checkbox);
this._elCheckboxes.appendChild(checkbox.el);
// Configure the events
this.configureEvents(checkbox);
// Execute the render event
this.props.onRender ? this.props.onRender(checkbox.el, item) : null;
}
}
/**
* Public Methods
*/
// Method to get the value
getValue(): { selectedItems: ICheckboxGroupItem | Array<ICheckboxGroupItem>, allItems: Array<ICheckboxGroupItem> } {
let allItems: Array<ICheckboxGroupItem> = [];
let selectedItems: Array<ICheckboxGroupItem> = [];
// Parse the checkboxes
for (let i = 0; i < this._checkboxes.length; i++) {
let cb = this._checkboxes[i];
// Add the item
allItems.push(cb.props);
// See if it's checked
if (cb.isChecked) {
// Add the value
selectedItems.push(cb.props);
}
}
// Return the values
return { selectedItems: this.props.multi ? selectedItems : selectedItems[0], allItems };
}
// Sets the checkbox items
setItems(newItems: Array<ICheckboxGroupItem> = []) {
let renderRow = typeof (this.props.colSize) === "number" ? this.props.colSize > 0 : false;
// Update the properties
this.props.items = newItems;
// Get the element containing the checkboxes and clear them
let elParent = renderRow ? this.el.querySelector("div") : this.el;
while (elParent.firstChild) { elParent.removeChild(elParent.firstChild); }
// Render the checkboxes
this.renderItems();
}
// Method to set the value
// Sets the dropdown value
setValue(value) {
// See if this is a single checkbox
if (this.props.multi != true && this._checkboxes.length == 1) {
// See if this checkbox should be checked
if (typeof (value) === "boolean" && value) {
// Select the item
this._checkboxes[0].isChecked ? null : this._checkboxes[0].toggle();
}
return;
}
// Ensure it's an array
let values = value ? (typeof (value.length) === "number" && typeof (value) !== "string" ? value : [value]) : [];
// Parse the items
for (let i = 0; i < this._checkboxes.length; i++) {
let checkbox = this._checkboxes[i];
// Toggle checked items
checkbox.isChecked ? checkbox.toggle() : null;
}
// Parse the values
for (let i = 0; i < values.length; i++) {
let value = values[i];
// Parse the items
for (let j = 0; j < this._checkboxes.length; j++) {
let checkbox = this._checkboxes[j];
// Select this checkbox if the label matches
checkbox.props.label == value ? checkbox.toggle() : null;
}
}
// See if a change event exists
if (this._initFl && this.props.onChange) {
let value = this.getValue();
// Execute the change event
this.props.onChange(value.selectedItems, value.allItems);
}
}
}
export const CheckboxGroup = (props: ICheckboxGroupProps, template?: string, cbTemplate?: string): ICheckboxGroup => { return new _CheckboxGroup(props, template, cbTemplate); }