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 = '
Press "Apply Filters" to refresh the table.
' + 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); } }