| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 |
- import $ from '../../shared/jquery.js';
- import { AjaxReq, fetchHeaders } from './OMGUtils';
- const EDIT_ACTION = 'edit';
- const EDITABLE_COLUMN_ATTRIBUTE = 'aria-editable';
- const EDIT_ACTIVE_CLASS = 'shadow rounded bg-dark text-light';
- const EDIT_ACTIVE_ROW_CLASS = 'bg-info';
- const FORM_CONTENT_TYPE = 'application/x-www-form-urlencoded';
- const NON_EDITABLE_VALUE = 'false';
- let tableSelector = null;
- let controllerUrl = '';
- /**
- * Returns the editable table column names.
- *
- * @returns {string[]} Column names.
- * @sideEffects Reads the document.
- */
- function getTableFieldNames() {
- return $(`${tableSelector} thead th`).map(function () {
- return this.innerText;
- }).get();
- }
- /**
- * Returns an attribute from a table column definition.
- *
- * @param {number} columnIndex Column index.
- * @param {string} attributeName Attribute name.
- * @returns {string|undefined} Attribute value.
- * @sideEffects Reads the document.
- */
- function getColumnAttribute(columnIndex, attributeName) {
- return $(`${tableSelector} thead th`).eq(columnIndex).attr(attributeName);
- }
- /**
- * Cancels the edit of a table cell and restores its previous value.
- *
- * @param {HTMLElement} cell Table cell.
- * @returns {void}
- * @sideEffects Updates the edited table cell.
- */
- function cancelEdit(cell) {
- cell.innerText = $(cell).data('oldvalue');
- $(cell).parent('tr').removeClass(`dt-editing-cell ${EDIT_ACTIVE_ROW_CLASS}`);
- $(cell).removeClass(EDIT_ACTIVE_CLASS);
- $('body').focus();
- cell.contentEditable = 'false';
- }
- /**
- * Shows a request error without discarding diagnostic context.
- *
- * @param {unknown} error Request failure.
- * @returns {void}
- * @sideEffects Logs the failure and displays an alert.
- */
- function showRequestError(error) {
- console.error('Editable table request failed.', error);
- alert('Unable to save the table changes.');
- }
- /**
- * Runs a table command using form-urlencoded data.
- *
- * @param {string} action Server action.
- * @returns {void}
- * @sideEffects Performs a network request and displays an alert.
- */
- function executeTableAction(action) {
- AjaxReq(controllerUrl, {
- headers: { ...fetchHeaders, 'Content-Type': FORM_CONTENT_TYPE },
- method: 'POST',
- body: `action=${action}`,
- }).fetchPromise()
- .then(response => alert(`${response.code} - ${response.err}`))
- .catch(showRequestError);
- }
- /**
- * Sends the currently edited row to the server.
- *
- * @param {HTMLElement} cell Edited cell.
- * @returns {void}
- * @sideEffects Performs a network request and refreshes the DataTable.
- */
- function saveEdit(cell) {
- const formData = new FormData();
- const fields = getTableFieldNames();
- $('.dt-editing-cell td').each(function (index) {
- formData.append(fields[index], this.innerText);
- });
- formData.append('action', EDIT_ACTION);
- AjaxReq(controllerUrl, { method: 'POST', body: formData }).fetchPromise()
- .then(response => {
- $(tableSelector).DataTable().ajax.reload();
- alert(`${response.code} - ${response.err}`);
- })
- .catch(showRequestError)
- .finally(() => {
- cell.contentEditable = 'false';
- });
- }
- /**
- * Initializes an editable DataTable.
- *
- * @param {string} tableReference DataTable selector.
- * @param {string} controllerUrlReference Server endpoint.
- * @returns {void}
- * @sideEffects Initializes the table and registers DOM event handlers.
- */
- function initializeEditableTable(tableReference, controllerUrlReference) {
- tableSelector = tableReference;
- controllerUrl = controllerUrlReference;
- const tableBody = $(`${tableSelector} tbody`);
- $(tableSelector).DataTable({
- ajax: {
- url: controllerUrl,
- type: 'POST',
- data: { action: 'getData' },
- dataSrc(data) {
- $(tableSelector).closest('.dt-container').parent().removeClass('d-none');
- return data;
- },
- },
- lengthChange: false,
- dom: 'frtBip',
- order: [[0, 'asc']],
- buttons: [
- { text: 'Completa lista', action: () => executeTableAction('closelist') },
- { text: 'Annulla lista', action: () => executeTableAction('cancellist') },
- ],
- });
- tableBody.on('click', 'td', function () {
- if (getColumnAttribute(this.cellIndex, EDITABLE_COLUMN_ATTRIBUTE) === NON_EDITABLE_VALUE) {
- return;
- }
- this.contentEditable = 'true';
- $(this).data('oldvalue', this.innerText);
- $(this).parent('tr').addClass(`dt-editing-cell ${EDIT_ACTIVE_ROW_CLASS}`);
- $(this).addClass(EDIT_ACTIVE_CLASS);
- this.focus();
- });
- tableBody.on('blur', 'td', function () {
- cancelEdit(this);
- });
- tableBody.on('keydown', 'td', function (event) {
- if (event.code === 'Escape' || event.code === 'Tab') {
- cancelEdit(this);
- return false;
- }
- if (event.code === 'Enter') {
- $(this).data('oldvalue', this.innerText);
- saveEdit(this);
- return false;
- }
- });
- }
- export default initializeEditableTable;
|