const DEBUG_MODE = /localhost/.test(window.location.href) ? 0 : 0; import { Utility } from '../../core/utility'; import { TableIndices } from '../../lib/table/table'; 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; _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; 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); //Todo: 1 forEach loop let checkboxColumns = this._findCheckboxColumns(); checkboxColumns.forEach(columnId => this._checkAllColumns.push(new CheckAllColumn(this._element, app, this._columns[columnId]))); checkboxColumns.forEach(columnId => { let currentColumn = this._columns[columnId]; currentColumn.forEach(el => el.addEventListener('click', (ev) => { if(ev.shiftKey && this.lastCheckedCell !== null) { let lastClickedIndex = this._tableIndices.rowIndex(this._lastCheckedCell); let currentCellIndex = this._tableIndices.rowIndex(el); if(currentCellIndex > lastClickedIndex) this._checkMultipleCells(lastClickedIndex, currentCellIndex, columnId); else this._checkMultipleCells(currentCellIndex, lastClickedIndex, columnId); } else { this._lastCheckedCell = el; } })); }); // mark initialized this._element.classList.add(CHECK_ALL_INITIALIZED_CLASS); } _checkMultipleCells(firstRowIndex, lastRowIndex, columnId) { for(let i=firstRowIndex; i<=lastRowIndex; i++) { let cell = this._columns[columnId][i]; if (cell.tagName !== 'TH') { cell.querySelector(CHECKBOX_SELECTOR).checked = true; } } } _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; _checkAllCheckbox; _checkboxId = 'check-all-checkbox-' + Math.floor(Math.random() * 100000); constructor(table, app, column) { this._column = column; this._table = table; this._app = app; 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); this._checkAllCheckbox.addEventListener('input', this._onCheckAllCheckboxInput.bind(this)); 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 => checkbox.addEventListener('input', this._updateCheckAllCheckboxState.bind(this)) ); } _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; }); } }