UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

742 lines (659 loc) • 29.5 kB
"use strict"; var $ = require("../../core/renderer"), gridCore = require("./ui.data_grid.core"), ExpandedGroupingHelper = require("./ui.data_grid.grouping.expanded").GroupingHelper, CollapsedGroupingHelper = require("./ui.data_grid.grouping.collapsed").GroupingHelper, messageLocalization = require("../../localization/message"), dataSourceAdapter = require("./ui.data_grid.data_source_adapter"), typeUtils = require("../../core/utils/type"), each = require("../../core/utils/iterator").each, devices = require("../../core/devices"), deferredUtils = require("../../core/utils/deferred"), when = deferredUtils.when, Deferred = deferredUtils.Deferred; var DATAGRID_GROUP_PANEL_CLASS = "dx-datagrid-group-panel", DATAGRID_GROUP_PANEL_MESSAGE_CLASS = "dx-group-panel-message", DATAGRID_GROUP_PANEL_ITEM_CLASS = "dx-group-panel-item", DATAGRID_GROUP_PANEL_LABEL_CLASS = "dx-toolbar-label", DATAGRID_EXPAND_CLASS = "dx-datagrid-expand", DATAGRID_GROUP_ROW_CLASS = "dx-group-row"; var GroupingDataSourceAdapterExtender = function () { return { init: function init() { this.callBase.apply(this, arguments); this._initGroupingHelper(); }, _initGroupingHelper: function _initGroupingHelper(options) { var grouping = this._grouping, remoteOperations = options ? options.remoteOperations : this.remoteOperations(); if (remoteOperations.filtering && remoteOperations.sorting && remoteOperations.paging && !remoteOperations.grouping) { if (!grouping || grouping instanceof CollapsedGroupingHelper) { this._grouping = new ExpandedGroupingHelper(this); } } else { if (!grouping || grouping instanceof ExpandedGroupingHelper) { this._grouping = new CollapsedGroupingHelper(this); } } }, totalItemsCount: function totalItemsCount() { var that = this, totalCount = that.callBase(); return totalCount > 0 && that._dataSource.group() && that._dataSource.requireTotalCount() ? totalCount + that._grouping.totalCountCorrection() : totalCount; }, itemsCount: function itemsCount() { return this._dataSource.group() ? this._grouping.itemsCount() || 0 : this.callBase(); }, allowCollapseAll: function allowCollapseAll() { return this._grouping.allowCollapseAll(); }, isRowExpanded: function isRowExpanded(key) { var groupInfo = this._grouping.findGroupInfo(key); return groupInfo ? groupInfo.isExpanded : !this._grouping.allowCollapseAll(); }, collapseAll: function collapseAll(groupIndex) { return this._collapseExpandAll(groupIndex, false); }, expandAll: function expandAll(groupIndex) { return this._collapseExpandAll(groupIndex, true); }, _collapseExpandAll: function _collapseExpandAll(groupIndex, isExpand) { var that = this, dataSource = that._dataSource, group = dataSource.group(), groups = gridCore.normalizeSortingInfo(group || []), i; if (groups.length) { for (i = 0; i < groups.length; i++) { if (groupIndex === undefined || groupIndex === i) { groups[i].isExpanded = isExpand; } else if (group && group[i]) { groups[i].isExpanded = group[i].isExpanded; } } dataSource.group(groups); that._grouping.foreachGroups(function (groupInfo, parents) { if (groupIndex === undefined || groupIndex === parents.length - 1) { groupInfo.isExpanded = isExpand; } }, false, true); } return true; }, refresh: function refresh() { this.callBase.apply(this, arguments); return this._grouping.refresh.apply(this._grouping, arguments); }, changeRowExpand: function changeRowExpand(path) { var that = this, dataSource = that._dataSource; if (dataSource.group()) { dataSource.beginLoading(); return that._changeRowExpandCore(path).always(function () { dataSource.endLoading(); }); } }, _changeRowExpandCore: function _changeRowExpandCore(path) { return this._grouping.changeRowExpand(path); }, ///#DEBUG getGroupsInfo: function getGroupsInfo() { return this._grouping._groupsInfo; }, ///#ENDDEBUG _hasGroupLevelsExpandState: function _hasGroupLevelsExpandState(group, isExpanded) { if (group && Array.isArray(group)) { for (var i = 0; i < group.length; i++) { if (group[i].isExpanded === isExpanded) { return true; } } } }, _customizeRemoteOperations: function _customizeRemoteOperations(options, isReload, operationTypes) { var remoteOperations = options.remoteOperations; if (options.storeLoadOptions.group) { if (remoteOperations.grouping && !options.isCustomLoading) { if (!remoteOperations.groupPaging || this._hasGroupLevelsExpandState(options.storeLoadOptions.group, true)) { remoteOperations.paging = false; } } if (!remoteOperations.grouping && (!remoteOperations.sorting || !remoteOperations.filtering || options.isCustomLoading || this._hasGroupLevelsExpandState(options.storeLoadOptions.group, false))) { remoteOperations.paging = false; } } else if (!options.isCustomLoading && remoteOperations.paging && operationTypes.grouping) { this.resetCache(); } this.callBase.apply(this, arguments); }, _handleDataLoading: function _handleDataLoading(options) { this.callBase(options); this._initGroupingHelper(options); return this._grouping.handleDataLoading(options); }, _handleDataLoaded: function _handleDataLoaded(options) { return this._grouping.handleDataLoaded(options, this.callBase.bind(this)); }, _handleDataLoadedCore: function _handleDataLoadedCore(options) { return this._grouping.handleDataLoadedCore(options, this.callBase.bind(this)); } }; }(); dataSourceAdapter.extend(GroupingDataSourceAdapterExtender); var GroupingDataControllerExtender = function () { return { init: function init() { var that = this; that.callBase(); that.createAction("onRowExpanding"); that.createAction("onRowExpanded"); that.createAction("onRowCollapsing"); that.createAction("onRowCollapsed"); }, _beforeProcessItems: function _beforeProcessItems(items) { var groupColumns = this._columnsController.getGroupColumns(); items = this.callBase(items); if (items.length && groupColumns.length) { items = this._processGroupItems(items, groupColumns.length); } return items; }, _processItem: function _processItem(item, options) { if (typeUtils.isDefined(item.groupIndex) && typeUtils.isString(item.rowType) && item.rowType.indexOf("group") === 0) { item = this._processGroupItem(item, options); options.dataIndex = 0; } else { item = this.callBase.apply(this, arguments); } return item; }, _processGroupItem: function _processGroupItem(item) { return item; }, _processGroupItems: function _processGroupItems(items, groupsCount, options) { var that = this, groupedColumns = that._columnsController.getGroupColumns(), column = groupedColumns[groupedColumns.length - groupsCount], scrollingMode, i, item, resultItems; if (!options) { scrollingMode = that.option("scrolling.mode"); options = { collectContinuationItems: scrollingMode !== "virtual" && scrollingMode !== "infinite", resultItems: [], path: [], values: [] }; } resultItems = options.resultItems; if (options.data) { if (options.collectContinuationItems || !options.data.isContinuation) { resultItems.push({ rowType: "group", data: options.data, groupIndex: options.path.length - 1, isExpanded: !!options.data.items, key: options.path.slice(0), values: options.values.slice(0) }); } } if (items) { if (groupsCount === 0) { resultItems.push.apply(resultItems, items); } else { for (i = 0; i < items.length; i++) { item = items[i]; if (item && "items" in item) { options.data = item; options.path.push(item.key); options.values.push(column && column.deserializeValue ? column.deserializeValue(item.key) : item.key); that._processGroupItems(item.items, groupsCount - 1, options); options.data = undefined; options.path.pop(); options.values.pop(); } else { resultItems.push(item); } } } } return resultItems; }, publicMethods: function publicMethods() { return this.callBase().concat(["collapseAll", "expandAll", "isRowExpanded", "expandRow", "collapseRow"]); }, /** * @name dxDataGridMethods.collapseAll * @publicName collapseAll(groupIndex) * @param1 groupIndex:number | undefined */ collapseAll: function collapseAll(groupIndex) { var dataSource = this._dataSource; if (dataSource && dataSource.collapseAll(groupIndex)) { dataSource.pageIndex(0); dataSource.reload(); } }, /** * @name dxDataGridMethods.expandAll * @publicName expandAll(groupIndex) * @param1 groupIndex:number | undefined */ expandAll: function expandAll(groupIndex) { var dataSource = this._dataSource; if (dataSource && dataSource.expandAll(groupIndex)) { dataSource.pageIndex(0); dataSource.reload(); } }, changeRowExpand: function changeRowExpand(key) { var that = this, expanded = that.isRowExpanded(key), args = { key: key, expanded: expanded }; that.executeAction(expanded ? "onRowCollapsing" : "onRowExpanding", args); if (!args.cancel) { return when(that._changeRowExpandCore(key)).done(function () { args.expanded = !expanded; that.executeAction(expanded ? "onRowCollapsed" : "onRowExpanded", args); }); } return new Deferred().resolve(); }, _changeRowExpandCore: function _changeRowExpandCore(key) { var that = this, dataSource = this._dataSource, d; if (!dataSource) return; d = new Deferred(); when(dataSource.changeRowExpand(key)).done(function () { that.load().done(d.resolve).fail(d.reject); }).fail(d.reject); return d; }, /** * @name dxDataGridMethods.isRowExpanded * @publicName isRowExpanded(key) * @param1 key:any * @return boolean */ isRowExpanded: function isRowExpanded(key) { var dataSource = this._dataSource; return dataSource && dataSource.isRowExpanded(key); }, /** * @name dxDataGridMethods.expandRow * @publicName expandRow(key) * @param1 key:any * @return Promise<void> */ expandRow: function expandRow(key) { if (!this.isRowExpanded(key)) { return this.changeRowExpand(key); } return new Deferred().resolve(); }, /** * @name dxDataGridMethods.collapseRow * @publicName collapseRow(key) * @param1 key:any * @return Promise<void> */ collapseRow: function collapseRow(key) { if (this.isRowExpanded(key)) { return this.changeRowExpand(key); } return new Deferred().resolve(); }, optionChanged: function optionChanged(args) { if (args.name === "grouping" /* autoExpandAll */) { args.name = "dataSource"; } this.callBase(args); } }; }(); var onGroupingMenuItemClick = function onGroupingMenuItemClick(column, params) { var columnsController = this._columnsController; switch (params.itemData.value) { case "group": var groups = columnsController._dataSource.group() || []; columnsController.columnOption(column.dataField, "groupIndex", groups.length); break; case "ungroup": columnsController.columnOption(column.dataField, "groupIndex", -1); break; case "ungroupAll": this.component.clearGrouping(); break; } }; var GroupingHeaderPanelExtender = function () { return { _getToolbarItems: function _getToolbarItems() { var items = this.callBase(); return this._appendGroupingItem(items); }, _appendGroupingItem: function _appendGroupingItem(items) { var that = this, isRendered = false, groupPanelRenderedCallback = function groupPanelRenderedCallback(e) { that._updateGroupPanelContent($(e.itemElement).find("." + DATAGRID_GROUP_PANEL_CLASS)); isRendered && that.renderCompleted.fire(); isRendered = true; }; if (that._isGroupPanelVisible()) { var toolbarItem = { html: "<div class='" + DATAGRID_GROUP_PANEL_CLASS + "'></div>", name: "groupPanel", onItemRendered: groupPanelRenderedCallback, location: "before", locateInMenu: "never", sortIndex: 1 }; items.push(toolbarItem); } return items; }, _isGroupPanelVisible: function _isGroupPanelVisible() { var groupPanelOptions = this.option("groupPanel"), isVisible; if (groupPanelOptions) { isVisible = groupPanelOptions.visible; if (isVisible === "auto") { isVisible = devices.current().deviceType === "desktop" ? true : false; } } return isVisible; }, _renderGroupPanelItems: function _renderGroupPanelItems($groupPanel, groupColumns) { var that = this; $groupPanel.empty(); each(groupColumns, function (index, groupColumn) { that._createGroupPanelItem($groupPanel, groupColumn); }); }, _createGroupPanelItem: function _createGroupPanelItem($rootElement, groupColumn) { return $("<div>").addClass(groupColumn.cssClass).addClass(DATAGRID_GROUP_PANEL_ITEM_CLASS).data("columnData", groupColumn).appendTo($rootElement).text(groupColumn.caption); }, _columnOptionChanged: function _columnOptionChanged(e) { if (!this._requireReady && !gridCore.checkChanges(e.optionNames, ["width", "visibleWidth"])) { var $toolbarElement = this.element(), $groupPanel = $toolbarElement && $toolbarElement.find("." + DATAGRID_GROUP_PANEL_CLASS); if ($groupPanel && $groupPanel.length) { this._updateGroupPanelContent($groupPanel); this.renderCompleted.fire(); } } this.callBase(); }, _updateGroupPanelContent: function _updateGroupPanelContent($groupPanel) { var that = this, groupColumns = that.getController("columns").getGroupColumns(), groupPanelOptions = that.option("groupPanel"); that._renderGroupPanelItems($groupPanel, groupColumns); if (groupPanelOptions.allowColumnDragging && !groupColumns.length) { $("<div>").addClass(DATAGRID_GROUP_PANEL_MESSAGE_CLASS).text(groupPanelOptions.emptyPanelText).appendTo($groupPanel); $groupPanel.closest("." + DATAGRID_GROUP_PANEL_LABEL_CLASS).css("maxWidth", "none"); that.updateToolbarDimensions(); } }, allowDragging: function allowDragging(column) { var groupPanelOptions = this.option("groupPanel"); return this._isGroupPanelVisible() && groupPanelOptions.allowColumnDragging && column && column.allowGrouping; }, getColumnElements: function getColumnElements() { var $element = this.element(); return $element && $element.find("." + DATAGRID_GROUP_PANEL_ITEM_CLASS); }, getColumns: function getColumns() { return this.getController("columns").getGroupColumns(); }, getBoundingRect: function getBoundingRect() { var that = this, $element = that.element(), offset; if ($element && $element.find("." + DATAGRID_GROUP_PANEL_CLASS).length) { offset = $element.offset(); return { top: offset.top, bottom: offset.top + $element.height() }; } return null; }, getName: function getName() { return "group"; }, getContextMenuItems: function getContextMenuItems(options) { var that = this, contextMenuEnabled = that.option("grouping.contextMenuEnabled"), $groupedColumnElement = $(options.targetElement).closest("." + DATAGRID_GROUP_PANEL_ITEM_CLASS), items; if ($groupedColumnElement.length) { options.column = $groupedColumnElement.data("columnData"); } if (contextMenuEnabled && options.column) { var column = options.column, isGroupingAllowed = typeUtils.isDefined(column.allowGrouping) ? column.allowGrouping : true; if (isGroupingAllowed) { var isColumnGrouped = typeUtils.isDefined(column.groupIndex) && column.groupIndex > -1, groupingTexts = that.option("grouping.texts"), onItemClick = onGroupingMenuItemClick.bind(that, column); items = [{ text: groupingTexts.ungroup, value: "ungroup", disabled: !isColumnGrouped, onItemClick: onItemClick }, { text: groupingTexts.ungroupAll, value: "ungroupAll", onItemClick: onItemClick }]; } } return items; }, isVisible: function isVisible() { return this.callBase() || this._isGroupPanelVisible(); }, optionChanged: function optionChanged(args) { if (args.name === "groupPanel") { this._invalidate(); args.handled = true; } else { this.callBase(args); } } }; }(); exports.GroupingHeaderPanelExtender = GroupingHeaderPanelExtender; var GroupingRowsViewExtender = function () { return { getContextMenuItems: function getContextMenuItems(options) { var that = this, contextMenuEnabled = that.option("grouping.contextMenuEnabled"), items; if (contextMenuEnabled && options.row && options.row.rowType === "group") { var columnsController = that._columnsController, column = columnsController.columnOption("groupIndex:" + options.row.groupIndex); if (column && column.allowGrouping) { var groupingTexts = that.option("grouping.texts"), onItemClick = onGroupingMenuItemClick.bind(that, column); items = []; items.push({ text: groupingTexts.ungroup, value: "ungroup", onItemClick: onItemClick }, { text: groupingTexts.ungroupAll, value: "ungroupAll", onItemClick: onItemClick }); } } return items; }, _rowClick: function _rowClick(e) { var that = this, expandMode = that.option("grouping.expandMode"), scrollingMode = that.option("scrolling.mode"), isGroupRowStateChanged = scrollingMode !== "infinite" && expandMode === "rowClick" && $(e.event.target).closest("." + DATAGRID_GROUP_ROW_CLASS).length, isExpandButtonClicked = $(e.event.target).closest("." + DATAGRID_EXPAND_CLASS).length; if (isGroupRowStateChanged || isExpandButtonClicked) { that._changeGroupRowState(e); } that.callBase(e); }, _changeGroupRowState: function _changeGroupRowState(e) { var dataController = this.getController("data"), row = dataController.items()[e.rowIndex]; if (row.rowType !== "detail") { dataController.changeRowExpand(row.key); e.event.preventDefault(); e.handled = true; } } }; }(); var columnHeadersViewExtender = function () { return { getContextMenuItems: function getContextMenuItems(options) { var that = this, contextMenuEnabled = that.option("grouping.contextMenuEnabled"), items = that.callBase(options); if (contextMenuEnabled && options.row && (options.row.rowType === "header" || options.row.rowType === "detailAdaptive")) { var column = options.column; if (!column.command && (!typeUtils.isDefined(column.allowGrouping) || column.allowGrouping)) { var groupingTexts = that.option("grouping.texts"), isColumnGrouped = typeUtils.isDefined(column.groupIndex) && column.groupIndex > -1, onItemClick = onGroupingMenuItemClick.bind(that, column); items = items || []; items.push({ text: groupingTexts.groupByThisColumn, value: "group", beginGroup: true, disabled: isColumnGrouped, onItemClick: onItemClick }); if (column.showWhenGrouped) { items.push({ text: groupingTexts.ungroup, value: "ungroup", disabled: !isColumnGrouped, onItemClick: onItemClick }); } items.push({ text: groupingTexts.ungroupAll, value: "ungroupAll", onItemClick: onItemClick }); } } return items; } }; }(); gridCore.registerModule("grouping", { defaultOptions: function defaultOptions() { return { /** * @name dxDataGridOptions.grouping * @publicName grouping * @type object */ grouping: { /** * @name dxDataGridOptions.grouping.autoExpandAll * @publicName autoExpandAll * @type boolean * @default true */ autoExpandAll: true, /** * @name dxDataGridOptions.grouping.allowCollapsing * @publicName allowCollapsing * @type boolean * @default true */ allowCollapsing: true, /** * @name dxDataGridOptions.grouping.contextMenuEnabled * @publicName contextMenuEnabled * @type boolean * @default false */ contextMenuEnabled: false, /** * @name dxDataGridOptions.grouping.expandMode * @publicName expandMode * @type Enums.GridGroupingExpandMode * @default "buttonClick" */ expandMode: "buttonClick", /** * @name dxDataGridOptions.grouping.texts * @publicName texts * @type object */ texts: { /** * @name dxDataGridOptions.grouping.texts.groupContinuesMessage * @publicName groupContinuesMessage * @type string * @default "Continues on the next page" */ groupContinuesMessage: messageLocalization.format("dxDataGrid-groupContinuesMessage"), /** * @name dxDataGridOptions.grouping.texts.groupContinuedMessage * @publicName groupContinuedMessage * @type string * @default "Continued from the previous page" */ groupContinuedMessage: messageLocalization.format("dxDataGrid-groupContinuedMessage"), /** * @name dxDataGridOptions.grouping.texts.groupByThisColumn * @publicName groupByThisColumn * @type string * @default "Group by This Column" */ groupByThisColumn: messageLocalization.format("dxDataGrid-groupHeaderText"), /** * @name dxDataGridOptions.grouping.texts.ungroup * @publicName ungroup * @type string * @default "Ungroup" */ ungroup: messageLocalization.format("dxDataGrid-ungroupHeaderText"), /** * @name dxDataGridOptions.grouping.texts.ungroupAll * @publicName ungroupAll * @type string * @default "Ungroup All" */ ungroupAll: messageLocalization.format("dxDataGrid-ungroupAllText") } }, /** * @name dxDataGridOptions.groupPanel * @publicName groupPanel * @type object */ groupPanel: { /** * @name dxDataGridOptions.groupPanel.visible * @publicName visible * @type boolean|Enums.Mode * @default false */ visible: false, /** * @name dxDataGridOptions.groupPanel.emptyPanelText * @publicName emptyPanelText * @type string * @default "Drag a column header here to group by that column" */ emptyPanelText: messageLocalization.format("dxDataGrid-groupPanelEmptyText"), /** * @name dxDataGridOptions.groupPanel.allowColumnDragging * @publicName allowColumnDragging * @type boolean * @default true */ allowColumnDragging: true } }; }, extenders: { controllers: { data: GroupingDataControllerExtender, columns: { _getExpandColumnOptions: function _getExpandColumnOptions() { var options = this.callBase.apply(this, arguments); options.cellTemplate = gridCore.getExpandCellTemplate(); return options; } } }, views: { headerPanel: GroupingHeaderPanelExtender, rowsView: GroupingRowsViewExtender, columnHeadersView: columnHeadersViewExtender } } });