UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

328 lines (327 loc) • 16.3 kB
/** * DevExtreme (esm/__internal/grids/grid_core/master_detail/module.js) * Version: 22.1.9 * Build date: Tue Apr 18 2023 * * Copyright (c) 2012 - 2023 Developer Express Inc. ALL RIGHTS RESERVED * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/ */ import { getHeight, getWidth } from "../../../../core/utils/size"; import $ from "../../../../core/renderer"; import { grep } from "../../../../core/utils/common"; import { each } from "../../../../core/utils/iterator"; import { isDefined } from "../../../../core/utils/type"; import { when, Deferred } from "../../../../core/utils/deferred"; import gridCoreUtils from "../module_utils"; const MASTER_DETAIL_CELL_CLASS = "dx-master-detail-cell"; const MASTER_DETAIL_ROW_CLASS = "dx-master-detail-row"; const CELL_FOCUS_DISABLED_CLASS = "dx-cell-focus-disabled"; const ROW_LINES_CLASS = "dx-row-lines"; export const masterDetailModule = { defaultOptions: () => ({ masterDetail: { enabled: false, autoExpandAll: false, template: null } }), extenders: { controllers: { columns: { _getExpandColumnsCore() { const expandColumns = this.callBase(); if (this.option("masterDetail.enabled")) { expandColumns.push({ type: "detailExpand", cellTemplate: gridCoreUtils.getExpandCellTemplate() }) } return expandColumns } }, data: function() { const initMasterDetail = function(that) { that._expandedItems = []; that._isExpandAll = that.option("masterDetail.autoExpandAll") }; return { init() { initMasterDetail(this); this.callBase() }, expandAll(groupIndex) { const that = this; if (groupIndex < 0) { that._isExpandAll = true; that._expandedItems = []; that.updateItems() } else { that.callBase.apply(that, arguments) } }, collapseAll(groupIndex) { const that = this; if (groupIndex < 0) { that._isExpandAll = false; that._expandedItems = []; that.updateItems() } else { that.callBase.apply(that, arguments) } }, isRowExpanded(key) { const that = this; const expandIndex = gridCoreUtils.getIndexByKey(key, that._expandedItems); if (Array.isArray(key)) { return that.callBase.apply(that, arguments) } return !!(that._isExpandAll ^ (expandIndex >= 0 && that._expandedItems[expandIndex].visible)) }, _getRowIndicesForExpand(key) { const rowIndex = this.getRowIndexByKey(key); return [rowIndex, rowIndex + 1] }, _changeRowExpandCore(key) { const that = this; let result; if (Array.isArray(key)) { result = that.callBase.apply(that, arguments) } else { const expandIndex = gridCoreUtils.getIndexByKey(key, that._expandedItems); if (expandIndex >= 0) { const { visible: visible } = that._expandedItems[expandIndex]; that._expandedItems[expandIndex].visible = !visible } else { that._expandedItems.push({ key: key, visible: true }) } that.updateItems({ changeType: "update", rowIndices: that._getRowIndicesForExpand(key) }); result = (new Deferred).resolve() } return result }, _processDataItem(data, options) { const dataItem = this.callBase.apply(this, arguments); dataItem.isExpanded = this.isRowExpanded(dataItem.key); if (void 0 === options.detailColumnIndex) { options.detailColumnIndex = -1; each(options.visibleColumns, (index, column) => { if ("expand" === column.command && !isDefined(column.groupIndex)) { options.detailColumnIndex = index; return false } }) } if (options.detailColumnIndex >= 0) { dataItem.values[options.detailColumnIndex] = dataItem.isExpanded } return dataItem }, _processItems(items, change) { const that = this; const { changeType: changeType } = change; const result = []; items = that.callBase.apply(that, arguments); if ("loadingAll" === changeType) { return items } if ("refresh" === changeType) { that._expandedItems = grep(that._expandedItems, item => item.visible) } each(items, (index, item) => { result.push(item); const expandIndex = gridCoreUtils.getIndexByKey(item.key, that._expandedItems); if ("data" === item.rowType && (item.isExpanded || expandIndex >= 0) && !item.isNewRow) { result.push({ visible: item.isExpanded, rowType: "detail", key: item.key, data: item.data, values: [] }) } }); return result }, optionChanged(args) { const that = this; let isEnabledChanged; let isAutoExpandAllChanged; if ("masterDetail" === args.name) { args.name = "dataSource"; switch (args.fullName) { case "masterDetail": { const value = args.value || {}; const previousValue = args.previousValue || {}; isEnabledChanged = value.enabled !== previousValue.enabled; isAutoExpandAllChanged = value.autoExpandAll !== previousValue.autoExpandAll; break } case "masterDetail.template": initMasterDetail(that); break; case "masterDetail.enabled": isEnabledChanged = true; break; case "masterDetail.autoExpandAll": isAutoExpandAllChanged = true } if (isEnabledChanged || isAutoExpandAllChanged) { initMasterDetail(that) } } that.callBase(args) } } }(), resizing: { fireContentReadyAction() { this.callBase.apply(this, arguments); this._updateParentDataGrids(this.component.$element()) }, _updateParentDataGrids($element) { const $masterDetailRow = $element.closest(".dx-master-detail-row"); if ($masterDetailRow.length) { when(this._updateMasterDataGrid($masterDetailRow, $element)).done(() => { this._updateParentDataGrids($masterDetailRow.parent()) }) } }, _updateMasterDataGrid($masterDetailRow, $detailElement) { const masterRowOptions = $($masterDetailRow).data("options"); const masterDataGrid = $($masterDetailRow).closest("." + this.getWidgetContainerClass()).parent().data("dxDataGrid"); if (masterRowOptions && masterDataGrid) { return this._updateMasterDataGridCore(masterDataGrid, masterRowOptions) } }, _updateMasterDataGridCore(masterDataGrid, masterRowOptions) { const d = Deferred(); if (masterDataGrid.getView("rowsView").isFixedColumns()) { this._updateFixedMasterDetailGrids(masterDataGrid, masterRowOptions.rowIndex, $(masterRowOptions.rowElement)).done(d.resolve) } else { if (true === masterDataGrid.option("scrolling.useNative")) { masterDataGrid.updateDimensions().done(() => d.resolve(true)); return } const scrollable = masterDataGrid.getScrollable(); if (scrollable) { null === scrollable || void 0 === scrollable ? void 0 : scrollable.update().done(() => d.resolve()) } else { d.resolve() } } return d.promise() }, _updateFixedMasterDetailGrids(masterDataGrid, masterRowIndex, $detailElement) { const d = Deferred(); const $rows = $(masterDataGrid.getRowElement(masterRowIndex)); const $tables = $(masterDataGrid.getView("rowsView").getTableElements()); const rowsNotEqual = 2 === (null === $rows || void 0 === $rows ? void 0 : $rows.length) && getHeight($rows.eq(0)) !== getHeight($rows.eq(1)); const tablesNotEqual = 2 === (null === $tables || void 0 === $tables ? void 0 : $tables.length) && getHeight($tables.eq(0)) !== getHeight($tables.eq(1)); if (rowsNotEqual || tablesNotEqual) { const detailElementWidth = getWidth($detailElement); masterDataGrid.updateDimensions().done(() => { const isDetailHorizontalScrollCanBeShown = this.option("columnAutoWidth") && true === masterDataGrid.option("scrolling.useNative"); const isDetailGridWidthChanged = isDetailHorizontalScrollCanBeShown && detailElementWidth !== getWidth($detailElement); if (isDetailHorizontalScrollCanBeShown && isDetailGridWidthChanged) { this.updateDimensions().done(() => d.resolve(true)) } else { d.resolve(true) } }); return d.promise() } return Deferred().resolve() }, _toggleBestFitMode(isBestFit) { this.callBase.apply(this, arguments); if (this.option("masterDetail.template")) { const $rowsTable = this._rowsView.getTableElement(); if ($rowsTable) { $rowsTable.find(".dx-master-detail-cell").css("maxWidth", isBestFit ? 0 : "") } } } } }, views: { rowsView: { _getCellTemplate(options) { const that = this; const { column: column } = options; const editingController = that.getController("editing"); const isEditRow = editingController && editingController.isEditRow(options.rowIndex); let template; if ("detail" === column.command && !isEditRow) { template = that.option("masterDetail.template") || { allowRenderToDetachedContainer: false, render: that._getDefaultTemplate(column) } } else { template = that.callBase.apply(that, arguments) } return template }, _isDetailRow: row => row && row.rowType && 0 === row.rowType.indexOf("detail"), _createRow(row) { const $row = this.callBase.apply(this, arguments); if (row && this._isDetailRow(row)) { this.option("showRowLines") && $row.addClass("dx-row-lines"); $row.addClass("dx-master-detail-row"); if (isDefined(row.visible)) { $row.toggle(row.visible) } } return $row }, _renderCells($row, options) { const { row: row } = options; let $detailCell; const visibleColumns = this._columnsController.getVisibleColumns(); if (row.rowType && this._isDetailRow(row)) { if (this._needRenderCell(0, options.columnIndices)) { $detailCell = this._renderCell($row, { value: null, row: row, rowIndex: row.rowIndex, column: { command: "detail" }, columnIndex: 0, change: options.change }); $detailCell.addClass("dx-cell-focus-disabled").addClass("dx-master-detail-cell").attr("colSpan", visibleColumns.length) } } else { this.callBase.apply(this, arguments) } } } } } };