@eclipse-scout/core
Version:
Eclipse Scout runtime
185 lines (164 loc) • 5.61 kB
text/typescript
/*
* Copyright (c) 2010, 2025 BSI Business Systems Integration AG
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*/
import {BooleanColumnModel, Cell, CheckBoxField, Column, comparators, scout, TableRow} from '../../index';
/**
* A column holding boolean values represented by check boxes.
*/
export class BooleanColumn extends Column<boolean> implements BooleanColumnModel {
declare model: BooleanColumnModel;
triStateEnabled: boolean;
constructor() {
super();
this.comparator = comparators.NUMERIC;
this.filterType = 'ColumnUserFilter';
this.horizontalAlignment = 0;
this.minWidth = Column.SMALL_MIN_WIDTH;
this.triStateEnabled = false;
this.textBased = false;
}
protected override _formatValue(value: boolean, row?: TableRow): string {
if (this.triStateEnabled && value === null) {
return '?';
}
return value ? 'X' : '';
}
override buildCell(cell: Cell<boolean>, row: TableRow): string {
let content = '',
enabled = row.enabled,
tableNodeColumn = this.table.isTableNodeColumn(this),
rowPadding = 0;
if (tableNodeColumn) {
rowPadding = this.table._calcRowLevelPadding(row);
}
if (cell.empty) {
// if cell wants to be really empty (e.g. no checkbox icon, use logic of base class)
return super.buildCell(cell, row);
}
enabled = enabled && cell.editable;
let cssClass = this._cellCssClass(cell, tableNodeColumn);
let style = this._cellStyle(cell, tableNodeColumn, rowPadding);
if (!enabled) {
cssClass += ' disabled';
}
let checkBoxCssClass = 'check-box';
let ariaChecked = '';
if (cell.value === true) {
checkBoxCssClass += ' checked';
ariaChecked = 'aria-checked="true"';
}
if (cell.value === false) {
ariaChecked = 'aria-checked="false"';
}
if (this.triStateEnabled && cell.value !== true && cell.value !== false) {
checkBoxCssClass += ' undefined';
ariaChecked = 'aria-checked="mixed"';
}
if (!enabled) {
checkBoxCssClass += ' disabled';
}
if (tableNodeColumn && row.expandable) {
this.tableNodeColumn = true;
content = this._expandIcon(row.expanded, rowPadding) + content;
if (row.expanded) {
cssClass += ' expanded';
}
}
// empty aria label added so screen readers finds the checkbox in the column (adding   in the div content would work, too)
content = content + '<div aria-label=" " role="checkbox" ' + ariaChecked + ' class="' + checkBoxCssClass + '"></div>';
return this._buildCell(cell, content, style, cssClass);
}
$checkBox($row: JQuery): JQuery {
let $cell = this.table.$cell(this, $row);
return $cell.children('.check-box');
}
protected override _cellCssClass(cell: Cell<boolean>, tableNode?: boolean): string {
let cssClass = super._cellCssClass(cell);
cssClass = cssClass.replace(' editable', '');
cssClass += ' checkable';
if (tableNode) {
cssClass += ' table-node';
}
return cssClass;
}
/**
* This function does intentionally _not_ call the super function (prepareCellEdit) because we don't want to
* show an editor for BooleanColumns when user clicks on a cell.
*/
override onMouseUp(event: JQuery.MouseUpEvent, $row: JQuery) {
let row = $row.data('row') as TableRow,
cell = this.cell(row);
if (this.table.checkableColumn === this) {
this.table.checkRow(row, !row.checked);
} else if (this.isCellEditable(row, cell, event)) {
this._toggleCellValue(row, cell);
}
}
/**
* In a remote app this function is overridden, the default implementation is the local case.
* @see TableAdapter
*/
protected _toggleCellValue(row: TableRow, cell: Cell<boolean>) {
let prepareEvent = this.table.trigger('prepareCellEdit', {
column: this,
row: row
});
if (prepareEvent.defaultPrevented) {
return;
}
let value = cell.value as boolean;
let newValue = !value;
if (this.triStateEnabled) {
if (value === false) {
newValue = true;
} else if (value === true) {
newValue = null;
} else if (value === null) {
newValue = false;
}
}
let dummyField = scout.create(CheckBoxField, {
parent: this.table,
value: newValue
});
let completeEvent = this.table.trigger('completeCellEdit', {
field: dummyField,
row: row,
column: this,
cell: cell
});
if (!completeEvent.defaultPrevented) {
this.setCellValue(row, newValue);
}
dummyField.destroy();
}
protected override _createEditor(row: TableRow): CheckBoxField {
return scout.create(CheckBoxField, {
parent: this.table,
triStateEnabled: this.triStateEnabled
});
}
override cellTextForGrouping(row: TableRow): string {
let cell = this.cell(row);
if (this.triStateEnabled && cell.value === null) {
return this.session.text('ui.BooleanColumnGroupingMixed');
}
if (cell.value === true) {
return this.session.text('ui.BooleanColumnGroupingTrue');
}
return this.session.text('ui.BooleanColumnGroupingFalse');
}
setTriStateEnabled(triStateEnabled: boolean) {
if (this.triStateEnabled === triStateEnabled) {
return;
}
this.triStateEnabled = triStateEnabled;
this.table.rows.forEach(row => this._updateCellText(row, this.cell(row)));
}
}