'use strict'; var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } /** * Licensed Materials - Property of IBM * IBM Cognos Products: Dashboard * (C) Copyright IBM Corp. 2016, 2020 * US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp. */ define(['../../../widgets/livewidget/nls/StringResources', './Pivot', '../grid/GridDnDManager', 'underscore', '../grid/GridDataProvider', '../grid/GridDropTarget', '../grid/GridContentRenderer', 'react-dom', 'react', 'ca-ui-toolkit', 'react-draggable', 'jquery', '../../../util/DashboardFormatter'], function (StringResources, Pivot, GridDndManager, _, DataProvider, GridDropTarget, GridContentRenderer, ReactDOM, React, Toolkit, Draggable, $, Formatter) { 'use strict'; var ROW_SLOT_ID = 'row_level1'; var COLUMN_SLOT_ID = 'column_level1'; var VALUES_SLOT_ID = 'values'; var PROP_ID_SUPPRESSION = 'suppression'; var PROP_ID_EXPANDCOLLAPSE = 'expandCollapse'; var PROP_ID_HIDDEN_ROWS_AND_COLS = 'hiddenRowsAndColumns'; var MEASURE_ROW_RESIZE_IDENTIFIER = 'Measures_Row'; var DEFAULT_ROW_HEIGHT = 32; var DEFAULT_COLUMN_WIDTH = 120; var MIN_ROW_HEIGHT = 24; var MIN_COLUMN_WIDTH = 24; var SHAPE_WIDTH = 24; // hiddenRowHeight is set as a small float number that is close to 0 to prevent the react removing the dom with 0 height var HIDDEN_ROW_HEIGHT = 0.000001; // hiddenColumnWidth is set as a small float number that is close to 0 to prevent the react removing the dom with 0 width var HIDDEN_COL_WIDTH = 0.000001; var EXPAND_INDENTATION = 24; var AXIS_X = 'x'; var AXIS_Y = 'y'; var AREA_TYPE = { ROW: 'cell_edge_row', COLUMN: 'cell_edge_column', CELL: 'cell', MEASURE: 'values', SUMMARY: 'summary' }; var DEFAULT_TEXT_STYLE = { FONT_SIZE: '10pt', FONT_FAMILY: 'IBM Plex Sans', PADDING_WIDTH: 18 }; return function () { function CrosstabGrid(options) { _classCallCheck(this, CrosstabGrid); options = options || {}; this.$el = options.$el; this.visModel = options.visModel; this.dashboardApi = options.dashboardApi; this.crosstabView = options.crosstabView; this.content = this.crosstabView && this.crosstabView.content; this.colorsService = options.colorsService; this.conditionalFormatting = options.conditionalFormatting; this.dataProvider = new DataProvider(); this.textStyleIndex = { cell: 'dataValueStyles', corner: 'valueHeadingStyles', row: 'rowHeadingStyles', column: 'columnHeadingStyles', summary: 'summaryStyles', selectedArea: 'selectedAreaStyles' }; //crosstab dnd this._gridDnDManager = new GridDndManager({ grid: this, dashboardApi: this.dashboardApi, content: this.content, gridEdgeMappedToId: { row: ROW_SLOT_ID, column: COLUMN_SLOT_ID, values: VALUES_SLOT_ID } }); this._shapeCols = []; } CrosstabGrid.prototype.render = function render(resultData, resizing, renderingNewData, eventHandler) { this.eventHandler = eventHandler; // If the data has changed or we're not resizing (property change) then create the pivot table if (!resizing || renderingNewData || !this.data) { this._pivotTable = new Pivot({ data: resultData, visModel: this.visModel, slots: this.content.getFeature('Visualization').getSlots(), dashboard: this.dashboardApi, conditionalFormatting: this.conditionalFormatting }); this.data = this._pivotTable.create(); // if the data has changed, cached cellWidthStatus needs to be reset this._cellWidthStatus = null; } this._alternateRowFlag = -1; // -1: not initialize, 1: alternate on odd number, 0: alternate on even number. this._cellStartRow = this._pivotTable.colEdgeNestingLevelWithMeasure ? this._pivotTable.colEdgeNestingLevelWithMeasure : this._pivotTable.colEdgeNestingLevel; if (this.gridRef && resizing && !renderingNewData) { //if only do resizing this.onResize(); this.onSyncScrollBar(); return Promise.resolve(true); } else { // dataChange will change the rowNum and colNum of the data, need to re-render the grid this.dataProvider.updateData(this.data); //reset summary indicator flag if (!this._errorWarningAdded) { this.crosstabView.clearInfoIndicator('error_summary_cell'); } else { this._errorWarningAdded = false; } this.$el.addClass('dashboard-common-grid').addClass('xtab-grid'); this._renderReactGrid(); if (this.gridRef) { return Promise.resolve(true); } else { return Promise.resolve(false); } } }; CrosstabGrid.prototype.onResize = function onResize() { this.maxColHeight = this._getMaxColHeight(); this.gridRef && this.gridRef.recomputeGridSize(); }; CrosstabGrid.prototype._getMaxColHeight = function _getMaxColHeight() { return this.$el && this.$el.length && this.$el[0].offsetHeight || Infinity; }; CrosstabGrid.prototype.onSyncScrollBar = function onSyncScrollBar() { // when parent dom is moved or updated the scrollLeft and scrollTop value reset to 0 for the bottom-right-grid // this is a bug in React MultiGrid Level // the fix here is to sync the scrollBar among the three grid before onResize is triggered var $domNode = $(this.$el[0]); var rightBottomGrid = $domNode.find('.ba-common-grid__bottom-right-grid'); var rightTopGrid = $domNode.find('.ba-common-grid__top-right-grid'); var leftBottomGrid = $domNode.find('.ba-common-grid__bottom-left-grid'); $(rightBottomGrid).animate({ scrollLeft: $(rightTopGrid).scrollLeft(), scrollTop: $(leftBottomGrid).scrollTop() }, 0); }; CrosstabGrid.prototype.removeGridView = function removeGridView() { if (this.gridRef && this.$el) { ReactDOM.unmountComponentAtNode(this.$el[0]); this.gridRef = null; } }; CrosstabGrid.prototype.remove = function remove() { this.columnWidths = null; this.rowHeights = null; this.fixedRowHeight = null; this.fixedColumnWidth = null; this.hiddenRowsAndColumns = null; this._cachedHiddenCol = null; this._cachedHiddenRow = null; this._cachedRowDataItemInfo = null; this._cachedLevelInfo = null; this._cachedColumnDataItemInfo = null; this.expandCollapseFeature = null; this.isExpandable = null; this.dataProvider = null; this.data = null; this._pivotTable = null; this.eventHandler = null; this._selections = null; this._measureHeaderDecorations = null; this._selectedMeasureNodes = null; this._isSummaryHighlighted = null; this._cellWidthStatus = null; this._canvas = null; this.removeGridView(); this.$el = null; }; CrosstabGrid.prototype._setSummaryColor = function _setSummaryColor(gridCellProps) { var summaryColor = this.conditionalFormatting && this.conditionalFormatting.getSummaryFillColor(); if (summaryColor) { _.extend(gridCellProps.style, { 'background-color': summaryColor }); } }; CrosstabGrid.prototype._getConditionalFormatting = function _getConditionalFormatting(condValue, dataValue, measureIndex) { var style = void 0; if (this.conditionalFormatting) { var measure = measureIndex >= 0 && this._pivotTable._measuresInfo.length > measureIndex ? this._pivotTable._measuresInfo[measureIndex] : undefined; if (measure) { var dataItem = this.content.getFeature('Visualization').getSlots().getDataItem(measure.id); style = this.conditionalFormatting.getFormatting(dataValue.rawValue, condValue.value, dataItem.getColumnId()); } } else { var conditionalPalette = this.visModel.getConditions() ? this.visModel.getConditions().palette : null; if (conditionalPalette) { var paletteStyle = conditionalPalette.getColorByValue(condValue.value); if (paletteStyle) { style = paletteStyle.getStyle(); } } } return style; }; CrosstabGrid.prototype._getDataCellValue = function _getDataCellValue(dataCellValue, valueType) { if (valueType === 'tuple') { dataCellValue = dataCellValue && dataCellValue.tuple; } else if (valueType === 'useValue') { dataCellValue = dataCellValue && dataCellValue.isMeasure ? this._getValue(dataCellValue) : this._getUseValue(dataCellValue); } else if (valueType === 'condValue') { dataCellValue = dataCellValue && dataCellValue.condValue; } else if (valueType === 'type') { dataCellValue = dataCellValue && dataCellValue.type; } else if (valueType === 'isMeasure') { dataCellValue = dataCellValue && dataCellValue.isMeasure; } else if (valueType === 'nestlevel') { dataCellValue = dataCellValue && dataCellValue.nestlevel; } else if (valueType === 'rowEdge') { dataCellValue = dataCellValue && dataCellValue.rowEdge; } else if (valueType === 'columnEdge') { dataCellValue = dataCellValue && dataCellValue.columnEdge; } else if (valueType === 'ancestor_or_self') { dataCellValue = dataCellValue && dataCellValue.ancestor_or_self; } else if (valueType === 'levelNumber') { dataCellValue = dataCellValue && dataCellValue.value && dataCellValue.value.ln; } else if (valueType === 'parentUseValue') { dataCellValue = dataCellValue && dataCellValue.value && dataCellValue.value.pu; } else { var value = this._getValue(dataCellValue); // Should preserve null and 0 values, except undefined. Should allow user format the 3 types of // cells respectively. dataCellValue = value === undefined ? '' : value; } return dataCellValue; }; /** * Removes cell-is-focused classname if there's no selections * * @param aClassString * @return {*} * @private */ CrosstabGrid.prototype._removeFocusedClassName = function _removeFocusedClassName(aClassString) { var SELECTED = 'cell-is-focused'; if (!(this._selections && (this._selections.datapointSelection || this._selections.rowSelection || this._selections.colSelection))) { if (aClassString && aClassString.indexOf(SELECTED) !== -1) { return aClassString.replace(SELECTED, '').trim(); } } return aClassString; }; CrosstabGrid.prototype.restoreFormat = function restoreFormat() { this.fixedRowHeight = null; this.fixedColumnWidth = null; this.columnWidths = null; this.rowHeights = null; }; CrosstabGrid.prototype.setFormat = function setFormat(format) { this.fixedRowHeight = format.fixedRowHeight; this.fixedColumnWidth = format.fixedColumnWidth; this.columnWidths = format.columnWidths; this.rowHeights = format.rowHeights; }; CrosstabGrid.prototype.setHiddenRowsAndColumns = function setHiddenRowsAndColumns(hiddenRowsAndColumns) { this.hiddenRowsAndColumns = hiddenRowsAndColumns; }; /** * Apply highlight decoration to the selected measure header cell * @param $node: the node has been selected */ CrosstabGrid.prototype.setMeasureHeaderDecorations = function setMeasureHeaderDecorations(node) { var decorations = $(node).attr('usevalue'); this._measureHeaderDecorations = this._measureHeaderDecorations || []; this._selectedMeasureNodes = this._selectedMeasureNodes || []; if (this._measureHeaderDecorations.indexOf(decorations) > -1 || $(node).hasClass('dashboard-grid-cell-selected')) { this.clearMeasureHeaderDecorations(); } else { this._measureHeaderDecorations.push(decorations); this._selectedMeasureNodes.push(node); } }; /** * Get selected measure header cell nodes list */ CrosstabGrid.prototype.getSelectedMeasureNodes = function getSelectedMeasureNodes() { return this._selectedMeasureNodes; }; /** * Clear selected measure header cell decoration. */ CrosstabGrid.prototype.clearMeasureHeaderDecorations = function clearMeasureHeaderDecorations() { this._measureHeaderDecorations = null; this._selectedMeasureNodes = null; }; CrosstabGrid.prototype.highlightSummary = function highlightSummary(node) { this._isSummaryHighlighted = !$(node).hasClass('dashboard-grid-cell-selected'); }; CrosstabGrid.prototype.resetSummaryHighlight = function resetSummaryHighlight() { this._isSummaryHighlighted = false; }; CrosstabGrid.prototype.isSummaryHighlighted = function isSummaryHighlighted() { return this._isSummaryHighlighted; }; /** * Build resize key for the resize map from ancestor_or_self info */ CrosstabGrid.prototype._buildResizeKey = function _buildResizeKey(ancestor_or_self) { var resizeKey = ''; _.each(ancestor_or_self, function (dataItem) { if (dataItem.value) { resizeKey += dataItem.value + ','; } else { resizeKey += dataItem + ','; } }); return resizeKey.slice(0, -1); }; /** * calculate colspan, rowspan, columnWidth and rowHeight of current data cell * * @param {integer} colIndex, column index of current cell * @param {integer} rowIndex, row index of current cell * @param {integer} colBound, numbers of columns * @param {integer} rowBound, numbers of rows * @param {object} dataProvider * @param {integer} fixedRows, numbers of fixed rows * @param {integer} fixedColumns, numbers of fixed columns * @param {any} dataCellValue * @param {object} gridCellProps * @param {integer} defaultColumnWidth, fixedColumnWidth value * @param {integer} defaultRowHeight, fixedRowHeight value * @return {object} colSpan, rowSpan, gridCellColumnWidth, gridCellRowHeight */ CrosstabGrid.prototype._getSpanIndex = function _getSpanIndex(options) { var colIndex = options.colIndex, rowIndex = options.rowIndex, colBound = options.colBound, rowBound = options.rowBound, dataProvider = options.dataProvider, fixedRows = options.fixedRows, fixedColumns = options.fixedColumns, dataCellValue = options.dataCellValue, gridCellProps = options.gridCellProps, defaultColumnWidth = options.defaultColumnWidth, defaultRowHeight = options.defaultRowHeight, ignoreGrouping = options.ignoreGrouping; var colSpanIndex = colIndex + 1; var gridCellColumnWidth = parseInt(gridCellProps.style.width, 10); var siblingCellColumnWidth = void 0, siblingCellRowHeight = void 0; if (!ignoreGrouping.column) { while (colSpanIndex <= colBound && this._getDataCellValue(dataProvider.getValue(rowIndex, colSpanIndex)) === dataCellValue && this._getDataCellValue(dataProvider.getValue(0, colSpanIndex)) === this._getDataCellValue(dataProvider.getValue(0, colIndex))) { siblingCellColumnWidth = this._getColumnWidth(dataProvider, fixedRows - 1, colSpanIndex, defaultColumnWidth); gridCellColumnWidth = gridCellColumnWidth + siblingCellColumnWidth; colSpanIndex++; } } var colSpan = colSpanIndex - colIndex - 1; var rowSpanIndex = rowIndex + 1; var gridCellRowHeight = parseInt(gridCellProps.style.height, 10); if (!ignoreGrouping.row) { while (rowSpanIndex <= rowBound && this._getDataCellValue(dataProvider.getValue(rowSpanIndex, colIndex)) === dataCellValue && this._getDataCellValue(dataProvider.getValue(rowSpanIndex, 0)) === this._getDataCellValue(dataProvider.getValue(rowIndex, 0))) { siblingCellRowHeight = this._getRowHeight(dataProvider, rowSpanIndex, fixedColumns - 1, defaultRowHeight); gridCellRowHeight = gridCellRowHeight + siblingCellRowHeight; rowSpanIndex++; } } var rowSpan = rowSpanIndex - rowIndex - 1; return { colSpan: colSpan, rowSpan: rowSpan, gridCellColumnWidth: gridCellColumnWidth, gridCellRowHeight: gridCellRowHeight }; }; /** * calculate delta value bounded to minimal values * * @param {integer} delta * @param {integer} bound, MIN_COLUMN_WIDTH or MIN_ROW_HEIGHT * @param {integer} spanIndex * @param {integer} currentValue, gridCellColumnWidth/gridCellRowHeight value */ CrosstabGrid.prototype._calculateDelta = function _calculateDelta(delta, bound, spanIndex, currentValue) { if (delta + currentValue < bound) { delta = bound - currentValue; } else if (spanIndex > 0) { var evenDelta = parseInt((delta + currentValue) / (spanIndex + 1)); if (evenDelta < bound) { delta = delta + (bound - evenDelta) * (spanIndex + 1); } } return delta; }; /** * resize the grid with draggable handler * * @param {object} dataProvider * @param {string} direction, 'x' for columnWidth and 'y' for rowHeight * @param {integer} delta * @param {integer} colIndex * @param {integer} rowIndex * @param {integer} colSpan * @param {integer} rowSpan * @param {integer} fixedRows, numbers of fixed rows * @param {integer} fixedColumns, numbers of fixed columns * @param {integer} defaultValue, fixedColumnWidth/fixedRowHeight value * @param {integer} currentValue, gridCellColumnWidth/gridCellRowHeight value * @param {boolean} skipBound, skip the bound check and grow the cell if skipBound is set to true */ CrosstabGrid.prototype._onDraggableResize = function _onDraggableResize(options) { if (options.delta !== undefined && options.delta === 0) { return; } var dataProvider = options.dataProvider, direction = options.direction, delta = options.delta, rowIndex = options.rowIndex, colIndex = options.colIndex, colSpan = options.colSpan, rowSpan = options.rowSpan, fixedColumns = options.fixedColumns, fixedRows = options.fixedRows, defaultValue = options.defaultValue, currentValue = options.currentValue, skipBound = options.skipBound; var index = void 0, spanIndex = void 0, boundIndex = void 0, bound = void 0, formatMap = void 0, propertyName = void 0, rootCellValue = void 0, rootResizeKey = void 0, siblingCellValue = void 0, siblingResizeKey = void 0; var dataValue = dataProvider.getValue(rowIndex, colIndex); if (direction === AXIS_X) { formatMap = this.columnWidths || {}; propertyName = 'columnWidths'; index = colIndex; boundIndex = rowIndex; spanIndex = colSpan; bound = MIN_COLUMN_WIDTH; rootCellValue = dataProvider.getValue(fixedRows - 1, index); if (this._getDataCellValue(rootCellValue, 'type') === 'corner') { // when the cell is a corner cell, use the dataItem label as resize key rootResizeKey = this._getCachedDataItemInfoByIndex(this._cachedRowDataItemInfo, index, 'dataitemId'); } else { rootResizeKey = this._buildResizeKey(this._getDataCellValue(rootCellValue, 'ancestor_or_self')); } siblingCellValue = dataProvider.getNumColumns() - 1 > index + 1 && dataProvider.getValue(fixedRows - 1, index + 1); if (siblingCellValue && this._getDataCellValue(siblingCellValue, 'type') === 'corner') { siblingResizeKey = this._getCachedDataItemInfoByIndex(this._cachedRowDataItemInfo, index + 1, 'dataitemId'); } else { siblingResizeKey = this._buildResizeKey(this._getDataCellValue(siblingCellValue, 'ancestor_or_self')); } } else { formatMap = this.rowHeights || {}; propertyName = 'rowHeights'; index = rowIndex; boundIndex = colIndex; spanIndex = rowSpan; bound = MIN_ROW_HEIGHT; rootCellValue = dataProvider.getValue(index, fixedColumns - 1); if (this._getDataCellValue(rootCellValue, 'type') === 'corner') { // measure row is a special row since it does not have any dataItem mapped, use a constant as resize key rootResizeKey = this._getCachedDataItemInfoByIndex(this._cachedColumnDataItemInfo, index, 'dataitemId') || MEASURE_ROW_RESIZE_IDENTIFIER; } else { rootResizeKey = this._buildResizeKey(this._getDataCellValue(rootCellValue, 'ancestor_or_self')); } siblingCellValue = dataProvider.getNumRows() - 1 > index + 1 && dataProvider.getValue(index + 1, fixedColumns - 1); if (siblingCellValue && this._getDataCellValue(siblingResizeKey, 'type') === 'corner') { siblingResizeKey = this._getCachedDataItemInfoByIndex(this._cachedColumnDataItemInfo, index + 1, 'dataitemId') || MEASURE_ROW_RESIZE_IDENTIFIER; } else { siblingResizeKey = this._buildResizeKey(this._getDataCellValue(siblingResizeKey, 'ancestor_or_self')); } } var resizedValue = delta + currentValue; var resizeKey = this._buildResizeKey(this._getDataCellValue(dataValue, 'ancestor_or_self')); formatMap[resizeKey] = resizedValue; formatMap[rootResizeKey] = resizedValue; // child resize will resize the sibling and the children if (!skipBound && boundIndex > 0 && spanIndex <= 0 && siblingResizeKey) { formatMap[siblingResizeKey] = formatMap[siblingResizeKey] || defaultValue; formatMap[siblingResizeKey] = Math.max(formatMap[siblingResizeKey] - delta, bound); } // root resize will resize the parent and the children if (spanIndex > 0) { var evenDistribution = parseInt(resizedValue / (spanIndex + 1)); var counter = spanIndex + 1; while (counter > 0) { if (direction === AXIS_X) { rootResizeKey = this._buildResizeKey(this._getDataCellValue(dataProvider.getValue(fixedRows - 1, index + counter - 1), 'ancestor_or_self')); } else { rootResizeKey = this._buildResizeKey(this._getDataCellValue(dataProvider.getValue(index + counter - 1, fixedColumns - 1), 'ancestor_or_self')); } if (rootResizeKey) { formatMap[rootResizeKey] = evenDistribution; } counter--; } } this.crosstabView.setPropertyValue(propertyName, formatMap); }; /** * setup resize guideline and cell blocker for draggable resize handler */ CrosstabGrid.prototype._onStartResizeGuideLine = function _onStartResizeGuideLine(event, direction, containerClassName, offSetParent) { var style = {}; var guideLineClassName = void 0; if (direction === AXIS_X) { guideLineClassName = 'grid-column-resizer-guideLine'; style.height = this.$el[0].clientHeight; } else { guideLineClassName = 'grid-row-resizer-guideLine'; style.width = this.$el[0].clientWidth; } // add cell blocker to make sure hover does not leak through the drag handler var cells = $(this.$el[0]).find('.' + containerClassName); _.each(cells, function (cell) { $(cell).addClass(containerClassName + '-resizing'); }); // initialize the resize guideline styles var resizeGuideLine = $(this.$el[0]).find('.xtab-grid-guideLine'); var offset = $(this.$el[0]).find('.' + offSetParent).offsetParent().offsetParent().offset(); $(resizeGuideLine).addClass(guideLineClassName); style.top = event.clientY - offset.top - 1 + 'px'; style.left = event.clientX - offset.left - 1 + 'px'; $(resizeGuideLine).css(style); }; /** * move resize guideline along with draggable resize handler */ CrosstabGrid.prototype._onDragResizeGuideLine = function _onDragResizeGuideLine(event, direction, offSetParent) { var isResizingColumn = direction === AXIS_X; var guideLineClassName = isResizingColumn ? 'grid-column-resizer-guideLine' : 'grid-row-resizer-guideLine'; // update guideLine position while dragging happens var resizeGuideLine = $(this.$el[0]).find('.' + guideLineClassName); var offset = $(this.$el[0]).find('.' + offSetParent).offsetParent().offsetParent().offset(); if (isResizingColumn) { $(resizeGuideLine).css({ left: event.clientX - offset.left - 1 + 'px' }); } else { $(resizeGuideLine).css({ top: event.clientY - offset.top - 1 + 'px' }); } }; /** * remove resize guideline and cell blocker for draggable resize handler */ CrosstabGrid.prototype._onStopResizeGuideLine = function _onStopResizeGuideLine(event, direction, containerClassName) { var isResizingColumn = direction === AXIS_X; var guideLineClassName = isResizingColumn ? 'grid-column-resizer-guideLine' : 'grid-row-resizer-guideLine'; var style = isResizingColumn ? { height: '', top: '', left: '' } : { width: '', top: '', left: '' }; // remove the cell blocker var cells = $(this.$el[0]).find('.' + containerClassName); _.each(cells, function (cell) { $(cell).removeClass(containerClassName + '-resizing'); }); // reset the guideLine styles var resizeGuideLine = $(this.$el[0]).find('.' + guideLineClassName); $(resizeGuideLine).css(style); $(resizeGuideLine).removeClass(guideLineClassName); }; /** * render the draggable resize handler * @param {object} options */ CrosstabGrid.prototype._renderResizeHandler = function _renderResizeHandler(options) { var _this = this; var dataProvider = options.dataProvider, direction = options.direction, className = options.className, defaultValue = options.defaultValue, currentValue = options.currentValue, containerClassName = options.containerClassName, offSetParent = options.offSetParent, rowIndex = options.rowIndex, colIndex = options.colIndex, colSpan = options.colSpan, rowSpan = options.rowSpan, fixedColumns = options.fixedColumns, fixedRows = options.fixedRows, bound = options.bound, skipBound = options.skipBound; var spanIndex = direction === AXIS_X ? colSpan : rowSpan; var resizeHandler = React.createElement('div', { className: className, onDoubleClick: function onDoubleClick() { // double click to adjust the size fit the text var textWidth = direction === AXIS_X ? _this._cellWidthStatus && _this._cellWidthStatus[colIndex] && _this._cellWidthStatus[colIndex]['textWidth'] || defaultValue : defaultValue; var isShapeCol = _this._shapeCols.indexOf(colIndex) !== -1; if (isShapeCol) { textWidth += SHAPE_WIDTH; } var delta = textWidth - currentValue; if (spanIndex > 0) { delta = textWidth * spanIndex - currentValue; } if (delta > 0) { var draggableOptions = { dataProvider: dataProvider, direction: direction, delta: delta, rowIndex: rowIndex, colIndex: colIndex, colSpan: colSpan, rowSpan: rowSpan, fixedColumns: fixedColumns, fixedRows: fixedRows, defaultValue: defaultValue, currentValue: currentValue, skipBound: skipBound }; _this._onDraggableResize(draggableOptions); } } }, ''); return React.createElement(Draggable, { axis: direction, position: { x: 0, y: 0 }, onStart: function onStart(event) { _this._onStartResizeGuideLine(event, direction, containerClassName, offSetParent); }, onDrag: function onDrag(event) { _this._onDragResizeGuideLine(event, direction, offSetParent); }, onStop: function onStop(event, data) { _this._onStopResizeGuideLine(event, direction, containerClassName); var rawDeltaData = direction === AXIS_X ? data.x : data.y; var delta = _this._calculateDelta(rawDeltaData, bound, spanIndex, currentValue); var draggableOptions = { dataProvider: dataProvider, direction: direction, delta: delta, rowIndex: rowIndex, colIndex: colIndex, colSpan: colSpan, rowSpan: rowSpan, fixedColumns: fixedColumns, fixedRows: fixedRows, defaultValue: defaultValue, currentValue: currentValue, skipBound: skipBound }; _this._onDraggableResize(draggableOptions); } }, resizeHandler); }; /** * render the hidden rows or columns handler * @param {string} useValue * @param {string} position */ CrosstabGrid.prototype._renderHiddenRowsAndColumnsHandler = function _renderHiddenRowsAndColumnsHandler(useValue) { var _this2 = this; var position = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'bottom'; return React.createElement('div', { class: 'grid-hidden-rowsAndColumns ' + position, onDoubleClick: function onDoubleClick() { _this2.crosstabView.setPropertyValue(PROP_ID_HIDDEN_ROWS_AND_COLS, _this2.hiddenRowsAndColumns.filter(function (hiddenRowOrColumn) { return hiddenRowOrColumn !== useValue; })); } }, ''); }; /** * render the expand button * @param {object} expandOptions */ CrosstabGrid.prototype._renderExpandButton = function _renderExpandButton(expandOptions) { var _this3 = this; var dataItemInfo = expandOptions.dataItemInfo, parentUseValue = expandOptions.parentUseValue, currentUseValue = expandOptions.currentUseValue; return React.createElement(Toolkit.Button, { icon: 'visualizations-expand_16', iconSize: 'small', variant: 'icon', intent: 'primary', title: StringResources.get('expandBtnLabel'), onClick: function onClick(event) { _this3.expandCollapseFeature.expand(dataItemInfo.dataitemUniqueId, parentUseValue, currentUseValue); event.stopPropagation(); } }); }; /** * render the collapse button * @param {object} expandOptions */ CrosstabGrid.prototype._renderCollapseButton = function _renderCollapseButton(expandOptions) { var _this4 = this; var dataItemInfo = expandOptions.dataItemInfo, parentUseValue = expandOptions.parentUseValue, currentUseValue = expandOptions.currentUseValue, hasChildren = expandOptions.hasChildren; return React.createElement(Toolkit.Button, { icon: 'visualizations-collapse_16', iconSize: 'small', variant: 'icon', intent: 'primary', title: StringResources.get('collapseBtnLabel'), onClick: function onClick(event) { _this4.expandCollapseFeature.collapse(dataItemInfo.dataitemUniqueId, parentUseValue, currentUseValue); event.stopPropagation(); }, style: hasChildren ? {} : { visibility: 'hidden' } }); }; /** * render the text cell * @param {string} displayValue * @param {object} expandOptions */ CrosstabGrid.prototype._renderTextCell = function _renderTextCell(displayValue, expandOptions) { var textCellChildren = []; var style = {}; if (expandOptions.levelNumber !== undefined) { var expandCollapseHandler = expandOptions.isExpanded ? this._renderCollapseButton(expandOptions) : this._renderExpandButton(expandOptions); textCellChildren.push(expandCollapseHandler); var marginStyle = expandOptions.position === 'top' ? 'margin-top' : 'margin-left'; style[marginStyle] = (expandOptions.levelNumber - expandOptions.rootLevel) * EXPAND_INDENTATION; } textCellChildren.push(displayValue); return React.createElement('div', { class: 'dashboard-text-cell', style: style }, textCellChildren); }; CrosstabGrid.prototype._renderGridCellContent = function _renderGridCellContent(colIndex, style, fixedColumns, dataCellValue) { var shapeCol = colIndex + fixedColumns; var isShapeCol = this._shapeCols.indexOf(shapeCol) !== -1; if (!isShapeCol && style.shapeId) { isShapeCol = !!this._shapeCols.push(shapeCol); } var contentSpec = { displayValue: this._wrapDataCellValue(colIndex + fixedColumns, dataCellValue, style, true, isShapeCol) }; if (isShapeCol) { contentSpec.shapeId = style.shapeId; } return React.createElement(GridContentRenderer, contentSpec); }; /** * decorate edge cell with selection or implied selection style * @param {string} valueType, 'row' or 'column' * @param {object} dataValue, rawDataValue * @param {string} useValue * @param {array} classList, an array of class names */ CrosstabGrid.prototype._renderEdgeSelection = function _renderEdgeSelection(valueType, dataValue, useValue, classList) { var sSlotID = this._getSlotIDByEdgeType(valueType); var ancestor_or_self = this._getDataCellValue(dataValue, 'ancestor_or_self'); var edgeSelections = sSlotID === ROW_SLOT_ID ? this._selections.rowSelection : this._selections.colSelection; if (edgeSelections && edgeSelections.isSelected(ancestor_or_self)) { classList.push('dashboard-grid-cell-selected'); } else { var selectedDataPoints = _.chain(_.pluck(this.crosstabView.getSelector().getSelections(), 'categories')).flatten().map(function (category) { return category.value; }).value(); if (selectedDataPoints.indexOf(useValue) !== -1) { classList.push('dashboard-grid-cell-selected'); } } }; /** * decorate data cell with selection style * @param {object} dataValue, rawDataValue * @param {array} classList, an array of class names */ CrosstabGrid.prototype._renderDatapointSelection = function _renderDatapointSelection(dataValue, classList) { var columnEdge = this._getDataCellValue(dataValue, 'columnEdge'); var rowEdge = this._getDataCellValue(dataValue, 'rowEdge'); if (columnEdge && rowEdge && _.isObject(rowEdge.value) && (columnEdge.isMeasure || _.isObject(columnEdge.value))) { var selections = this._selections.datapointSelection; if (selections) { var aColumnEdgeContext = !columnEdge.isMeasure ? this._getCurrentEdgeSelectionContext(columnEdge) : []; var aRowEdgeContext = this._getCurrentEdgeSelectionContext(rowEdge); var selected = selections.isSelected(aColumnEdgeContext.concat(aRowEdgeContext)); if (selected) { classList.push('dashboard-grid-cell-selected'); } } } }; CrosstabGrid.prototype._getSelectionFormattingStyles = function _getSelectionFormattingStyles() { var _this5 = this; var useValue = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; var selectedAreaStyles = this.textStyle[this.textStyleIndex.selectedArea]; var convertedStylesValue = {}; var weight = ''; _.each(selectedAreaStyles, function (val, key) { var formatKey = useValue; var propValue = val && val[formatKey]; while (formatKey && formatKey.lastIndexOf(',') > 0) { formatKey = formatKey.slice(0, formatKey.lastIndexOf(',')); var nextFormatValue = val && val[formatKey]; if (propValue && nextFormatValue && propValue.weight < nextFormatValue.weight || !propValue && nextFormatValue) { propValue = val[formatKey]; } } //color prop need to convert the color into hexValue if (propValue && key === 'color') { convertedStylesValue[key] = propValue.value && _this5.colorsService.getHexColorFromDashboardColorSet(propValue.value) || ''; } else { convertedStylesValue[key] = propValue && propValue.value; } // keep the latest weight as reference var currentWeight = propValue && propValue.weight; if (currentWeight && currentWeight > weight) { weight = currentWeight; } }); if (_.values(convertedStylesValue).join('') !== '') { return { convertedStylesValue: convertedStylesValue, weight: weight }; } }; CrosstabGrid.prototype._getSelectionFormattingStylesForTuple = function _getSelectionFormattingStylesForTuple(dataValue, tuple) { var _getEdgeUseValues2 = this._getEdgeUseValues(dataValue, tuple), columnEdgeUseValue = _getEdgeUseValues2.columnEdgeUseValue, rowEdgeUseValue = _getEdgeUseValues2.rowEdgeUseValue; var convertedStylesValueForColumnEdge = this._getSelectionFormattingStyles(columnEdgeUseValue); var convertedStylesValueForRowEdge = this._getSelectionFormattingStyles(rowEdgeUseValue); var convertedStyles = convertedStylesValueForColumnEdge || convertedStylesValueForRowEdge; if (convertedStylesValueForColumnEdge && convertedStylesValueForRowEdge) { convertedStyles = convertedStylesValueForColumnEdge.weight > convertedStylesValueForRowEdge.weight ? convertedStylesValueForColumnEdge : convertedStylesValueForRowEdge; } return convertedStyles; }; /** * construct the edges useValues for dataPoint * @param {object} dataValue * @param {string} tuple value */ CrosstabGrid.prototype._getEdgeUseValues = function _getEdgeUseValues(dataValue, tuple) { var columnEdgeDecendant = dataValue.columnEdge && dataValue.columnEdge.descendant_or_self_without_measures; var columnEdgeCount = columnEdgeDecendant && columnEdgeDecendant.length || 0; var tupleUseValueList = tuple && _.isString(tuple) ? tuple.split(',') : null; var columnEdgeUseValue = tupleUseValueList && tupleUseValueList.slice(0, columnEdgeCount).join(','); var rowEdgeUseValue = tupleUseValueList && tupleUseValueList.slice(columnEdgeCount, tupleUseValueList.length).join(','); return { columnEdgeUseValue: columnEdgeUseValue, rowEdgeUseValue: rowEdgeUseValue }; }; /** * determine if a measure cell should be hidden * measure does not have any useValue mapping, need to use the useValue of the parent row * @param {object} dataProvider * @param {integer} rowIndex * @param {integer} columnIndex */ CrosstabGrid.prototype._isMeasureHidden = function _isMeasureHidden(dataProvider, rowIndex, columnIndex) { if (rowIndex < 1) { return false; } var dataValue = dataProvider.getValue(rowIndex - 1, columnIndex); var useValue = this._getDataCellValue(dataValue, 'useValue'); return this._isRowOrColumnHidden(useValue); }; /** * determine if a row or column should be hidden * @param {string} useValue */ CrosstabGrid.prototype._isRowOrColumnHidden = function _isRowOrColumnHidden() { var useValue = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; if (this.hiddenRowsAndColumns.length < 1) { return false; } var isHidden = this.hiddenRowsAndColumns.indexOf(useValue) !== -1; while (useValue && useValue.lastIndexOf(',') > 0 && !isHidden) { useValue = useValue.slice(0, useValue.lastIndexOf(',')); isHidden = this.hiddenRowsAndColumns.indexOf(useValue) !== -1; } return isHidden; }; CrosstabGrid.prototype._getCanvasFont = function _getCanvasFont(style) { // take default style into consideration var font = { 'font-style': style['font-style'], 'font-weight': style['font-weight'], 'font-size': style['font-size'] || DEFAULT_TEXT_STYLE.FONT_SIZE, 'font-family': style['font-family'] || DEFAULT_TEXT_STYLE.FONT_FAMILY }; return _.values(font).join(' '); }; CrosstabGrid.prototype._getTextWidth = function _getTextWidth(text, font) { this._canvas = this._canvas || document.createElement('canvas'); var context = this._canvas.getContext('2d'); context.font = font; return parseInt(context.measureText(text).width); }; CrosstabGrid.prototype._generateWrappedText = function _generateWrappedText(colIndex, font, width) { // cached the character counter that can fit a column, so we do not need to repeatly calculate for every cell in the same column var cachedCellWidthStatus = this._cellWidthStatus && this._cellWidthStatus[colIndex]; var cachedCharCount = cachedCellWidthStatus && cachedCellWidthStatus['charCount']; var cachedCellWidth = cachedCellWidthStatus && cachedCellWidthStatus['cellWidth']; var wrappedText = '#'; if (cachedCharCount && width === cachedCellWidth) { return wrappedText.repeat(cachedCharCount); } else { var singleCharWidth = this._getTextWidth(wrappedText, font); // take padding into consideration var charCount = parseInt((width - DEFAULT_TEXT_STYLE.PADDING_WIDTH) / singleCharWidth); // when the cell width is super small, wrap at least one char charCount = charCount <= 0 ? 1 : charCount; this._cellWidthStatus = this._cellWidthStatus || {}; this._cellWidthStatus[colIndex] = this._cellWidthStatus[colIndex] || {}; this._cellWidthStatus[colIndex]['charCount'] = charCount; this._cellWidthStatus[colIndex]['cellWidth'] = width; return wrappedText.repeat(charCount); } }; CrosstabGrid.prototype._wrapDataCellValue = function _wrapDataCellValue(colIndex, dataCellValue, gridCellStyles, isTextWrapped, isShapeCol) { var font = this._getCanvasFont(gridCellStyles); // take padding into consideration var textWidth = this._getTextWidth(dataCellValue, font) + DEFAULT_TEXT_STYLE.PADDING_WIDTH; var cellWidth = parseInt(gridCellStyles.width); var cellContentWidth = textWidth; if (isShapeCol) { cellContentWidth += SHAPE_WIDTH; } if (cellContentWidth > cellWidth) { // cached the biggeset textWidth for resize to unwrap the text this._cellWidthStatus = this._cellWidthStatus || {}; this._cellWidthStatus[colIndex] = this._cellWidthStatus[colIndex] || {}; // we always keep track the biggest textWidth, so using colIndex as key is safe this._cellWidthStatus[colIndex]['textWidth'] = this._cellWidthStatus[colIndex]['textWidth'] < textWidth ? textWidth : this._cellWidthStatus[colIndex]['textWidth'] || textWidth; if (isTextWrapped) { // only wrapped text if the flag is on dataCellValue = this._generateWrappedText(colIndex, font, cellWidth); } } return dataCellValue; }; CrosstabGrid.prototype._getWhiteListStyles = function _getWhiteListStyles(styles, blackList) { return _.omit(styles, blackList); }; CrosstabGrid.prototype._isSuppressionOn = function _isSuppressionOn() { var suppressionValue = this.content && this.content.getPropertyValue(PROP_ID_SUPPRESSION); if (suppressionValue && suppressionValue === 'none') { return false; } return true; }; CrosstabGrid.prototype._isExpandable = function _isExpandable() { var isExpandFeatureOn = !this.dashboardApi.getGlassCoreSvc('.FeatureChecker').checkValue('dashboard', 'expandCollapse', 'disabled'); var supportsExpandCollapse = this.content && this.content.getPropertyValue(PROP_ID_EXPANDCOLLAPSE); return isExpandFeatureOn && supportsExpandCollapse; }; /** * get expand options for current dataCell * @param {object} dataValue * @param {object} siblingDataValue * @param {object} dataItemInfo * @param {string} position - top/left * @returns {Object} expandOptions */ CrosstabGrid.prototype._getExpandOptions = function _getExpandOptions(dataValue, siblingDataValue, dataItemInfo, levelInfo, position) { var useValues = this._getDataCellValue(dataValue, 'useValue').split(','); var siblingUseValues = siblingDataValue && this._getDataCellValue(siblingDataValue, 'useValue').split(','); // in nested scenario, the useValue of the cell will contain all the edge useValues, the last one will be the one we need var useValue = useValues[useValues.length - 1]; var siblingUseValue = siblingUseValues && siblingUseValues[siblingUseValues.length - 1]; return { dataItemInfo: dataItemInfo, parentUseValue: this._getDataCellValue(dataValue, 'parentUseValue'), currentUseValue: useValue, levelNumber: this._getDataCellValue(dataValue, 'levelNumber'), isExpanded: !!(dataItemInfo && dataItemInfo.expandMap && dataItemInfo.expandMap[useValue]), position: position, rootLevel: levelInfo && levelInfo.rootLevelnumber, hasChildren: !!(siblingDataValue && (useValue === this._getDataCellValue(siblingDataValue, 'parentUseValue') || useValue === siblingUseValue)) }; }; /** * get expandInfo from the dataItem * @param {object} dataItem * @param {object} expandMap * @param {integer} maxDepth * @returns {Object} maxDepth and expandMap */ CrosstabGrid.prototype._getExpandInfo = function _getExpandInfo(dataItem, expandMap, maxDepth) { var _this6 = this; var union = dataItem.getUnion(); var dataItemList = union.getDataItemList(); if (dataItemList.length > 0) { maxDepth++; dataItemList.forEach(function (newDataItem) { var nestedChildren = newDataItem.getDrillDownValue(); expandMap[nestedChildren] = true; var nestedUnion = newDataItem.getUnion(); var nestedDataItemList = nestedUnion.getDataItemList(); if (nestedDataItemList.length > 0) { var tmpMaxDepth = _this6._getExpandInfo(newDataItem, expandMap, maxDepth).maxDepth; if (tmpMaxDepth > maxDepth) { maxDepth = tmpMaxDepth; } } }); } return { maxDepth: maxDepth, expandMap: expandMap }; }; /** * get dataItemInfo by slotId * @param {string} slotId * @returns {Object} dataItemInfo */ CrosstabGrid.prototype._getDataItemInfoBySlotId = function _getDataItemInfoBySlotId(slotId) { var _this7 = this; var visualization = this.content && this.content.getFeature('Visualization'); var slots = visualization && visualization.getSlots(); var slot = slots.getSlot(slotId); var dataItemInfo = {}; if (slot) { _.each(slot.getDataItemList(), function (dataItem, index) { var expandInfo = _this7._getExpandInfo(dataItem, {}, 0); dataItemInfo[index] = { dataitemId: dataItem.getColumnId(), dataitemUniqueId: dataItem.getId(), expandMap: expandInfo.expandMap, maxDepth: expandInfo.maxDepth, isProperty: dataItem.getMetadataColumn().isProperty() }; }); } return dataItemInfo; }; /** * get cached dataItemInfo by index * @param {Object} cachedDataItemInfo * @param {integer} row/column index * @param {string} propertyName * @returns {Object} dataItemInfo */ CrosstabGrid.prototype._getCachedDataItemInfoByIndex = function _getCachedDataItemInfoByIndex(cachedDataItemInfoMap, index, propertyName) { var cachedDataItemInfo = cachedDataItemInfoMap && cachedDataItemInfoMap[index]; return propertyName ? cachedDataItemInfo && cachedDataItemInfo[propertyName] : cachedDataItemInfo; }; CrosstabGrid.prototype._getCellPropertyColors = function _getCellPropertyColors() { try { // if user customized a background color for current widget var fillColor = this.content && this.content.getPropertyValue('fillColor'); var cellFillColor = fillColor && this.colorsService.getHexColorFromDashboardColorSet(fillColor); // TODO: have our own theme mapping for new grid var foregroundColorProperties = this.colorsService.getForegroundColorPropertiesForUIElement(fillColor, 'tabs'); var cellTextColor = foregroundColorProperties && foregroundColorProperties.length && foregroundColorProperties[0].value; return { cellFillColor: cellFillColor, cellTextColor: cellTextColor }; } catch (err) { return {}; } }; CrosstabGrid.prototype._getIndentationDepth = function _getIndentationDepth(dataItemInfo, type, index) { var maxDepth = this._getCachedDataItemInfoByIndex(dataItemInfo, index, 'maxDepth') || 0; var levelInfo = this._cachedLevelInfo[type][index]; var maxLevelDepth = levelInfo && levelInfo.maxLevelDepth || 0; return Math.max(maxDepth, maxLevelDepth); }; /** * calculate columnWidth for current column * hiddenColumnWidth > customizedColumnWidth > fixedColumnWidth(default) * hiddenColumnWidth is set as a small float number that is close to 0 to prevent the react removing the dom with 0 width * @param {object} dataProvider * @param {integer} rowIndex * @param {integer} columnIndex * @param {integer} fixedColumnWidth */ CrosstabGrid.prototype._getColumnWidth = function _getColumnWidth(dataProvider, rowIndex, colIndex, fixedColumnWidth) { // check from cached status first if (this._cachedHiddenCol[colIndex]) { return HIDDEN_COL_WIDTH; } var fixedRowCellValue = dataProvider.getValue(rowIndex, colIndex); var isMeasure = this._getDataCellValue(fixedRowCellValue, 'isMeasure'); if (this._isRowOrColumnHidden(this._getDataCellValue(fixedRowCellValue, 'useValue')) || isMeasure && this._isMeasureHidden(dataProvider, rowIndex, colIndex)) { this._cachedHiddenCol[colIndex] = true; return HIDDEN_COL_WIDTH; } // when the cell is a corner cell, use the dataItem label as resize key var rootResizeKey = this._getDataCellValue(fixedRowCellValue, 'type') === 'corner' ? this._getCachedDataItemInfoByIndex(this._cachedRowDataItemInfo, colIndex, 'dataitemId') : this._buildResizeKey(this._getDataCellValue(fixedRowCellValue, 'ancestor_or_self')); if (this.columnWidths && this.columnWidths[rootResizeKey]) { return this.columnWidths[rootResizeKey]; } var isShapeCol = this._shapeCols.indexOf(colIndex) !== -1; if (isShapeCol) { fixedColumnWidth += SHAPE_WIDTH; } // increase columnWidth for the expand indentations var indentationDepth = this._getIndentationDepth(this._cachedRowDataItemInfo, 'col', colIndex); if (this.isExpandable && indentationDepth > 0) { return parseInt(fixedColumnWidth, 10) + indentationDepth * EXPAND_INDENTATION; } return fixedColumnWidth; }; /** * calculate rowHeight for current row * hiddenRowHeight > customizedRowHeight > fixedRowheight(default) * hiddenRowHeight is set as a small float number that is close to 0 to prevent the react removing the dom with 0 height * @param {object} dataProvider * @param {integer} rowIndex * @param {integer} columnIndex * @param {integer} fixedRowHeight */ CrosstabGrid.prototype._getRowHeight = function _getRowHeight(dataProvider, rowIndex, colIndex, fixedRowHeight) { // check from cached status first if (this._cachedHiddenRow[colIndex]) { return HIDDEN_ROW_HEIGHT; } var fixedColumnCellValue = dataProvider.getValue(rowIndex, colIndex); if (this._isRowOrColumnHidden(this._getDataCellValue(fixedColumnCellValue, 'useValue'))) { this._cachedHiddenRow[rowIndex] = true; return HIDDEN_ROW_HEIGHT; } // when the cell is a corner cell, use the dataItem label as resize key // measure row is a special row since it does not have any dataItem mapped, use a constant as resize key var rootResizeKey = this._getDataCellValue(fixedColumnCellValue, 'type') === 'corner' ? this._getCachedDataItemInfoByIndex(this._cachedColumnDataItemInfo, rowIndex, 'dataitemId') || MEASURE_ROW_RESIZE_IDENTIFIER : this._buildResizeKey(this._getDataCellValue(fixedColumnCellValue, 'ancestor_or_self')); if (this.rowHeights && this.rowHeights[rootResizeKey]) { return this.rowHeights[rootResizeKey]; } // increase rowHeight for the expand indentations var indentationDepth = this._getIndentationDepth(this._cachedColumnDataItemInfo, 'row', rowIndex); if (this.isExpandable && indentationDepth > 0) { return parseInt(fixedRowHeight, 10) + indentationDepth * EXPAND_INDENTATION; } return fixedRowHeight; }; CrosstabGrid.prototype._renderReactGrid = function _renderReactGrid() { var _this8 = this; var _dataProvider = this.dataProvider; _dataProvider.updateData.bind(this.dataProvider); _dataProvider.getNumColumns.bind(this.dataProvider); _dataProvider.getNumRows.bind(this.dataProvider); _dataProvider.getValue.bind(this.dataProvider); // in story, the first-time rendering from dashboard, the offsetHeight of the node is 0, need to check this this.maxColHeight = this._getMaxColHeight(); var fixedColumns = this._pivotTable.getNestingLevels().rowNestingLevel; var fixedRows = this._pivotTable.getNestingLevels().colNestingLevel; _dataProvider.updateData(this.data); var numColumns = _dataProvider.getNumColumns() - fixedColumns; var numRows = _dataProvider.getNumRows() - fixedRows; var TABINDEX = 0; var fixedRowHeight = this.fixedRowHeight || DEFAULT_ROW_HEIGHT; var fixedColumnWidth = this.fixedColumnWidth || DEFAULT_COLUMN_WIDTH; if (numRows === 0) { fixedRows = numRows; } if (numColumns === 0) { fixedColumns = numColumns; } var _getCellPropertyColor = this._getCellPropertyColors(), cellFillColor = _getCellPropertyColor.cellFillColor, cellTextColor = _getCellPropertyColor.cellTextColor; var isSuppressed = this._isSuppressionOn(); this.isExpandable = this._isExpandable(); // load expandCollapseFeature if the grid is expandable if (this.isExpandable) { this.expandCollapseFeature = this.content && this.content.getFeature('ExpandCollapse'); } // cache the dataitemInfo this._cachedRowDataItemInfo = this._getDataItemInfoBySlotId(ROW_SLOT_ID); this._cachedColumnDataItemInfo = this._getDataItemInfoBySlotId(COLUMN_SLOT_ID); // cache the levelInfo this._cachedLevelInfo = this._pivotTable.getLevelInfo(); //reset cached hidden rows and columns info per render this._cachedHiddenRow = {}; this._cachedHiddenCol = {}; var dataCellRenderer = function dataCellRenderer(rowIndex, colIndex, gridCellProps) { var dataValue = _dataProvider.getValue(rowIndex + fixedRows, colIndex + fixedColumns); var _isSummary = _this8._isSummary(dataValue); var dataCellValue = _this8._getDataCellValue(dataValue); var measureInfo = _this8._pivotTable._measuresInfo; var measureIndex = measureInfo.length > 0 ? colIndex % measureInfo.length : null; var formatSpec = Number.isInteger(measureIndex) ? measureInfo[measureIndex].formatSpec : null; var content = _this8.crosstabView && _this8.crosstabView.content; if (content) { var visFormatSpec = content.getPropertyValue('format'); if (visFormatSpec) { formatSpec = _.extend({}, formatSpec, visFormatSpec); } } dataCellValue = Formatter.formatNull(dataCellValue, formatSpec); var tuple = _this8._getDataCellValue(dataValue, 'tuple'); var blackListStyles = ['word-break', 'white-space']; //populate the attributes we needed _.extend(gridCellProps, { tuple: tuple, measure: _this8._getDataCellValue(dataValue, 'isMeasure'), row: rowIndex + fixedRows, col: colIndex + fixedColumns, 'aria-label': dataCellValue, tabindex: TABINDEX, area: AREA_TYPE.CELL }); gridCellProps.className = _this8._removeFocusedClassName(gridCellProps.className); var classList = [gridCellProps.className]; classList.push('grid-data-cell', 'dashboard-grid-cell'); if (_this8._cachedHiddenRow[rowIndex + fixedRows] || _this8._cachedHiddenCol[colIndex + fixedColumns]) { // if any of the edge is hidden, render an empty div gridCellProps.className = classList.join(' '); return React.createElement('div', gridCellProps, ''); } // background color from Property if (cellFillColor && !_isSummary) { if ((rowIndex + fixedRows) % 2 === 0) { gridCellProps.style = _.extend(gridCellProps.style, { color: cellTextColor }); classList.push('light'); } else { gridCellProps.style = _.extend(gridCellProps.style, { backgroundColor: cellFillColor, color: cellTextColor }); } } //Text toolbar style applied var valueType = _this8._getDataCellValue(dataValue, 'type'); if (!valueType) { // ignore text wrapping styles var values = Object.assign({}, _this8.textStyle[_this8.textStyleIndex.cell]); Object.keys(values).forEach(function (key) { return values[key] === '' && delete values[key]; }); Object.assign(gridCellProps.style, _this8._getWhiteListStyles(values, blackListStyles)); } //Selection formatting for text toolbar var selectedAreaStyles = _this8._getSelectionFormattingStylesForTuple(dataValue, tuple); if (selectedAreaStyles) { // ignore text wrapping styles var _values = selectedAreaStyles.convertedStylesValue; Object.keys(_values).forEach(function (key) { return _values[key] === '' && delete _values[key]; }); Object.assign(gridCellProps.style, _this8._getWhiteListStyles(_values, blackListStyles)); } //Alternative row background if ((rowIndex + fixedRows) % 2 === 0) { classList.push('alternate'); } //Conditional Formatting var condValue = _this8._getDataCellValue(dataValue, 'condValue'); if (condValue) { var _style = _this8._getConditionalFormatting(condValue, dataValue, measureIndex); _.extend(gridCellProps.style, _style); } //render selection highlight _this8._renderDatapointSelection(dataValue, classList); var children = []; // styles overwritten for summary cell if (_isSummary) { classList.push('summary'); if (dataValue.rowEdge.isSummary) { children.push(React.createElement('div', { className: 'grid-summary-decorator' }, '')); } gridCellProps.area = AREA_TYPE.SUMMARY; // ignore text wrapping styles _.extend(gridCellProps.style, _this8._getWhiteListStyles(_this8.textStyle[_this8.textStyleIndex.summary], blackListStyles)); // summary text is always bold _.extend(gridCellProps.style, { 'font-weight': 'bold' }); if (_this8._isSummaryHighlighted) { classList.push('dashboard-grid-cell-selected'); } _this8._setSummaryColor(gridCellProps); } children.push(_this8._renderGridCellContent(colIndex, gridCellProps.style, fixedColumns, dataCellValue)); gridCellProps.className = classList.join(' '); return React.createElement('div', gridCellProps, children); }; var fixedRowCellRenderer = function fixedRowCellRenderer(rowIndex, colIndex, gridCellProps) { var dataValue = _dataProvider.getValue(rowIndex, colIndex + fixedColumns); var _isSummary = _this8._isSummary(dataValue); var useValue = _this8._getDataCellValue(dataValue, 'useValue'); var dataCellValue = _this8._getDataCellValue(dataValue); var isMeasure = _this8._getDataCellValue(dataValue, 'isMeasure'); //populate the attributes we needed _.extend(gridCellProps, { useValue: useValue, nestlevel: _this8._getDataCellValue(dataValue, 'nestlevel'), row: rowIndex, col: colIndex + fixedColumns, scope: 'col', 'aria-label': dataCellValue, tabindex: TABINDEX, area: AREA_TYPE.COLUMN }); var classList = gridCellProps.className ? [gridCellProps.className] : []; classList.push('grid-fixed-row-cell', 'dashboard-grid-cell'); if (_this8._cachedHiddenCol[colIndex + fixedColumns]) { // if column is hidden, render a hidden column handler on the left gridCellProps.className = classList.join(' '); gridCellProps.style.zIndex = numColumns - colIndex; delete gridCellProps.style.width; return React.createElement('div', gridCellProps, _this8._renderHiddenRowsAndColumnsHandler(useValue, 'left')); } //Text toolbar style applied var valueType = _this8._getDataCellValue(dataValue, 'type'); valueType = valueType && valueType === 'column' && isMeasure ? 'corner' : valueType; if (valueType) { var styleIndexForValueType = _this8.textStyleIndex[valueType]; _.extend(gridCellProps.style, _this8.textStyle[styleIndexForValueType]); // overwrite the area type if the column is actually a measure label if (valueType === 'corner') { _.extend(gridCellProps, { area: AREA_TYPE.MEASURE, measure: 'true' }); // highlight the measure header cell if multiselected for calculation if (_this8._measureHeaderDecorations && _this8._measureHeaderDecorations.indexOf(useValue) > -1) { classList.push('dashboard-grid-cell-selected'); } } } //Selection formatting for text toolbar var selectedAreaStyles = _this8._getSelectionFormattingStyles(useValue); if (selectedAreaStyles) { _.extend(gridCellProps.style, selectedAreaStyles.convertedStylesValue); } // colspan/rowspan var spanIndexOptions = { colIndex: colIndex + fixedColumns, rowIndex: rowIndex, colBound: numColumns + 1, rowBound: fixedRows, dataProvider: _dataProvider, fixedRows: fixedRows, fixedColumns: fixedColumns, dataCellValue: dataCellValue, gridCellProps: gridCellProps, defaultColumnWidth: fixedColumnWidth, defaultRowHeight: fixedRowHeight, ignoreGrouping: { row: !_isSummary } }; var _getSpanIndex2 = _this8._getSpanIndex(spanIndexOptions), colSpan = _getSpanIndex2.colSpan, rowSpan = _getSpanIndex2.rowSpan, gridCellColumnWidth = _getSpanIndex2.gridCellColumnWidth, gridCellRowHeight = _getSpanIndex2.gridCellRowHeight; _.extend(gridCellProps.style, { width: gridCellColumnWidth + 'px', zIndex: numColumns - colIndex + (colSpan > rowSpan ? colSpan : rowSpan) }); var columnInfo = _this8._pivotTable._columnInfo; var index = colIndex % columnInfo.length; var formatSpec = columnInfo[index] && columnInfo[index].formatSpec; var content = _this8.crosstabView && _this8.crosstabView.content; if (content) { var visFormatSpec = content.getPropertyValue('format'); if (visFormatSpec) { formatSpec = _.extend({}, formatSpec, visFormatSpec); } } if (_isSummary) { formatSpec = null; } var formattedDisplayValue = isSuppressed ? Formatter.format(dataCellValue, formatSpec) : Formatter.formatNull(dataCellValue); // check if cell is expandable var siblingDataValue = colIndex + fixedColumns < numColumns ? _dataProvider.getValue(rowIndex, colIndex + fixedColumns + 1) : null; // defect 298869: Disable expand/collapse on crosstab if property/attribute data item on edges var _cachedDataItemInfoByIndex = _this8._getCachedDataItemInfoByIndex(_this8._cachedColumnDataItemInfo, rowIndex); var isProperty = _cachedDataItemInfoByIndex && _cachedDataItemInfoByIndex.isProperty; var expandOptions = _this8.isExpandable && !isProperty ? _this8._getExpandOptions(dataValue, siblingDataValue, _cachedDataItemInfoByIndex, _this8._cachedLevelInfo.row[rowIndex], 'top') : {}; var children = [_this8._renderTextCell(formattedDisplayValue, expandOptions)]; // styles overwritten for summary cell if (_isSummary) { classList.push('summary'); children.push(React.createElement('div', { class: 'grid-summary-decorator' }, '')); gridCellProps.area = AREA_TYPE.SUMMARY; _.extend(gridCellProps.style, _this8.textStyle[_this8.textStyleIndex.summary]); // summary text is always bold _.extend(gridCellProps.style, { 'font-weight': 'bold' }); if (_this8._isSummaryHighlighted) { classList.push('dashboard-grid-cell-selected'); } _this8._setSummaryColor(gridCellProps); } else { gridCellProps.style.height = Math.min(gridCellRowHeight, _this8.maxColHeight) + 'px'; //render selection and implied Selection _this8._renderEdgeSelection(valueType, dataValue, useValue, classList); if (isMeasure) { children.push(React.createElement('div', { class: 'grid-drop-zone left' }, '')); children.push(React.createElement('div', { class: 'grid-drop-zone right' }, '')); } else { children.push(React.createElement('div', { class: 'grid-drop-zone top' }, '')); children.push(React.createElement('div', { class: 'grid-drop-zone bottom' }, '')); } children.push(React.createElement('div', { class: 'grid-drop-zone replace' }, '')); } gridCellProps.className = classList.join(' '); // common resize props var commonResizeHandlerOptions = { dataProvider: _dataProvider, containerClassName: 'grid-fixed-row-cell', offSetParent: 'ba-common-grid__top-right-grid', rowIndex: rowIndex, colIndex: colIndex + fixedColumns, colSpan: colSpan, rowSpan: rowSpan, fixedColumns: fixedColumns, fixedRows: fixedRows }; // column resize handlers children.push(_this8._renderResizeHandler(_.extend(commonResizeHandlerOptions, { direction: AXIS_X, className: 'grid-column-resizer', defaultValue: fixedColumnWidth, currentValue: gridCellColumnWidth, bound: MIN_COLUMN_WIDTH, skipBound: false }))); // row resize handlers children.push(_this8._renderResizeHandler(_.extend(commonResizeHandlerOptions, { direction: AXIS_Y, className: 'grid-row-resizer', defaultValue: fixedRowHeight, currentValue: gridCellRowHeight, bound: MIN_ROW_HEIGHT, skipBound: true }))); return React.createElement(GridDropTarget, _extends({ dndManager: _this8._gridDnDManager, cellType: 'row', isMeasure: isMeasure }, gridCellProps), children); }; var fixedColumnCellRenderer = function fixedColumnCellRenderer(rowIndex, colIndex, gridCellProps) { var dataValue = _dataProvider.getValue(rowIndex + fixedRows, colIndex); var _isSummary = _this8._isSummary(dataValue); var useValue = _this8._getDataCellValue(dataValue, 'useValue'); var dataCellValue = _this8._getDataCellValue(dataValue); //populate the attributes we needed _.extend(gridCellProps, { useValue: useValue, nestlevel: _this8._getDataCellValue(dataValue, 'nestlevel'), row: rowIndex + fixedRows, col: colIndex, scope: 'row', 'aria-label': dataCellValue, tabindex: TABINDEX, area: AREA_TYPE.ROW }); var classList = gridCellProps.className ? [gridCellProps.className] : []; classList.push('grid-fixed-column-cell', 'dashboard-grid-cell'); if (_this8._cachedHiddenRow[rowIndex + fixedRows]) { // if row is hidden, render a hidden row handler on the bottom gridCellProps.className = classList.join(' '); gridCellProps.style.zIndex = numRows - rowIndex; delete gridCellProps.style.height; return React.createElement('div', gridCellProps, _this8._renderHiddenRowsAndColumnsHandler(useValue, 'bottom')); } //Text toolbar style applied var valueType = _this8._getDataCellValue(dataValue, 'type'); if (valueType) { var styleIndexForValueType = _this8.textStyleIndex[valueType]; _.extend(gridCellProps.style, _this8.textStyle[styleIndexForValueType]); } //Selection formatting for text toolbar var selectedAreaStyles = _this8._getSelectionFormattingStyles(useValue); if (selectedAreaStyles) { _.extend(gridCellProps.style, selectedAreaStyles.convertedStylesValue); } // colspan/rowspan var spanIndexOptions = { colIndex: colIndex, rowIndex: rowIndex + fixedRows, colBound: fixedColumns, rowBound: numRows + fixedRows - 1, dataProvider: _dataProvider, fixedRows: fixedRows, fixedColumns: fixedColumns, dataCellValue: dataCellValue, gridCellProps: gridCellProps, defaultColumnWidth: fixedColumnWidth, defaultRowHeight: fixedRowHeight, ignoreGrouping: { column: !_isSummary } }; var _getSpanIndex3 = _this8._getSpanIndex(spanIndexOptions), colSpan = _getSpanIndex3.colSpan, rowSpan = _getSpanIndex3.rowSpan, gridCellColumnWidth = _getSpanIndex3.gridCellColumnWidth, gridCellRowHeight = _getSpanIndex3.gridCellRowHeight; _.extend(gridCellProps.style, { width: gridCellColumnWidth + 'px', zIndex: numRows - rowIndex + (colSpan > rowSpan ? colSpan : rowSpan) }); var rowInfo = _this8._pivotTable._rowInfo; var index = colIndex % rowInfo.length; var formatSpec = rowInfo[index] && rowInfo[index].formatSpec; var content = _this8.crosstabView && _this8.crosstabView.content; if (content) { var visFormatSpec = content.getPropertyValue('format'); if (visFormatSpec) { formatSpec = _.extend({}, formatSpec, visFormatSpec); } } if (_isSummary) { formatSpec = null; } var formattedDisplayValue = isSuppressed ? Formatter.format(dataCellValue, formatSpec) : Formatter.formatNull(dataCellValue); // check if cell is expandable var siblingDataValue = rowIndex < numRows - 1 ? _dataProvider.getValue(rowIndex + fixedRows + 1, colIndex) : null; // defect 298869: Disable expand/collapse on crosstab if property/attribute data item on edges var _cachedDataItemInfoByIndex = _this8._getCachedDataItemInfoByIndex(_this8._cachedRowDataItemInfo, colIndex); var isProperty = _cachedDataItemInfoByIndex && _cachedDataItemInfoByIndex.isProperty; var expandOptions = _this8.isExpandable && !isProperty ? _this8._getExpandOptions(dataValue, siblingDataValue, _cachedDataItemInfoByIndex, _this8._cachedLevelInfo.col[colIndex], 'left') : {}; var children = [_this8._renderTextCell(formattedDisplayValue, expandOptions)]; // styles overwritten for summary cell if (_isSummary) { classList.push('summary'); children.push(React.createElement('div', { class: 'grid-summary-decorator' }, '')); gridCellProps.area = AREA_TYPE.SUMMARY; _.extend(gridCellProps.style, _this8.textStyle[_this8.textStyleIndex.summary]); // summary text is always bold _.extend(gridCellProps.style, { 'font-weight': 'bold' }); if (_this8._isSummaryHighlighted) { classList.push('dashboard-grid-cell-selected'); } _this8._setSummaryColor(gridCellProps); } else { gridCellProps.style.height = Math.min(gridCellRowHeight, _this8.maxColHeight) + 'px'; //render selection and implied Selection _this8._renderEdgeSelection(valueType, dataValue, useValue, classList); children.push(React.createElement('div', { class: 'grid-drop-zone left' }, '')); children.push(React.createElement('div', { class: 'grid-drop-zone replace' }, '')); children.push(React.createElement('div', { class: 'grid-drop-zone right' }, '')); } gridCellProps.className = classList.join(' '); // generate the size map for double-click on fixedColumn cell to expand the wrapped value _this8._wrapDataCellValue(colIndex, dataCellValue, gridCellProps.style, false); // common resize props var commonResizeHandlerOptions = { dataProvider: _dataProvider, containerClassName: 'grid-fixed-column-cell', offSetParent: 'ba-common-grid__bottom-left-grid', rowIndex: rowIndex + fixedRows, colIndex: colIndex, colSpan: colSpan, rowSpan: rowSpan, fixedColumns: fixedColumns, fixedRows: fixedRows }; // column resize handlers children.push(_this8._renderResizeHandler(_.extend(commonResizeHandlerOptions, { direction: AXIS_X, className: 'grid-column-resizer', defaultValue: fixedColumnWidth, currentValue: gridCellColumnWidth, bound: MIN_COLUMN_WIDTH, skipBound: true }))); // row resize handlers children.push(_this8._renderResizeHandler(_.extend(commonResizeHandlerOptions, { direction: AXIS_Y, className: 'grid-row-resizer', defaultValue: fixedRowHeight, currentValue: gridCellRowHeight, bound: MIN_ROW_HEIGHT, skipBound: false }))); return React.createElement(GridDropTarget, _extends({ dndManager: _this8._gridDnDManager, cellType: 'column' }, gridCellProps), children); }; var fixedCornerCellRenderer = function fixedCornerCellRenderer(rowIndex, colIndex, gridCellProps) { var dataValue = _dataProvider.getValue(rowIndex, colIndex); var dataCellValue = _this8._getDataCellValue(dataValue); //populate the attributes we needed _.extend(gridCellProps, { row: rowIndex, col: colIndex, tabindex: TABINDEX, area: AREA_TYPE.MEASURE, measure: 'true', 'aria-label': dataCellValue }); var classList = gridCellProps.className ? [gridCellProps.className] : []; classList.push('grid-corner-cell', 'dashboard-grid-cell'); //Text toolbar style applied var valueType = _this8._getDataCellValue(dataValue, 'type'); if (valueType) { var styleIndexForValueType = _this8.textStyleIndex[valueType]; _.extend(gridCellProps.style, _this8.textStyle[styleIndexForValueType]); } // colspan/rowspan var spanIndexOptions = { colIndex: colIndex, rowIndex: rowIndex, colBound: fixedColumns, rowBound: fixedRows, dataProvider: _dataProvider, fixedRows: fixedRows, fixedColumns: fixedColumns, dataCellValue: dataCellValue, gridCellProps: gridCellProps, defaultColumnWidth: fixedColumnWidth, defaultRowHeight: fixedRowHeight, ignoreGrouping: {} }; var _getSpanIndex4 = _this8._getSpanIndex(spanIndexOptions), colSpan = _getSpanIndex4.colSpan, rowSpan = _getSpanIndex4.rowSpan, gridCellColumnWidth = _getSpanIndex4.gridCellColumnWidth, gridCellRowHeight = _getSpanIndex4.gridCellRowHeight; _.extend(gridCellProps.style, { width: gridCellColumnWidth + 'px', height: Math.min(gridCellRowHeight, _this8.maxColHeight) + 'px', zIndex: fixedColumns - colIndex + (fixedRows - rowIndex) + (colSpan > rowSpan ? colSpan : rowSpan) }); var children = [React.createElement('div', { class: 'dashboard-text-cell' }, dataCellValue)]; if (dataCellValue) { children.push(React.createElement('div', { class: 'grid-drop-zone left' }, '')); children.push(React.createElement('div', { class: 'grid-drop-zone replace' }, '')); children.push(React.createElement('div', { class: 'grid-drop-zone right' }, '')); } gridCellProps.className = classList.join(' '); return React.createElement(GridDropTarget, _extends({ dndManager: _this8._gridDnDManager, isMeasure: true, cellType: 'corner' }, gridCellProps), children); }; var rowHeight = function rowHeight(index) { return _this8._getRowHeight(_dataProvider, index, fixedColumns - 1, fixedRowHeight); }; var columnWidth = function columnWidth(index) { return _this8._getColumnWidth(_dataProvider, fixedRows - 1, index, fixedColumnWidth); }; // RTC #290279 - Crosstab and Grid will sometimes show blank cells when row span is active var overscanRowCount = fixedColumns > 1 ? 2 : 20; var overscanColumnCount = fixedRows > 1 ? 2 : 10; var style = {}; var grid = React.createElement(Toolkit.Grid, { rowHeight: rowHeight, columnWidth: columnWidth, numColumns: numColumns, numRows: numRows, fixedRows: fixedRows, fixedColumns: fixedColumns, dataCellRenderer: dataCellRenderer, fixedRowCellRenderer: fixedRowCellRenderer, fixedColumnCellRenderer: fixedColumnCellRenderer, fixedCornerCellRenderer: fixedCornerCellRenderer, overscanRowCount: overscanRowCount, overscanColumnCount: overscanColumnCount, style: style, ref: function ref(node) { _this8.gridRef = node; }, maxColumnWidth: Infinity }); var gridGuideLine = React.createElement('div', { class: 'xtab-grid-guideLine' }, ''); var crosstabGrid = React.createElement('div', { class: 'xtab-grid-view' }, [grid, gridGuideLine]); ReactDOM.render(crosstabGrid, this.$el[0]); this.gridRef && this.gridRef.recomputeGridSize(); }; CrosstabGrid.prototype._isSummary = function _isSummary(dataValue) { if (dataValue) { if (dataValue.rowEdge && dataValue.columnEdge) { return dataValue.columnEdge.isSummary || dataValue.rowEdge.isSummary; } else { return dataValue.isSummary; } } return false; }; /** * Set selections context which contains row edge selection, column edge selection * and datapoint selection **/ CrosstabGrid.prototype.setSelections = function setSelections(selections, options) { if (options && options.clearSelectionCaches) { this.resetSummaryHighlight(); this.clearMeasureHeaderDecorations(); } this._selections = selections; }; CrosstabGrid.prototype._getSlotIDByEdgeType = function _getSlotIDByEdgeType(edgeType) { if (edgeType === 'row') { return ROW_SLOT_ID; } else if (edgeType === 'column') { return COLUMN_SLOT_ID; } return null; }; CrosstabGrid.prototype.setStyles = function setStyles(styleObj) { this.textStyle = styleObj; }; CrosstabGrid.prototype._getCurrentEdgeSelectionContext = function _getCurrentEdgeSelectionContext(edge) { var aEdgeContextAncestor = _.clone(edge.ancestor_or_self); var aEdgeContextDescendant = _.clone(edge.descendant_or_self); aEdgeContextAncestor = _.filter(aEdgeContextAncestor, function (entry) { return entry.value; }); aEdgeContextAncestor.pop(); aEdgeContextDescendant = _.filter(aEdgeContextDescendant, function (entry) { return entry.value; }); return (aEdgeContextAncestor || []).concat(aEdgeContextDescendant || []); }; CrosstabGrid.prototype.onEnterContainer = function onEnterContainer() { var firstCellNode = $(this.$el[0]).find('.grid-corner-cell[row="0"][col="0"]'); if (firstCellNode.length) { firstCellNode.focus(); } }; CrosstabGrid.prototype._getValue = function _getValue(value) { if (value === null || value === undefined) { return; } return value.value && typeof value.value.label !== 'undefined' ? value.value.label : value.value; }; CrosstabGrid.prototype._getUseValue = function _getUseValue(value) { if (value.type === 'column' || value.type === 'row') { var aTuples = value.ancestor_or_self; if (aTuples) { return _.pluck(aTuples, 'value') + ''; } } return null; }; CrosstabGrid.prototype.showDropZone = function showDropZone(selector) { this.hideDropZones(); var cells = this.$el.find(selector); cells.css({ 'display': 'block' }); this.$el.find('.grid-column-resizer, .grid-row-resizer').css({ 'display': 'none' }); // Hide resizer handles }; CrosstabGrid.prototype.hideDropZones = function hideDropZones() { this.$el.find('.grid-drop-zone').css({ 'display': 'none' }); this.$el.find('.grid-column-resizer, .grid-row-resizer').css({ 'display': 'block' }); // Show resizer handles }; CrosstabGrid.prototype.showReplaceDropZone = function showReplaceDropZone(idx, type, useValue) { if (idx === 'corner') { this.showDropZone('.grid-corner-cell > .grid-drop-zone'); } else { if (type === 'row') { if (useValue) { this.showDropZone('.grid-fixed-row-cell[row="' + idx + '"][useValue="' + useValue + '"] > .grid-drop-zone'); } else { this.showDropZone('.grid-fixed-row-cell[row="' + idx + '"] > .grid-drop-zone'); } } else if (type === 'col') { this.showDropZone('.grid-fixed-column-cell[col="' + idx + '"] > .grid-drop-zone'); } } }; CrosstabGrid.prototype.showLeftDropZone = function showLeftDropZone(col) { if (col === 'corner') { this.showDropZone('.grid-corner-cell > .grid-drop-zone.left'); } else { this.showDropZone('.grid-fixed-column-cell[col="' + col + '"] > .grid-drop-zone.left, .grid-fixed-row-cell[col="' + col + '"] > .grid-drop-zone.left'); } }; CrosstabGrid.prototype.showRightDropZone = function showRightDropZone(col) { if (col === 'corner') { this.showDropZone('.grid-corner-cell > .grid-drop-zone.right'); } else { this.showDropZone('.grid-fixed-column-cell[col="' + col + '"] > .grid-drop-zone.right, .grid-fixed-row-cell[col="' + col + '"] > .grid-drop-zone.right'); } }; CrosstabGrid.prototype.showTopDropZone = function showTopDropZone(row) { this.showDropZone('.grid-fixed-row-cell[row="' + row + '"] > .grid-drop-zone.top'); }; CrosstabGrid.prototype.showBottomDropZone = function showBottomDropZone(row) { this.showDropZone('.grid-fixed-row-cell[row="' + row + '"] > .grid-drop-zone.bottom'); }; return CrosstabGrid; }(); }); //# sourceMappingURL=CrosstabGrid.js.map