class CellManagement { currentEditingCell = null; currentEditingCellInitialValue = ""; currentEditingCellInitialValueHTML = ""; currentEditingCellStyle = 'single-line'; constructor() { this.initialize(); } initialize() { document.addEventListener('DOMContentLoaded', () => { CellManagement.updateAllDates(); document.addEventListener('focusout', this.onFocusOut.bind(this)); document.addEventListener('click', this.onClick.bind(this)); document.addEventListener('keypress', this.onKeyPressed.bind(this)); document.addEventListener('draw.dt', () => CellManagement.updateAllDates()) }) } /** * @param {FocusEvent} event */ onFocusOut(event) { let target = event.target; if (event.relatedTarget === this.currentEditingCell) { return; } let element = target.closest('[data-cell-editable]'); if (element) { this.validateCellEdited(element); } } /** * @param {PointerEvent} event */ onClick(event) { let target = event.target; let element = target.closest('[data-cell-editable]'); if (element) { this.clickCellEditable(element, event); } } /** * @param {KeyboardEvent} event */ onKeyPressed(event) { let target = event.target; let element = target.closest('[data-cell-single-line]'); if (element) { if (event.key === 'Enter') { this.validateCellEdited(element); } } } static updateAllDates() { document.querySelectorAll("[data-date-performed-ago]").forEach(el => this.updatePerformedAgo(el)); document.querySelectorAll("[data-date]").forEach(el => this.updateCellDate(el)); document.querySelectorAll(".cell-date").forEach(el => this.updateCellDate(el)); document.querySelectorAll(".cell-long-time").forEach(el => this.updateCellTime(el)); } /** * @param {HTMLElement} element */ static updateCellTime(element) { let rawDate = element.dataset.date; element.innerHTML = DateTime.fromJSDate(new Date(rawDate)).toLocaleString(DateTime.DATETIME_FULL); } /** * @param {HTMLElement} element */ static updateCellDate(element) { let rawDate = element.dataset.date; if (rawDate.length < 10) { return; } element.innerHTML = DateTime.fromJSDate(new Date(rawDate)).toLocaleString(DateTime.DATE_FULL); } /** * @param {HTMLElement} element */ static updatePerformedAgo(element) { let rawDate = element.dataset.datePerformedAgo; if (rawDate.length < 10) { return; } element.innerHTML = __('app.performed_ago', { 'ago': DateTime.fromJSDate(new Date(rawDate)).toRelative() }); } /** * @param {HTMLElement} element * @param {PointerEvent} event */ clickCellEditable(element, event) { if (event) { event.stopImmediatePropagation(); } if (this.currentEditingCell !== null) { return; } this.currentEditingCellInitialValue = element.textContent.trim(); this.currentEditingCellInitialValueHTML = element.innerHTML.trim(); let addClz = element.dataset.classes?.split(' ') ?? []; if (typeof element.dataset.cellSingleLine !== 'undefined') { this.currentEditingCellStyle = 'single-line'; this.currentEditingCell = Commons.createInput('text', 'tmpTF', this.currentEditingCellInitialValue); this.currentEditingCell.classList.add( 'form-control', 'form-control-light', 'unfocuscheck', ); addClz.forEach(el => this.currentEditingCell.classList.add(el)); } else { this.currentEditingCellStyle = 'multi-line'; let textAreaElement = document.createElement('textarea') textAreaElement.classList.add('unfocuscheck', 'multi-cell-editable-light'); addClz.forEach(el => textAreaElement.classList.add(el)); textAreaElement.rows = this.currentEditingCellInitialValue.split("\n").length textAreaElement.textContent = this.currentEditingCellInitialValue; this.currentEditingCell = textAreaElement; } element.innerHTML = ''; element.append(this.currentEditingCell); this.currentEditingCell.focus(); } validateCellEdited(cell) { if (app.getOperationInProgress()) { return; } if (this.currentEditingCell === null) { return; } let newValue = this.currentEditingCell.value.trim(); if (newValue === this.currentEditingCellInitialValue.trim()) { cell.innerHTML = this.currentEditingCellInitialValueHTML; this.currentEditingCellInitialValue = null; this.currentEditingCell = null; return; } app.setRefreshingState(true); let fetchOptions = Commons.getPostOptions(JSON.stringify({ fieldName: cell.dataset.field, field: newValue })); let instance = cell; fetch(cell.dataset.uri, fetchOptions) .then((response) => { let text = this.currentEditingCell.value; try { response.json().then((json) => { if (json.type !== "success") { text = this.currentEditingCellInitialValue; } if (this.currentEditingCellStyle === 'single-line') { instance.textContent = text; } else { instance.innerHTML = Commons.nl2br(text); } Commons.handleAjaxResponse(json) }) } catch (err) { } this.currentEditingCellInitialValue = null; this.currentEditingCell = null; app.setRefreshingState(false); }) } } new CellManagement();