750 lines
38 KiB
JavaScript
750 lines
38 KiB
JavaScript
|
|
import BusinessObjects from "../lib/business_objects/business_objects.js";
|
|
import Events from "../lib/events.js";
|
|
import LocalStorage from "../lib/local_storage.js";
|
|
import Validation from "../lib/validation.js";
|
|
import BasePage from "./base.js";
|
|
import API from "../api.js";
|
|
import DOM from "../dom.js";
|
|
import Utils from "../lib/utils.js";
|
|
|
|
import OverlayConfirm from "../components/common/temporary/overlay_confirm.js";
|
|
import OverlayError from "../components/common/temporary/overlay_error.js";
|
|
|
|
export default class TableBasePage extends BasePage {
|
|
// static hash
|
|
// static attrIdRowObject
|
|
// callSaveTableContent
|
|
|
|
constructor(router) {
|
|
super(router);
|
|
this.cursorYInitial = null;
|
|
this.rowInitial = null;
|
|
this.placeholder = null;
|
|
this.dragSrcEl = null;
|
|
this.dragSrcRow = null;
|
|
|
|
this.hookupTableCellDdls = this.hookupTableCellDdls.bind(this);
|
|
}
|
|
|
|
initialize(isPopState = false) {
|
|
throw new Error("Must implement initialize() method.");
|
|
}
|
|
sharedInitialize(isPopState = false, isSinglePageApp = false) {
|
|
if (!isPopState) {
|
|
super.sharedInitialize();
|
|
this.hookupFilters();
|
|
this.hookupButtonsSaveCancel();
|
|
this.hookupTableMain();
|
|
OverlayConfirm.hookup(() => {
|
|
if (isSinglePageApp) {
|
|
this.saveRecordsTableDirtySinglePageApp();
|
|
}
|
|
else {
|
|
this.saveRecordsTableDirty();
|
|
}
|
|
});
|
|
} else {
|
|
let dataPage = this.getLocalStoragePage();
|
|
let filters = dataPage[flagFormFilters];
|
|
let formFilters = TableBasePage.getFormFilters();
|
|
let filtersDefault = DOM.convertForm2JSON(formFilters);
|
|
if (!Validation.areEqualDicts(filters, filtersDefault)) {
|
|
this.callFilterTableContent();
|
|
}
|
|
}
|
|
}
|
|
hookupFilters() {
|
|
if (this.constructor === TableBasePage) {
|
|
throw new Error("Subclass of TableBasePage must implement method hookupFilters().");
|
|
}
|
|
}
|
|
sharedHookupFilters() {
|
|
this.hookupButtonApplyFilters();
|
|
this.hookupSearchTextFilter();
|
|
}
|
|
hookupFilterActive() {
|
|
let filterSelector = idFormFilters + ' #' + flagActiveOnly;
|
|
let filterActiveOld = document.querySelector(filterSelector);
|
|
filterActiveOld.removeAttribute('id');
|
|
let parentDiv = filterActiveOld.parentElement;
|
|
let isChecked = (DOM.getElementAttributeValuePrevious(parentDiv) == "True");
|
|
let filterActiveNew = document.querySelector(idFormFilters + ' div.' + flagActiveOnly + '.' + flagContainerInput + ' svg.' + flagActiveOnly);
|
|
filterActiveNew.setAttribute('id', flagActiveOnly);
|
|
if (isChecked) filterActiveNew.classList.add(flagIsChecked);
|
|
|
|
Events.hookupEventHandler("click", filterSelector, (event, filterActive) => {
|
|
Utils.consoleLogIfNotProductionEnvironment({ filterActive });
|
|
Utils.consoleLogIfNotProductionEnvironment({ [filterActive.tagName]: filterActive.tagName });
|
|
let svgElement = (filterActive.tagName.toUpperCase() == 'SVG') ? filterActive : filterActive.parentElement;
|
|
let wasChecked = svgElement.classList.contains(flagIsChecked);
|
|
if (wasChecked) {
|
|
svgElement.classList.remove(flagIsChecked);
|
|
}
|
|
else {
|
|
svgElement.classList.add(flagIsChecked);
|
|
}
|
|
return this.handleChangeFilter(event, filterActive);
|
|
});
|
|
let filter = document.querySelector(filterSelector);
|
|
let filterValuePrevious = DOM.getElementValueCurrent(filter);
|
|
filter.setAttribute(attrValueCurrent, filterValuePrevious);
|
|
filter.setAttribute(attrValuePrevious, filterValuePrevious);
|
|
}
|
|
hookupFilter(filterFlag, handler = (event, filter) => { return this.handleChangeFilter(event, filter); }) {
|
|
let filterSelector = idFormFilters + ' #' + filterFlag;
|
|
Events.hookupEventHandler("change", filterSelector, handler);
|
|
let filter = document.querySelector(filterSelector);
|
|
let filterValuePrevious = DOM.getElementValueCurrent(filter);
|
|
filter.setAttribute(attrValueCurrent, filterValuePrevious);
|
|
filter.setAttribute(attrValuePrevious, filterValuePrevious);
|
|
}
|
|
handleChangeFilter(event, filter) {
|
|
let isDirtyFilter = DOM.updateAndCheckIsElementDirty(filter);
|
|
let formFilters = TableBasePage.getFormFilters();
|
|
let areDirtyFilters = isDirtyFilter || DOM.hasDirtyChildrenContainer(formFilters);
|
|
let tbody = document.querySelector(idTableMain + ' tbody');
|
|
let rows = tbody.querySelectorAll(':scope > tr');
|
|
rows.forEach((row) => {
|
|
if (areDirtyFilters && !row.classList.contains(flagIsCollapsed)) row.classList.add(flagIsCollapsed);
|
|
if (!areDirtyFilters && row.classList.contains(flagIsCollapsed)) {
|
|
row.classList.remove(flagIsCollapsed);
|
|
let dirtyInputs = row.querySelectorAll('input.' + flagDirty);
|
|
dirtyInputs.forEach((dirtyInput) => {
|
|
dirtyInput.value = DOM.getElementAttributeValueCurrent(dirtyInput);
|
|
});
|
|
}
|
|
});
|
|
if (areDirtyFilters) {
|
|
/*
|
|
tbody.querySelectorAll('tr').forEach((tr) => {
|
|
if (!DOM.hasDirtyChildrenContainer(tr)) tr.remove();
|
|
});
|
|
*/
|
|
tbody.innerHTML = '<div>Press "Apply Filters" to refresh the table.</div>' + tbody.innerHTML;
|
|
if (!tbody.classList.contains(flagIsCollapsed)) tbody.classList.add(flagIsCollapsed);
|
|
}
|
|
else {
|
|
let isDirtyLabel = tbody.querySelector(":scope > div");
|
|
if (isDirtyLabel != null) isDirtyLabel.remove();
|
|
if (tbody.classList.contains(flagIsCollapsed)) tbody.classList.remove(flagIsCollapsed);
|
|
let initialisedElements = tbody.querySelectorAll('.' + flagInitialised);
|
|
initialisedElements.forEach((initialisedElement) => {
|
|
initialisedElement.classList.remove(flagInitialised);
|
|
});
|
|
this.hookupTableMain();
|
|
}
|
|
this.updateAndToggleShowButtonsSaveCancel();
|
|
}
|
|
hookupFilterIsNotEmpty() {
|
|
this.hookupFilter(flagIsNotEmpty);
|
|
}
|
|
hookupButtonApplyFilters() {
|
|
Events.hookupEventHandler("click", idButtonApplyFilters, (event, button) => {
|
|
event.stopPropagation();
|
|
this.callFilterTableContent();
|
|
});
|
|
}
|
|
hookupSearchTextFilter() {
|
|
this.hookupFilter(flagSearch);
|
|
}
|
|
hookupFilterCommandCategory() {
|
|
this.hookupFilter(attrIdCommandCategory, (event, filterCommandCategory) => {
|
|
this.handleChangeFilter();
|
|
let isDirtyFilter = filterCommandCategory.classList.contains(flagDirty);
|
|
let idCommandCategory = DOM.getElementValueCurrent(filterCommandCategory);
|
|
console.log("filter commands unsorted");
|
|
console.log(Utils.getListFromDict(filterCommands));
|
|
let commandsInCategory = Utils.getListFromDict(filterCommands).filter(command => command[attrIdCommandCategory] == idCommandCategory);
|
|
let sortedCommands = commandsInCategory.sort((a, b) => a[flagName].localeCompare(b[flagName]));
|
|
let filterCommand = document.querySelector(idFormFilters + ' .' + flagCommand);
|
|
let idCommandPrevious = DOM.getElementAttributeValuePrevious(filterCommand);
|
|
filterCommand.innerHTML = '';
|
|
let optionJson, option;
|
|
option = DOM.createOption(null);
|
|
filterCommand.appendChild(option);
|
|
sortedCommands.forEach((command) => {
|
|
optionJson = BusinessObjects.getOptionJsonFromObjectJson(command, idCommandPrevious);
|
|
option = DOM.createOption(optionJson);
|
|
filterCommand.appendChild(option);
|
|
});
|
|
filterCommand.dispatchEvent(new Event('change'));
|
|
return isDirtyFilter;
|
|
});
|
|
}
|
|
hookupFilterCommand() {
|
|
this.hookupFilter(attrIdCommand);
|
|
}
|
|
hookupFilterLocation() {
|
|
this.hookupFilter(attrIdLocation);
|
|
}
|
|
/*
|
|
getAndLoadFilteredTableContent = () => {
|
|
this.callFilterTableContent()
|
|
.catch(error => console.error('Error:', error));
|
|
}
|
|
*/
|
|
static getFormFilters() {
|
|
return document.querySelector(idFormFilters);
|
|
}
|
|
callFilterTableContent() {
|
|
let formFilters = TableBasePage.getFormFilters();
|
|
let filtersJson = DOM.convertForm2JSON(formFilters);
|
|
Utils.consoleLogIfNotProductionEnvironment("callFilterTableContent");
|
|
Utils.consoleLogIfNotProductionEnvironment("formFilters");
|
|
Utils.consoleLogIfNotProductionEnvironment(formFilters);
|
|
Utils.consoleLogIfNotProductionEnvironment("filtersJson");
|
|
Utils.consoleLogIfNotProductionEnvironment(filtersJson);
|
|
this.leave();
|
|
API.goToHash(this.constructor.hash, filtersJson);
|
|
}
|
|
callbackLoadTableContent(response) {
|
|
let table = TableBasePage.getTableMain();
|
|
let bodyTable = table.querySelector('tbody');
|
|
bodyTable.querySelectorAll('tr').forEach(function(row) { row.remove(); });
|
|
let rowsJson = response.data[flagRows];
|
|
if (!Validation.isEmpty(rowsJson) && rowsJson.every(row => row.hasOwnProperty('display_order'))) {
|
|
rowsJson = rowsJson.sort((a, b) => a.display_order - b.display_order);
|
|
}
|
|
rowsJson.forEach(this.loadRowTable.bind(this));
|
|
this.hookupTableMain();
|
|
}
|
|
static getTableMain() {
|
|
return document.querySelector(idTableMain);
|
|
}
|
|
loadRowTable(rowJson) {
|
|
throw new Error("Subclass of TableBasePage must implement method loadRowTable().");
|
|
}
|
|
getAndLoadFilteredTableContentSinglePageApp() {
|
|
this.callFilterTableContent()
|
|
.then(data => {
|
|
Utils.consoleLogIfNotProductionEnvironment('Table data received:', data);
|
|
this.callbackLoadTableContent(data);
|
|
})
|
|
.catch(error => console.error('Error:', error));
|
|
}
|
|
hookupButtonsSaveCancel() {
|
|
this.hookupButtonSave();
|
|
this.hookupButtonCancel();
|
|
this.toggleShowButtonsSaveCancel(false);
|
|
}
|
|
saveRecordsTableDirty() {
|
|
let records = this.getTableRecords(true);
|
|
if (records.length == 0) {
|
|
OverlayError.show('No records to save');
|
|
return;
|
|
}
|
|
let formElement = TableBasePage.getFormFilters();
|
|
let comment = DOM.getElementValueCurrent(document.querySelector(idTextareaConfirm));
|
|
this.callSaveTableContent(records, formElement, comment)
|
|
.then(data => {
|
|
if (data[flagStatus] == flagSuccess) {
|
|
if (_verbose) {
|
|
Utils.consoleLogIfNotProductionEnvironment('Records saved!');
|
|
Utils.consoleLogIfNotProductionEnvironment('Data received:', data);
|
|
}
|
|
this.callFilterTableContent();
|
|
}
|
|
else {
|
|
Utils.consoleLogIfNotProductionEnvironment("error: ", data[flagMessage]);
|
|
OverlayError.show(data[flagMessage]);
|
|
}
|
|
})
|
|
.catch(error => console.error('Error:', error));
|
|
}
|
|
getTableRecords(dirtyOnly = false) {
|
|
let records = [];
|
|
let record;
|
|
document.querySelectorAll(idTableMain + ' > tbody > tr').forEach((row) => {
|
|
if (dirtyOnly && !DOM.hasDirtyChildrenContainer(row)) return;
|
|
record = this.getJsonRow(row);
|
|
records.push(record);
|
|
});
|
|
return records;
|
|
}
|
|
getJsonRow(row) {
|
|
throw new Error("Subclass of TableBasePage must implement method getJsonRow().");
|
|
}
|
|
saveRecordsTableDirtySinglePageApp() {
|
|
let records = this.getTableRecords(true);
|
|
if (records.length == 0) {
|
|
OverlayError.show('No records to save');
|
|
return;
|
|
}
|
|
let formElement = TableBasePage.getFormFilters();
|
|
let comment = DOM.getElementValueCurrent(document.querySelector(idTextareaConfirm));
|
|
this.callSaveTableContent(records, formElement, comment)
|
|
.then(data => {
|
|
if (data[flagStatus] == flagSuccess) {
|
|
if (_verbose) {
|
|
Utils.consoleLogIfNotProductionEnvironment('Records saved!');
|
|
Utils.consoleLogIfNotProductionEnvironment('Data received:', data);
|
|
}
|
|
this.callbackLoadTableContent(data);
|
|
}
|
|
else {
|
|
Utils.consoleLogIfNotProductionEnvironment("error: ", data[flagMessage]);
|
|
OverlayError.show(data[flagMessage]);
|
|
}
|
|
})
|
|
.catch(error => console.error('Error:', error));
|
|
}
|
|
hookupButtonCancel() {
|
|
Events.initialiseEventHandler('.' + flagContainer + '.' + flagSave + '.' + flagCancel + ' button.' + flagCancel, flagInitialised, (button) => {
|
|
button.addEventListener("click", (event) => {
|
|
event.stopPropagation();
|
|
button = event.target;
|
|
if (button.classList.contains(flagIsCollapsed)) return;
|
|
this.callFilterTableContent();
|
|
});
|
|
button.classList.add(flagIsCollapsed);
|
|
});
|
|
}
|
|
handleClickAddRowTable(event, button) {
|
|
event.stopPropagation();
|
|
_rowBlank.setAttribute(this.constructor.attrIdRowObject, -1 - _rowBlank.getAttribute(this.constructor.attrIdRowObject));
|
|
let tbody = document.querySelector(idTableMain + ' tbody');
|
|
if (tbody.classList.contains(flagIsCollapsed)) return;
|
|
let row = _rowBlank.cloneNode(true);
|
|
row.classList.remove(flagInitialised);
|
|
row.querySelectorAll('.' + flagInitialised).forEach(function(element) {
|
|
element.classList.remove(flagInitialised);
|
|
});
|
|
let countRows = document.querySelectorAll(idTableMain + ' > tbody > tr').length;
|
|
row.setAttribute(this.constructor.attrIdRowObject, -1 - countRows);
|
|
this.initialiseRowNew(tbody, row);
|
|
tbody.prepend(row);
|
|
tbody.scrollTop = 0;
|
|
this.hookupTableMain();
|
|
this.postInitialiseRowNewCallback(tbody);
|
|
}
|
|
initialiseRowNew(tbody, row) {
|
|
if (this.constructor === TableBasePage) {
|
|
throw new Error("Subclass of TableBasePage must implement method initialiseRowNew().");
|
|
}
|
|
// row.classList.remove(flagRowNew);
|
|
}
|
|
hookupTableMain() {
|
|
if (this.constructor === TableBasePage) {
|
|
throw new Error("Must implement hookupTableMain() method.");
|
|
}
|
|
Events.initialiseEventHandler(idTableMain, flagInitialised, (table) => {
|
|
this.cacheRowBlank();
|
|
});
|
|
}
|
|
cacheRowBlank() {
|
|
let selectorRowNew = idTableMain + ' tbody tr.' + flagRowNew;
|
|
let rowBlankTemp = document.querySelector(selectorRowNew);
|
|
if (rowBlankTemp == null) return;
|
|
Utils.consoleLogIfNotProductionEnvironment("row blank temp: ", rowBlankTemp);
|
|
let countRows = document.querySelectorAll(idTableMain + ' > tbody > tr').length;
|
|
_rowBlank = rowBlankTemp.cloneNode(true);
|
|
document.querySelectorAll(selectorRowNew).forEach(function(row) {
|
|
row.remove();
|
|
});
|
|
_rowBlank.setAttribute(this.constructor.attrIdRowObject, -1 - countRows);
|
|
}
|
|
postInitialiseRowNewCallback(tbody) {
|
|
if (this.constructor === TableBasePage) {
|
|
throw new Error("Subclass of TableBasePage must implement method postInitialiseRowNewCallback(tbody).");
|
|
}
|
|
}
|
|
initialiseSliderDisplayOrderRowNew(tbody, row) {
|
|
// let tdSelector = ':scope > tr > td.' + flagDisplayOrder;
|
|
// let tbody = document.querySelector('table' + (Validation.isEmpty(flagTable) ? '' : '.' + flagTable) + ' > tbody');
|
|
let slidersDisplayOrder = tbody.querySelectorAll(':scope > tr > td.' + flagDisplayOrder + ' input.' + flagSlider);
|
|
let maxDisplayOrder = 0;
|
|
slidersDisplayOrder.forEach((slider) => {
|
|
maxDisplayOrder = Math.max(maxDisplayOrder, parseFloat(DOM.getElementValueCurrent(slider)));
|
|
});
|
|
let sliderDisplayOrder = row.querySelector('td.' + flagDisplayOrder + ' .' + flagSlider);
|
|
DOM.setElementValuesCurrentAndPrevious(sliderDisplayOrder, maxDisplayOrder + 1);
|
|
}
|
|
hookupSlidersDisplayOrderTable() {
|
|
let selectorDisplayOrder = idTableMain + ' tbody tr td.' + flagDisplayOrder + ' input.' + flagSlider + '.' + flagDisplayOrder;
|
|
this.hookupChangeHandlerTableCells(selectorDisplayOrder);
|
|
}
|
|
hookupChangeHandlerTableCells(inputSelector, handler = (event, element) => { this.handleChangeNestedElementCellTable(event, element); }) {
|
|
Events.initialiseEventHandler(inputSelector, flagInitialised, (input) => {
|
|
input.addEventListener("change", (event) => {
|
|
handler(event, input);
|
|
});
|
|
handler(null, input);
|
|
});
|
|
}
|
|
handleChangeNestedElementCellTable(event, element) {
|
|
let wasDirtyParentRows = this.getAllIsDirtyRowsInParentTree(element);
|
|
let wasDirtyElement = element.classList.contains(flagDirty);
|
|
let isDirtyElement = DOM.updateAndCheckIsElementDirty(element);
|
|
// Utils.consoleLogIfNotProductionEnvironment({isDirtyElement, wasDirtyElement, wasDirtyParentRows});
|
|
// let td = DOM.getCellFromElement(element);
|
|
// DOM.setElementAttributeValueCurrent(td, DOM.getElementAttributeValueCurrent(element));
|
|
if (isDirtyElement != wasDirtyElement) {
|
|
// DOM.handleDirtyElement(td, isDirtyElement);
|
|
this.updateAndToggleShowButtonsSaveCancel();
|
|
this.cascadeChangedIsDirtyNestedElementCellTable(element, isDirtyElement, wasDirtyParentRows);
|
|
}
|
|
}
|
|
getAllIsDirtyRowsInParentTree(element) {
|
|
let rows = [];
|
|
let parent = element;
|
|
let isDirty;
|
|
while (parent) {
|
|
if (parent.tagName.toUpperCase() == 'TR') {
|
|
isDirty = parent.classList.contains(flagDirty)
|
|
rows.push(isDirty);
|
|
}
|
|
parent = parent.parentElement;
|
|
}
|
|
return rows;
|
|
}
|
|
cascadeChangedIsDirtyNestedElementCellTable(element, isDirtyElement, wasDirtyParentRows) {
|
|
if (Validation.isEmpty(wasDirtyParentRows)) return;
|
|
let tr = DOM.getRowFromElement(element);
|
|
let isDirtyRow = isDirtyElement || DOM.hasDirtyChildrenContainer(tr);
|
|
let wasDirtyRow = wasDirtyParentRows.shift();
|
|
Utils.consoleLogIfNotProductionEnvironment({isDirtyRow, wasDirtyRow});
|
|
if (isDirtyRow != wasDirtyRow) {
|
|
DOM.handleDirtyElement(tr, isDirtyRow);
|
|
this.updateAndToggleShowButtonsSaveCancel();
|
|
this.cascadeChangedIsDirtyNestedElementCellTable(tr.parentElement, isDirtyRow, wasDirtyParentRows);
|
|
}
|
|
}
|
|
hookupChangeHandlerTableCellsWhenNotCollapsed(inputSelector, handler = (event, element) => {
|
|
if (!element.classList.contains(flagIsCollapsed)) this.handleChangeNestedElementCellTable(event, element);
|
|
}) {
|
|
Events.hookupEventHandler("change", inputSelector, handler);
|
|
}
|
|
hookupFieldsCodeTable() {
|
|
this.hookupChangeHandlerTableCells(idTableMain + ' > tbody > tr > td.' + flagCode + ' > .' + flagCode);
|
|
}
|
|
hookupFieldsNameTable() {
|
|
this.hookupChangeHandlerTableCells(idTableMain + ' > tbody > tr > td.' + flagName + ' > .' + flagName);
|
|
}
|
|
hookupFieldsDescriptionTable() {
|
|
this.hookupChangeHandlerTableCells(idTableMain + ' > tbody > tr > td.' + flagDescription + ' > .' + flagDescription);
|
|
}
|
|
hookupFieldsNotesTable() {
|
|
this.hookupChangeHandlerTableCells(idTableMain + ' > tbody > tr > td.' + flagNotes + ' > .' + flagNotes);
|
|
}
|
|
hookupFieldsActive(flagTable = '', handleClickRowNew = (event, element) => { this.handleClickAddRowTable(event, element); }) {
|
|
let selectorButton = 'table.table-main' + (Validation.isEmpty(flagTable) ? '' : '.' + flagTable) + ' > tbody > tr > td.' + flagActive + ' .' + flagButton + '.' + flagActive;
|
|
let selectorButtonDelete = selectorButton + '.' + flagDelete;
|
|
let selectorButtonUndelete = selectorButton + ':not(.' + flagDelete + ')';
|
|
Utils.consoleLogIfNotProductionEnvironment("hookupFieldsActive: ", selectorButtonDelete, selectorButtonUndelete);
|
|
this.hookupButtonsRowDelete(selectorButtonDelete, selectorButtonUndelete);
|
|
this.hookupButtonsRowUndelete(selectorButtonDelete, selectorButtonUndelete);
|
|
Events.hookupEventHandler(
|
|
"click"
|
|
, 'table.table-main' + (Validation.isEmpty(flagTable) ? '' : '.' + flagTable) + ' > thead > tr > th.' + flagActive + ' .' + flagButton + '.' + flagActive
|
|
, (event, button) => { handleClickRowNew(event, button); }
|
|
);
|
|
}
|
|
hookupButtonsRowDelete(selectorButtonDelete, selectorButtonUndelete, changeHandler = (event, element) => { this.handleChangeNestedElementCellTable(event, element); }) {
|
|
Events.hookupEventHandler("click", selectorButtonDelete, (event, element) => {
|
|
this.handleClickButtonRowDelete(event, element, selectorButtonDelete, selectorButtonUndelete, (changeEvent, changeElement) => { changeHandler(changeEvent, changeElement); });
|
|
});
|
|
}
|
|
handleClickButtonRowDelete(event, element, selectorButtonDelete, selectorButtonUndelete, changeHandler = (event, element) => { this.handleChangeNestedElementCellTable(event, element); }) {
|
|
if (element.tagName.toUpperCase() != 'SVG') element = element.parentElement;
|
|
let valuePrevious = DOM.getElementAttributeValuePrevious(element);
|
|
let wasDirty = element.classList.contains(flagDirty);
|
|
let row = DOM.getRowFromElement(element);
|
|
if (row.classList.contains(flagRowNew) && !DOM.hasDirtyChildrenContainer(row)) {
|
|
row.parentNode.removeChild(row);
|
|
}
|
|
else {
|
|
let buttonAddTemplate = document.querySelector(idContainerTemplateElements + ' .' + flagButton + '.' + flagActive + '.' + flagAdd);
|
|
let buttonAdd = buttonAddTemplate.cloneNode(true);
|
|
DOM.setElementAttributeValuePrevious(buttonAdd, valuePrevious);
|
|
DOM.setElementAttributeValueCurrent(buttonAdd, false);
|
|
if (wasDirty) buttonAdd.classList.add(flagDirty);
|
|
element.replaceWith(buttonAdd);
|
|
changeHandler(null, buttonAdd);
|
|
this.hookupButtonsRowUndelete(selectorButtonDelete, selectorButtonUndelete, (changeEvent, changeElement) => { changeHandler(changeEvent, changeElement); });
|
|
}
|
|
this.updateAndToggleShowButtonsSaveCancel();
|
|
}
|
|
hookupButtonsRowUndelete(selectorButtonDelete, selectorButtonUndelete, changeHandler = (event, element) => { this.handleChangeNestedElementCellTable(event, element); }) {
|
|
Events.hookupEventHandler("click", selectorButtonUndelete, (event, element) => {
|
|
this.handleClickButtonRowUndelete(event, element, selectorButtonDelete, selectorButtonUndelete, (changeEvent, changeElement) => { changeHandler(changeEvent, changeElement); });
|
|
});
|
|
}
|
|
handleClickButtonRowUndelete(event, element, selectorButtonDelete, selectorButtonUndelete, changeHandler = (event, element) => { this.handleChangeNestedElementCellTable(event, element); }) {
|
|
if (element.tagName.toUpperCase() != 'SVG') element = element.parentElement;
|
|
let valuePrevious = DOM.getElementAttributeValuePrevious(element);
|
|
let wasDirty = DOM.isElementDirty(element);
|
|
let buttonDeleteTemplate = document.querySelector(idContainerTemplateElements + ' .' + flagButton + '.' + flagActive + '.' + flagDelete);
|
|
let buttonDelete = buttonDeleteTemplate.cloneNode(true);
|
|
DOM.setElementAttributeValuePrevious(buttonDelete, valuePrevious);
|
|
DOM.setElementAttributeValueCurrent(buttonDelete, true);
|
|
if (wasDirty) buttonDelete.classList.add(flagDirty);
|
|
element.replaceWith(buttonDelete);
|
|
changeHandler(null, buttonDelete);
|
|
this.hookupButtonsRowDelete(selectorButtonDelete, selectorButtonUndelete, (changeEvent, changeElement) => { changeHandler(changeEvent, changeElement); });
|
|
this.updateAndToggleShowButtonsSaveCancel();
|
|
}
|
|
hookupTdsAccessLevel() {
|
|
this.hookupTableCellDdlPreviews(flagAccessLevel, Utils.getListFromDict(accessLevels));
|
|
}
|
|
hookupTableCellDdlPreviews(
|
|
fieldFlag
|
|
, optionList
|
|
, cellSelector = null
|
|
, ddlHookup = (ddlSelector) => { this.hookupTableCellDdls(ddlSelector); }
|
|
, changeHandler = (event, element) => { this.handleChangeNestedElementCellTable(event, element); }
|
|
) {
|
|
if (cellSelector == null) cellSelector = idTableMain + ' > tbody > tr > td.' + fieldFlag;
|
|
Events.hookupEventHandler("click", cellSelector + ' div.' + fieldFlag, (event, div) => {
|
|
this.handleClickTableCellDdlPreview(
|
|
event
|
|
, div
|
|
, fieldFlag
|
|
, optionList
|
|
, cellSelector
|
|
, (ddlSelector) => { ddlHookup(
|
|
ddlSelector
|
|
, (event, element) => { changeHandler(event, element); }
|
|
); }
|
|
);
|
|
});
|
|
ddlHookup(cellSelector + ' select.' + fieldFlag);
|
|
}
|
|
hookupTableCellDdls(ddlSelector, changeHandler = (event, element) => { this.handleChangeNestedElementCellTable(event, element); }) {
|
|
this.hookupChangeHandlerTableCells(ddlSelector, (event, element) => { changeHandler(event, element); });
|
|
}
|
|
handleClickTableCellDdlPreview(event, div, fieldFlag, optionObjectList, cellSelector = null, ddlHookup = (cellSelector) => { this.hookupTableCellDdls(cellSelector); }) {
|
|
if (Validation.isEmpty(cellSelector)) cellSelector = idTableMain + ' > tbody > tr > td.' + fieldFlag;
|
|
let idSelected = DOM.getElementAttributeValueCurrent(div);
|
|
let td = DOM.getCellFromElement(div);
|
|
td.innerHTML = '';
|
|
let ddl = document.createElement('select');
|
|
ddl.classList.add(fieldFlag);
|
|
DOM.setElementValuesCurrentAndPrevious(ddl, idSelected);
|
|
let optionJson, option;
|
|
if (_verbose) {
|
|
Utils.consoleLogIfNotProductionEnvironment("click table cell ddl preview");
|
|
Utils.consoleLogIfNotProductionEnvironment({optionObjectList, cellSelector});
|
|
}
|
|
option = DOM.createOption(null);
|
|
ddl.appendChild(option);
|
|
optionObjectList.forEach((optionObjectJson) => {
|
|
optionJson = BusinessObjects.getOptionJsonFromObjectJson(optionObjectJson, idSelected);
|
|
option = DOM.createOption(optionJson);
|
|
ddl.appendChild(option);
|
|
});
|
|
td.appendChild(ddl);
|
|
let ddlSelector = cellSelector + ' select.' + fieldFlag;
|
|
ddlHookup(ddlSelector);
|
|
}
|
|
/*
|
|
hookupTableCellDDlPreviewsWhenNotCollapsed(cellSelector, optionList, ddlHookup = (event, element) => { this.hookupTableCellDdls(event, element); }) {
|
|
Events.hookupEventHandler("click", cellSelector + ' div', (event, div) => {
|
|
this.handleClickTableCellDdlPreview(event, div, optionList, cellSelector, (event, element) => { ddlHookup(event, element); });
|
|
});
|
|
}
|
|
*/
|
|
toggleColumnCollapsed(flagColumn, isCollapsed) {
|
|
this.toggleColumnHasClassnameFlag(flagColumn, isCollapsed, flagIsCollapsed);
|
|
}
|
|
toggleColumnHeaderCollapsed(flagColumn, isCollapsed) {
|
|
this.toggleColumnHasClassnameFlag(flagColumn, isCollapsed, flagIsCollapsed);
|
|
}
|
|
|
|
hookupFieldsCommandCategory(idTable = null) {
|
|
if (idTable == null) idTable = idTableMain;
|
|
this.hookupTableCellDdlPreviews(
|
|
flagCommandCategory
|
|
, Utils.getListFromDict(filterCommandCategories).sort((a, b) => a[flagName].localeCompare(b[flagName]))
|
|
, idTable + ' > tbody > tr > td.' + flagCommandCategory // + ' .' + flagCommandCategory
|
|
, (cellSelector) => { this.hookupCommandCategoryDdls(cellSelector); }
|
|
);
|
|
}
|
|
hookupCommandCategoryDdls(ddlSelector) {
|
|
this.hookupChangeHandlerTableCells(ddlSelector, (event, element) => { this.handleChangeCommandCategoryDdl(event, element); });
|
|
}
|
|
handleChangeCommandCategoryDdl(event, ddlCategory) {
|
|
let row = DOM.getRowFromElement(ddlCategory);
|
|
let idCommandCategoryRowOld = this.getIdCommandCategoryRow(row); // DOM.getElementAttributeValueCurrent(ddlCategory);
|
|
this.handleChangeNestedElementCellTable(event, ddlCategory);
|
|
let idCommandCategoryRowNew = this.getIdCommandCategoryRow(row); // DOM.getElementAttributeValueCurrent(ddlCategory);
|
|
if (
|
|
idCommandCategoryRowOld == idCommandCategoryRowNew
|
|
|| idCommandCategoryRowNew == 0
|
|
) return;
|
|
console.log({ idCommandCategoryRowNew, idCommandCategoryRowOld });
|
|
let idCommandCategoryFilter = this.getIdCommandCategoryFilter();
|
|
let tdCommand = row.querySelector('td.' + flagCommand);
|
|
tdCommand.dispatchEvent(new Event('click'));
|
|
let ddlCommand = row.querySelector('td.' + flagCommand + ' select.' + flagCommand);
|
|
ddlCommand.innerHTML = '';
|
|
ddlCommand.appendChild(DOM.createOption(null));
|
|
let optionJson, option;
|
|
let commandsInCategory = Utils.getListFromDict(filterCommands).filter(command =>
|
|
(
|
|
command[attrIdCommandCategory] == idCommandCategoryRowNew
|
|
|| idCommandCategoryRowNew == 0
|
|
)
|
|
&& (
|
|
command[attrIdCommandCategory] == idCommandCategoryFilter
|
|
|| idCommandCategoryFilter == 0
|
|
)
|
|
);
|
|
let sortedCommands = commandsInCategory.sort((a, b) => a[flagName].localeCompare(b[flagName]));
|
|
sortedCommands.forEach((command) => {
|
|
optionJson = BusinessObjects.getOptionJsonFromObjectJson(command);
|
|
option = DOM.createOption(optionJson);
|
|
ddlCommand.appendChild(option);
|
|
});
|
|
this.handleChangeNestedElementCellTable(event, ddlCommand);
|
|
}
|
|
hookupFieldsCommand(idTable = null) {
|
|
if (idTable == null) idTable = idTableMain;
|
|
Events.hookupEventHandler("click", idTable + ' > tbody > tr > td.' + flagCommand + ' div.' + flagCommand, (event, div) => {
|
|
Utils.consoleLogIfNotProductionEnvironment(div);
|
|
let parentTr = DOM.getRowFromElement(div);
|
|
Utils.consoleLogIfNotProductionEnvironment({ div, parentTr });
|
|
let tdCommandCategory = parentTr.querySelector('td.' + flagCommandCategory);
|
|
let idCommandCategoryRow = this.getIdCommandCategoryRow(parentTr); // DOM.getElementAttributeValueCurrent(tdCommandCategory);
|
|
let idCommandCategoryFilter = this.getIdCommandCategoryFilter();
|
|
let filterCommandList = Utils.getListFromDict(filterCommands);
|
|
let commandsInCategory = filterCommandList.filter(command =>
|
|
(
|
|
command[attrIdCommandCategory] == idCommandCategoryRow
|
|
|| idCommandCategoryRow == 0
|
|
)
|
|
&& (
|
|
command[attrIdCommandCategory] == idCommandCategoryFilter
|
|
|| idCommandCategoryFilter == 0
|
|
)
|
|
);
|
|
let sortedCommands = commandsInCategory.sort((a, b) => a[flagName].localeCompare(b[flagName]));
|
|
Utils.consoleLogIfNotProductionEnvironment({ tdCommandCategory, idCommandCategoryRow, idCommandCategoryFilter, filterCommandList, commandsInCategory });
|
|
Utils.consoleLogIfNotProductionEnvironment(filterCommandList);
|
|
this.handleClickTableCellDdlPreview(
|
|
event
|
|
, div
|
|
, flagCommand // fieldFlag
|
|
, sortedCommands // optionList
|
|
, idTable + ' > tbody > tr > td.' + flagCommand // cellSelector
|
|
, (cellSelector) => { this.hookupTableCellDdls(
|
|
cellSelector
|
|
, (event, element) => { this.handleChangeCommandDdl(event, element); }
|
|
); }
|
|
);
|
|
});
|
|
this.hookupTableCellDdls(
|
|
idTable + ' > tbody > tr > td.' + flagCommand + ' select.' + flagCommand
|
|
, (event, element) => { this.handleChangeCommandDdl(event, element); }
|
|
);
|
|
}
|
|
handleChangeCommandDdl(event, ddlCommand) {
|
|
// console.log("handle change command ddl");
|
|
let row = DOM.getRowFromElement(ddlCommand);
|
|
this.handleChangeNestedElementCellTable(event, ddlCommand);
|
|
let idCommandCategoryRowOld = this.getIdCommandCategoryRow(row);
|
|
let idCommandNew = this.getIdCommandRow(row);
|
|
let commandNew = filterCommands[idCommandNew];
|
|
// console.log({ idCommandCategoryRowOld, commandNew });
|
|
if (commandNew == null || idCommandCategoryRowOld == commandNew[attrIdCommandCategory]) return;
|
|
let divCommandCategory = row.querySelector('td.' + flagCommandCategory + ' div');
|
|
if (divCommandCategory) divCommandCategory.dispatchEvent(new Event('click'));
|
|
let ddlCommandCategory = row.querySelector('td.' + flagCommandCategory + ' select.' + flagCommandCategory);
|
|
DOM.setElementValueCurrent(ddlCommandCategory, commandNew[attrIdCommandCategory]);
|
|
// console.log({ ddlCommandCategory, commandNew });
|
|
this.handleChangeNestedElementCellTable(event, ddlCommandCategory);
|
|
}
|
|
getIdCommandCategoryRow(tr) {
|
|
let elementCommandCategory = tr.querySelector('td.' + flagCommandCategory + ' .' + flagCommandCategory);
|
|
return DOM.getElementAttributeValueCurrent(elementCommandCategory);
|
|
}
|
|
getIdCommandCategoryFilter() {
|
|
let formFilters = TableBasePage.getFormFilters();
|
|
let idCommandCategory = 0;
|
|
if (formFilters == null) return idCommandCategory;
|
|
let commandCategoryFilter = formFilters.querySelector('#' + attrIdCommandCategory);
|
|
let commandFilter = formFilters.querySelector('#' + attrIdCommand);
|
|
let valueCurrentCommandCategoryFilter = DOM.getElementAttributeValueCurrent(commandCategoryFilter);
|
|
Utils.consoleLogIfNotProductionEnvironment({ valueCurrentCommandCategoryFilter });
|
|
if (valueCurrentCommandCategoryFilter == "") {
|
|
let valueCurrentCommandFilter = DOM.getElementAttributeValueCurrent(commandFilter);
|
|
Utils.consoleLogIfNotProductionEnvironment({ valueCurrentCommandFilter });
|
|
if (valueCurrentCommandFilter != "") {
|
|
let command = filterCommands[valueCurrentCommandFilter];
|
|
idCommandCategory = command[attrIdCommandCategory];
|
|
}
|
|
} else {
|
|
idCommandCategory = parseInt(valueCurrentCommandCategoryFilter);
|
|
}
|
|
return idCommandCategory;
|
|
}
|
|
getHasCommandCategoryFilter() {
|
|
let idCommandCategoryFilter = this.getIdCommandCategoryFilter();
|
|
return !(Validation.isEmpty(idCommandCategoryFilter) || idCommandCategoryFilter == 0);
|
|
}
|
|
getIdCommandRow(tr) {
|
|
let elementCommand = tr.querySelector('td.' + flagCommand + ' .' + flagCommand);
|
|
return DOM.getElementAttributeValueCurrent(elementCommand);
|
|
}
|
|
getIdCommandFilter() {
|
|
let formFilters = TableBasePage.getFormFilters();
|
|
let commandFilter = formFilters.querySelector('#' + attrIdCommand);
|
|
let valueCurrentCommandFilter = DOM.getElementAttributeValueCurrent(commandFilter);
|
|
let idCommand = parseInt(valueCurrentCommandFilter);
|
|
return idCommand;
|
|
}
|
|
getHasCommandFilter() {
|
|
let idCommandFilter = this.getIdCommandFilter();
|
|
return !(Validation.isEmpty(idCommandFilter) || idCommandFilter == 0);
|
|
}
|
|
/*
|
|
createTdActive(isActive) {
|
|
let tdActive = document.createElement("td");
|
|
tdActive.classList.add(flagActive);
|
|
let buttonActive = document.createElement("button");
|
|
buttonActive.classList.add(flagActive);
|
|
buttonActive.classList.add(isActive ? flagDelete : flagAdd);
|
|
buttonActive.textContent = isActive ? 'x' : '+';
|
|
DOM.setElementAttributesValuesCurrentAndPrevious(buttonActive, isActive);
|
|
tdActive.appendChild(buttonActive);
|
|
return tdActive;
|
|
}
|
|
*/
|
|
leave() {
|
|
if (this.constructor === TableBasePage) {
|
|
throw new Error("Must implement leave() method.");
|
|
}
|
|
super.leave();
|
|
let formFilters = TableBasePage.getFormFilters();
|
|
let dataPage = {};
|
|
dataPage[flagFormFilters] = DOM.convertForm2JSON(formFilters);
|
|
this.setLocalStoragePage(dataPage);
|
|
}
|
|
|
|
toggleColumnHasClassnameFlag(columnFlag, isRequiredFlag, classnameFlag) {
|
|
let table = TableBasePage.getTableMain();
|
|
let columnTh = table.querySelector('th.' + columnFlag);
|
|
let columnThHasFlag = columnTh.classList.contains(classnameFlag);
|
|
if (isRequiredFlag == columnThHasFlag) return;
|
|
DOM.toggleElementHasClassnameFlag(columnTh, isRequiredFlag, classnameFlag);
|
|
}
|
|
toggleColumnHeaderHasClassnameFlag(columnFlag, isRequiredFlag, classnameFlag) {
|
|
let table = TableBasePage.getTableMain();
|
|
let columnTh = table.querySelector('th.' + columnFlag);
|
|
DOM.toggleElementHasClassnameFlag(columnTh, isRequiredFlag, classnameFlag);
|
|
}
|
|
|
|
updateAndToggleShowButtonsSaveCancel() {
|
|
// let pageBody = document.querySelector(idPageBody);
|
|
let isDirty = DOM.hasDirtyChildrenContainer(pageBody);
|
|
|
|
let buttonContainerSelector = '.' + flagContainer + '.' + flagSave + '.' + flagCancel;
|
|
let buttonSave = document.querySelector(buttonContainerSelector + ' ' + idButtonSave);
|
|
let areVisibleSaveCancelButtons = !buttonSave.classList.contains(flagIsCollapsed);
|
|
|
|
console.log({ pageBody, isDirty, areVisibleSaveCancelButtons });
|
|
|
|
this.toggleShowButtonsSaveCancel(isDirty || areVisibleSaveCancelButtons);
|
|
}
|
|
}
|