UNPKG

profoundjs

Version:

Profound.js Framework and Server

327 lines (302 loc) 14.9 kB
if (!window.plogic) window.plogic = {}; plogic.grid = { // Used by option_buttons widget // gridId = option_buttons["user defined data"] // selectionFieldName = option_buttons["user defined data 2"] (optional - default value is "sopt") doOption: (opt, gridId, selectionFieldName) => { selectionFieldName = selectionFieldName || "option"; // Is there more than 1 grid? arrGridId = gridId.split(","); // Is there more than 1 selection fieldName? arrSelectionFieldName = selectionFieldName.split(","); if (arrGridId.length !== arrSelectionFieldName.length) { alert(`The Option Buttons Widget "user defined data" & "user defined data 2" properties must have the same number of elements.`); return; } for (let i = 0; i < arrGridId.length; i += 1) { const gridObj = getObj(arrGridId[i]); if (gridObj !== null) { const count = gridObj.grid.getRecordCount(); for (let j = 1; j <= count; j += 1) { if (gridObj.grid.getDataValue(j, plogic.string.up("schecked")) === "1") { gridObj.grid.setDataValue(j, plogic.string.up(arrSelectionFieldName[i]), opt); } } } } plogic.button.pressKey("Enter"); }, // Grid - Handle keyboard Mode changed handleKeyboardModeChanged: (panel) => { const isKeyboard = plogic.keyboardMode.getMode(); const iconKeyboardModeOn = "list_alt"; const iconKeyboardModeOff = "check_box"; panel = panel || document; for (const gridWidget of panel.querySelectorAll('div[puiwdgt="grid"]')) { // If there is an icon in the 1st colum of the grid, change it to match the keyboard mode state. if (gridWidget.pui.properties["column headings"] && gridWidget.pui.properties["column headings"].split(",")[0].startsWith("<icon class=")) { const arrColumnHeadings = gridWidget.pui.properties["column headings"].split(","); arrColumnHeadings[0] = `<icon class="plogic--header pui-material-icons">${isKeyboard ? iconKeyboardModeOn : iconKeyboardModeOff}</icon>`; gridWidget.grid.setProperty("column headings", arrColumnHeadings.toString()); } const optionButtons = plogic.optionButtons.getforGrid(gridWidget); if (!optionButtons) continue; for (let row = 1; row <= gridWidget.grid.getRecordCount(); row += 1) { if (gridWidget.pui.properties["display subfile"] !== "false") { gridWidget.grid.setDataValue(row, plogic.string.up("keybrdmode"), isKeyboard); } } } }, // Check if the grid has active filters. isFiltered: (gridObj) => { if (get("filterAllId") === "") { // Set the filterAll field with the retrieved filterAll value. pui.set(`${gridObj.id}_filterAll`, gridObj.grid.getFilter("*all")); } let isFiltered = gridObj.grid.getFilter("*all") !== null && gridObj.grid.getFilter("*all") !== ""; if (!isFiltered) { // Loop on all columns for (let i = 0; i < gridObj.pui.properties["number of columns"]; i += 1) { isFiltered = gridObj.grid.getFilter(i) !== null && gridObj.grid.getFilter(i) !== ""; if (isFiltered) break; } } return isFiltered; }, // Do onfilterchange action onFilterChanged: (gridObj) => { if (!gridObj) { return; } // Check if the grid has active filters. const gridIsFiltered = plogic.grid.isFiltered(gridObj); const filterAllObj = getObj(`${gridObj.id}_filterAll`); if (filterAllObj) { // Add or remove the Remove Filters button depending on if grid has filtered rows or not. plogic.button.toggleRemoveFiltersButton(gridIsFiltered, gridObj, filterAllObj); } }, // Position message subfile based on "messages" output field positionMessageSubfile: (config) => { // Is there an error messages grid ? const msgGridItem = config.metaData.items.filter((item) => item["css class 2"] === "plogic--grid--messages")[0]; if (msgGridItem) { const myGridParent = getObj(msgGridItem.layout); // The grid container const myGrid = getObj(msgGridItem.id).grid; // The grid object if (myGridParent && myGrid) { // Update grid width based on its container width const newWidth = `${myGridParent.clientWidth - parseInt(msgGridItem.left, 10) - 20}px`; myGrid.setProperty("column widths", `${newWidth}`); myGrid.setProperty("width", `${newWidth}px`); myGrid.render(); } } }, // Remove all filters removeFilter: (gridObj, filterAllObj, removeFilterButton) => { pui.set(filterAllObj.id, ""); // Clear the filterAll field if (gridObj && gridObj.grid) { gridObj.grid.removeAllFilters(); } }, // Resize a grid based on its parent width resizeGrid: (gridObj) => { const myGridParent = gridObj.parentElement; // The grid container const myGrid = gridObj.grid; // Update grid width based on its container width const newWidth = `${myGridParent.clientWidth - parseInt(gridObj.style.left, 10) - 20}px`; myGrid.setProperty("column widths", `${newWidth}`); myGrid.setProperty("width", `${newWidth}px`); myGrid.render(); }, // Row click -> is there a checkbox to select ? rowClick: (row, rowNumber, event) => { const gridWidget = event.srcElement.closest('div[puiwdgt="grid"]'); // Don't do anything on blank rows if (row > gridWidget.grid.getRecordCount()) return; let checkBox = getObj(`schecked.${row}`); const simpleSelector = getObj(`${gridWidget.id.toLowerCase()}_selector.${row}`); if (simpleSelector) { simpleSelector.focus(); } else { const comboBox = checkBox && checkBox.previousElementSibling; // Don't do anything if the selectors (combo box AND checkbox) are protected if ( checkBox && (checkBox.classList.contains("PR") || checkBox.pui.properties["read only"] === "true") && comboBox && (comboBox.classList.contains("PR") || comboBox.pui.properties["read only"] === "true") ) { return; } // Don't do anything if the selectors (combo box AND checkbox) are hidden if ( checkBox && (checkBox.classList.contains("hidden") || checkBox.pui.properties.visibility === "hidden") && comboBox && (comboBox.classList.contains("hidden") || comboBox.pui.properties.visibility === "hidden") ) { return; } // Don't do anything if the selector is protected if (getObj(`schecked.${row}`) && getObj(`schecked.${row}`).pui.properties["read only"] === "true") return; // Don't set the option if keyboard mode and row is selected if (plogic.keyboardMode.getMode() && event && event.detail === 1) return; // Do not select when not keyboard mode, single click and checkbox does not exist if (!plogic.keyboardMode.getMode() && event && event.detail === 1 && !checkBox) return; } let makeSelected = event && event.detail === 2; if (!makeSelected) { const data = gridWidget.grid.getAllDataValues(); // We use rowNumber because of possible filtered or sorted rows. makeSelected = !(data[rowNumber - 1][plogic.string.up("schecked")] == "1" ? true : false); } if (!simpleSelector) { if (makeSelected) plogic.grid.setOption(gridWidget, row); else plogic.grid.setOption(gridWidget, row, ""); } // Double-click if (event && event.detail === 2) plogic.button.pressKey("Enter"); }, // Sometimes, grids have column headings built with variables. Those headings have been temporary tagged by the conversion theme as @[item_fieldName]. // This function will build "column headings" property based on those individuals fields. setColumnHeadings: (format) => { const arrGrids = format.metaData.items.filter((item) => item["field type"] === "grid" && !item["subfile message key"]); for (const gridWidget of arrGrids) { if (gridWidget["column headings"]) { const arrHeadings = gridWidget["column headings"].split(","); let arrTempFieldNames = []; for (let j = 0; j < arrHeadings.length; j += 1) { // If the heading corresponds to an individual field, let's replace the dummy value with the field value. if (arrHeadings[j].includes("@[") && arrHeadings[j].includes("]")) { const heading = arrHeadings[j]; const posStart = heading.indexOf("@[") + 2; const posEnd = heading.indexOf("]"); if (posStart >= posEnd) return; const tempFieldName = arrHeadings[j].substring(posStart, posEnd); // If there is more than one variable inside the brackets, the separator has to be ";;". if (tempFieldName.includes(";;")) { arrTempFieldNames = tempFieldName.split(";;"); } else { arrTempFieldNames = []; arrTempFieldNames.push(tempFieldName); } let tempHeading; arrHeadings[j] = ""; for (let k = 0; k < arrTempFieldNames.length; k += 1) { let currentItem = format.metaData.items.find((item) => item.value && item.value.fieldName && item.value.fieldName === arrTempFieldNames[k]); if (!currentItem) { currentItem = format.metaData.items.find((item) => item.id.endsWith(arrTempFieldNames[k])); } if (currentItem) { tempHeading = plogic.fields.getItemValue(currentItem, format); } // If the field has a conditioned visibility if ( currentItem && currentItem.visibility && currentItem.visibility.fieldName && currentItem.visibility.dataType === "expression" && currentItem.visibility.formatting === "Indicator" ) { const indicatorValue = format.data[`*IN${currentItem.visibility.fieldName.trim("N")}`]; // If not visible, search for the opposite field if ( (indicatorValue === "0" && currentItem.visibility.indFormat === "visible / hidden") || (indicatorValue === "1" && currentItem.visibility.indFormat === "hidden / visible") ) { // Opposite item = if the current item has a visibility conditioned by an indicator, we search the item with the same row/column and with opposite visibility. const oppositeItem = plogic.fields.getOppositeItem(currentItem, format.metaData.items); if (oppositeItem) { tempHeading = plogic.fields.getItemValue(oppositeItem, format); } } } if (k > 0) tempHeading = ` ${tempHeading}`; // Add a space between labels // Does currentItem have a "display attribute" property? // If yes, let's add the corresponding CSS class. if (currentItem && currentItem["display attribute field"] && currentItem["display attribute field"].fieldName) { const tempCSS = plogic.string.getClassFromHexcode(format.data[plogic.string.up(currentItem["display attribute field"].fieldName)]); tempHeading = `<div class="${tempCSS}">${tempHeading}</div>`; } arrHeadings[j] += tempHeading; // If last pass if (k === arrTempFieldNames.length - 1) { arrHeadings[j] = heading.replace(`@[${tempFieldName}]`, arrHeadings[j]); // If there is another variable like @[xxx] if (arrHeadings[j].includes("@[")) j -= 1; } } } } gridWidget["column headings"] = arrHeadings.toString(); } } }, // Grid filter Textbox setFilter: (gridId, filterObj) => { if (getObj(gridId) && getObj(gridId).grid) { getObj(gridId).grid.setFilter("*all", filterObj.value); } }, setOption: (gridWidget, row, value) => { const optionButtons = plogic.optionButtons.getforGrid(gridWidget); if (!optionButtons) return; let selecting = false; if (value == null) { value = optionButtons.pui.optionButtons.getDefaultOption(); // Not passing the 'value' parm means we are selecting records and the value takes the default value retruned by getDefaultOption(). // But this default value can only be 1, 2 or 5. If these 3 options are not authorized/available, it will return blank. // Therefore, we need an indicator saying that we are "selecting" records. selecting = true; } // selectionFieldName = option_buttons["user defined data 2"] (optional - default value is "sopt") let selectionFieldName = optionButtons.pui.properties["user defined data 2"] || "option"; // Is there more than 1 selection fieldName? arrSelectionFieldName = selectionFieldName.split(","); for (let i = 0; i < arrSelectionFieldName.length; i += 1) { // Do not change the selector value on blank rows if (row <= gridWidget.grid.getRecordCount()) { gridWidget.grid.setDataValue(row, plogic.string.up(arrSelectionFieldName[i]), value); gridWidget.grid.setDataValue(row, plogic.string.up("schecked"), value.length > 0 || selecting ? "1" : "0"); } } }, setSelection: (gridWidget, row, value) => { const schecked = plogic.string.up("schecked"); // Do not change the selector value on blank rows if (row <= gridWidget.grid.getRecordCount()) { // Only change the value if selecting/deselecting the row if ( gridWidget.grid.getDataValue(row, schecked) !== undefined && ( (gridWidget.grid.getDataValue(row, schecked) === "1" && value === "0") || (gridWidget.grid.getDataValue(row, schecked) === "0" && [undefined, "1"].includes(value)) ) ) { gridWidget.grid.setDataValue(row, schecked, value); } } }, // Update grid column headings css class updateHeadingsClass: (gridObj) => { // Grid column headings cells const arrGridHeaders = Array.prototype.slice.call(gridObj.querySelectorAll(".cell.header-cell")); // Grid 1st row cells const arrGridRow1Cells = Array.prototype.slice.call(gridObj.querySelectorAll(".cell.odd")).slice(0, arrGridHeaders.length); for (let i = 0; i < arrGridRow1Cells.length; i += 1) { // List elements of the grid cell const arrCellChildren = Array.prototype.slice.call(arrGridRow1Cells[i].children); if (arrCellChildren) { // Check if the cell content has the "plogic--monospace" css class. If yes, add that class to the header. const arrElems = arrCellChildren.find((elem) => elem.className.includes("plogic--monospace")); if (arrElems) { arrGridHeaders[i].className += " plogic--monospace"; } } } } };