167 lines
4.6 KiB
JavaScript
167 lines
4.6 KiB
JavaScript
// SPDX-FileCopyrightText: 2022 Gregor Kleen <gregor.kleen@ifi.lmu.de>,Sarah Vaupel <sarah.vaupel@ifi.lmu.de>,Sarah Vaupel <vaupel.sarah@campus.lmu.de>
|
|
//
|
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
const DEBUG_MODE = /localhost/.test(window.location.href) ? 0 : 0;
|
|
|
|
import { Utility } from '../../core/utility';
|
|
import { TableIndices } from '../../lib/table/table';
|
|
import { EventManager, EventWrapper, EVENT_TYPE } from '../../lib/event-manager/event-manager';
|
|
|
|
const CHECKBOX_SELECTOR = '[type="checkbox"]';
|
|
|
|
const CHECK_ALL_INITIALIZED_CLASS = 'check-all--initialized';
|
|
|
|
@Utility({
|
|
selector: 'table:not([uw-no-check-all])',
|
|
})
|
|
export class CheckAll {
|
|
_element;
|
|
|
|
_eventManager;
|
|
|
|
_columns = new Array();
|
|
_checkAllColumns = new Array();
|
|
|
|
_tableIndices;
|
|
|
|
_lastCheckedCell = null;
|
|
|
|
constructor(element, app) {
|
|
if (!element) {
|
|
throw new Error('Check All utility cannot be setup without an element!');
|
|
}
|
|
|
|
this._element = element;
|
|
|
|
this._eventManager = new EventManager();
|
|
|
|
if (this._element.classList.contains(CHECK_ALL_INITIALIZED_CLASS)) {
|
|
return false;
|
|
}
|
|
|
|
this._tableIndices = new TableIndices(this._element);
|
|
|
|
this._gatherColumns();
|
|
|
|
if (DEBUG_MODE > 0)
|
|
console.log(this._columns);
|
|
|
|
let checkboxColumns = this._findCheckboxColumns();
|
|
|
|
checkboxColumns.forEach(columnId => this._checkAllColumns.push(new CheckAllColumn(this._element, app, this._columns[columnId], this._eventManager)));
|
|
|
|
// mark initialized
|
|
this._element.classList.add(CHECK_ALL_INITIALIZED_CLASS);
|
|
}
|
|
|
|
destroy() {
|
|
this._eventManager.cleanUp();
|
|
this._checkAllColumns.forEach((column) => {
|
|
if (column._checkAllCheckBox !== undefined)
|
|
column._checkAllCheckBox.remove();
|
|
});
|
|
|
|
if(this._element.classList.contains(CHECK_ALL_INITIALIZED_CLASS))
|
|
this._element.classList.remove(CHECK_ALL_INITIALIZED_CLASS);
|
|
}
|
|
|
|
_gatherColumns() {
|
|
for (const rowIndex of Array(this._tableIndices.maxRow + 1).keys()) {
|
|
for (const colIndex of Array(this._tableIndices.maxCol + 1).keys()) {
|
|
if (DEBUG_MODE > 1)
|
|
console.log(rowIndex, colIndex);
|
|
|
|
const cell = this._tableIndices.getCell(rowIndex, colIndex);
|
|
|
|
if (!cell)
|
|
continue;
|
|
|
|
if (!this._columns[colIndex])
|
|
this._columns[colIndex] = new Array();
|
|
|
|
this._columns[colIndex][rowIndex] = cell;
|
|
}
|
|
}
|
|
}
|
|
|
|
_findCheckboxColumns() {
|
|
let checkboxColumnIds = new Array();
|
|
this._columns.forEach((col, i) => {
|
|
if (this._isCheckboxColumn(col)) {
|
|
checkboxColumnIds.push(i);
|
|
}
|
|
});
|
|
return checkboxColumnIds;
|
|
}
|
|
|
|
_isCheckboxColumn(col) {
|
|
return col.every(cell => cell.tagName == 'TH' || cell.querySelector(CHECKBOX_SELECTOR))
|
|
&& col.some(cell => cell.querySelector(CHECKBOX_SELECTOR));
|
|
}
|
|
}
|
|
|
|
class CheckAllColumn {
|
|
_app;
|
|
_table;
|
|
_column;
|
|
|
|
_eventManager;
|
|
|
|
_checkAllCheckbox;
|
|
_checkboxId = 'check-all-checkbox-' + Math.floor(Math.random() * 100000);
|
|
|
|
constructor(table, app, column, eventManager) {
|
|
this._column = column;
|
|
this._table = table;
|
|
this._app = app;
|
|
this._eventManager = eventManager;
|
|
|
|
const th = this._column.filter(element => element.tagName == 'TH')[0];
|
|
if (!th)
|
|
return false;
|
|
|
|
this._checkAllCheckbox = document.createElement('input');
|
|
this._checkAllCheckbox.setAttribute('type', 'checkbox');
|
|
this._checkAllCheckbox.setAttribute('id', this._checkboxId);
|
|
|
|
th.insertBefore(this._checkAllCheckbox, th.firstChild);
|
|
|
|
// set up new checkbox
|
|
this._app.utilRegistry.initAll(th);
|
|
|
|
const checkBoxInputEvent = new EventWrapper(EVENT_TYPE.INPUT, this._onCheckAllCheckboxInput.bind(this), this._checkAllCheckbox);
|
|
this._eventManager.registerNewListener(checkBoxInputEvent);
|
|
this._setupCheckboxListeners();
|
|
}
|
|
|
|
_onCheckAllCheckboxInput() {
|
|
this._toggleAll(this._checkAllCheckbox.checked);
|
|
}
|
|
|
|
_setupCheckboxListeners() {
|
|
this._column
|
|
.flatMap(cell => cell.tagName == 'TH' ? new Array() : Array.from(cell.querySelectorAll(CHECKBOX_SELECTOR)))
|
|
.forEach(checkbox => {
|
|
const checkBoxUpdateEvent = new EventWrapper(EVENT_TYPE.INPUT, this._updateCheckAllCheckboxState.bind(this), checkbox);
|
|
this._eventManager.registerNewListener(checkBoxUpdateEvent);
|
|
});
|
|
}
|
|
|
|
_updateCheckAllCheckboxState() {
|
|
const allChecked = this._column.every(cell =>
|
|
cell.tagName == 'TH' || cell.querySelector(CHECKBOX_SELECTOR).checked,
|
|
);
|
|
this._checkAllCheckbox.checked = allChecked;
|
|
}
|
|
|
|
_toggleAll(checked) {
|
|
this._column.forEach(cell => {
|
|
if (cell.tagName == 'TH')
|
|
return;
|
|
|
|
cell.querySelector(CHECKBOX_SELECTOR).checked = checked;
|
|
});
|
|
}
|
|
}
|