UNPKG

ag-grid

Version:

Advanced Data Grid / Data Table supporting Javascript / React / AngularJS / Web Components

1,040 lines 58.3 kB
/** * ag-grid - Advanced Data Grid / Data Table supporting Javascript / React / AngularJS / Web Components * @version v17.0.0 * @link http://www.ag-grid.com/ * @license MIT */ "use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; Object.defineProperty(exports, "__esModule", { value: true }); var utils_1 = require("../utils"); var cellComp_1 = require("./cellComp"); var rowNode_1 = require("../entities/rowNode"); var gridOptionsWrapper_1 = require("../gridOptionsWrapper"); var column_1 = require("../entities/column"); var events_1 = require("../events"); var context_1 = require("../context/context"); var component_1 = require("../widgets/component"); var componentAnnotations_1 = require("../widgets/componentAnnotations"); var LoadingCellRenderer = (function (_super) { __extends(LoadingCellRenderer, _super); function LoadingCellRenderer() { return _super.call(this, LoadingCellRenderer.TEMPLATE) || this; } LoadingCellRenderer.prototype.init = function (params) { var eLoadingIcon = utils_1._.createIconNoSpan('groupLoading', this.gridOptionsWrapper, null); this.eLoadingIcon.appendChild(eLoadingIcon); var localeTextFunc = this.gridOptionsWrapper.getLocaleTextFunc(); this.eLoadingText.innerText = localeTextFunc('loadingOoo', 'Loading'); }; LoadingCellRenderer.prototype.refresh = function (params) { return false; }; LoadingCellRenderer.TEMPLATE = "<div class=\"ag-stub-cell\">\n <span class=\"ag-loading-icon\" ref=\"eLoadingIcon\"></span>\n <span class=\"ag-loading-text\" ref=\"eLoadingText\"></span>\n </div>"; __decorate([ context_1.Autowired('gridOptionsWrapper'), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], LoadingCellRenderer.prototype, "gridOptionsWrapper", void 0); __decorate([ componentAnnotations_1.RefSelector('eLoadingIcon'), __metadata("design:type", HTMLElement) ], LoadingCellRenderer.prototype, "eLoadingIcon", void 0); __decorate([ componentAnnotations_1.RefSelector('eLoadingText'), __metadata("design:type", HTMLElement) ], LoadingCellRenderer.prototype, "eLoadingText", void 0); return LoadingCellRenderer; }(component_1.Component)); exports.LoadingCellRenderer = LoadingCellRenderer; var RowComp = (function (_super) { __extends(RowComp, _super); function RowComp(parentScope, bodyContainerComp, pinnedLeftContainerComp, pinnedRightContainerComp, fullWidthContainerComp, rowNode, beans, animateIn, useAnimationFrameForCreate) { var _this = _super.call(this) || this; _this.eAllRowContainers = []; _this.active = true; _this.columnRefreshPending = false; _this.cellComps = {}; // for animations, there are bits we want done in the next VM turn, to all DOM to update first. // instead of each row doing a setTimeout(func,0), we put the functions here and the rowRenderer // executes them all in one timeout _this.createSecondPassFuncs = []; // these get called before the row is destroyed - they set up the DOM for the remove animation (ie they // set the DOM up for the animation), then the delayedDestroyFunctions get called when the animation is // complete (ie removes from the dom). _this.removeFirstPassFuncs = []; // for animations, these functions get called 400ms after the row is cleared, called by the rowRenderer // so each row isn't setting up it's own timeout _this.removeSecondPassFuncs = []; _this.initialised = false; _this.parentScope = parentScope; _this.beans = beans; _this.bodyContainerComp = bodyContainerComp; _this.pinnedLeftContainerComp = pinnedLeftContainerComp; _this.pinnedRightContainerComp = pinnedRightContainerComp; _this.fullWidthContainerComp = fullWidthContainerComp; _this.rowNode = rowNode; _this.rowIsEven = _this.rowNode.rowIndex % 2 === 0; _this.paginationPage = _this.beans.paginationProxy.getCurrentPage(); _this.useAnimationFrameForCreate = useAnimationFrameForCreate; _this.setAnimateFlags(animateIn); return _this; } RowComp.prototype.init = function () { var _this = this; this.rowFocused = this.beans.focusedCellController.isRowFocused(this.rowNode.rowIndex, this.rowNode.rowPinned); this.scope = this.createChildScopeOrNull(this.rowNode.data); this.setupRowContainers(); this.addListeners(); if (this.slideRowIn) { this.createSecondPassFuncs.push(function () { _this.onTopChanged(); }); } if (this.fadeRowIn) { this.createSecondPassFuncs.push(function () { _this.eAllRowContainers.forEach(function (eRow) { return utils_1._.removeCssClass(eRow, 'ag-opacity-zero'); }); }); } }; RowComp.prototype.createTemplate = function (contents, extraCssClass) { if (extraCssClass === void 0) { extraCssClass = null; } var templateParts = []; var rowHeight = this.rowNode.rowHeight; var rowClasses = this.getInitialRowClasses(extraCssClass).join(' '); var rowIdSanitised = utils_1._.escape(this.rowNode.id); var userRowStyles = this.preProcessStylesFromGridOptions(); var businessKey = this.getRowBusinessKey(); var businessKeySanitised = utils_1._.escape(businessKey); var rowTopStyle = this.getInitialRowTopStyle(); templateParts.push("<div"); templateParts.push(" role=\"row\""); templateParts.push(" row-index=\"" + this.rowNode.getRowIndexString() + "\""); templateParts.push(rowIdSanitised ? " row-id=\"" + rowIdSanitised + "\"" : ""); templateParts.push(businessKey ? " row-business-key=\"" + businessKeySanitised + "\"" : ""); templateParts.push(" comp-id=\"" + this.getCompId() + "\""); templateParts.push(" class=\"" + rowClasses + "\""); templateParts.push(" style=\"height: " + rowHeight + "px; " + rowTopStyle + " " + userRowStyles + "\">"); // add in the template for the cells templateParts.push(contents); templateParts.push("</div>"); return templateParts.join(''); }; RowComp.prototype.getCellForCol = function (column) { var cellComp = this.cellComps[column.getColId()]; if (cellComp) { return cellComp.getGui(); } else { return null; } }; RowComp.prototype.afterFlush = function () { if (!this.initialised) { this.initialised = true; this.executeProcessRowPostCreateFunc(); } }; RowComp.prototype.executeProcessRowPostCreateFunc = function () { var func = this.beans.gridOptionsWrapper.getProcessRowPostCreateFunc(); if (func) { var params = { eRow: this.eBodyRow, ePinnedLeftRow: this.ePinnedLeftRow, ePinnedRightRow: this.ePinnedRightRow, node: this.rowNode, api: this.beans.gridOptionsWrapper.getApi(), rowIndex: this.rowNode.rowIndex, addRenderedRowListener: this.addEventListener.bind(this), columnApi: this.beans.gridOptionsWrapper.getColumnApi(), context: this.beans.gridOptionsWrapper.getContext() }; func(params); } }; RowComp.prototype.getInitialRowTopStyle = function () { var rowTopStyle = ''; var setRowTop = !this.beans.forPrint && !this.beans.gridOptionsWrapper.isAutoHeight(); if (setRowTop) { // if sliding in, we take the old row top. otherwise we just set the current row top. var pixels = this.slideRowIn ? this.roundRowTopToBounds(this.rowNode.oldRowTop) : this.rowNode.rowTop; var afterPaginationPixels = this.applyPaginationOffset(pixels); var afterScalingPixels = this.beans.heightScaler.getRealPixelPosition(afterPaginationPixels); // if not setting row top, then below is empty string rowTopStyle = "transform: translateY(" + afterScalingPixels + "px); "; } return rowTopStyle; }; RowComp.prototype.getRowBusinessKey = function () { if (typeof this.beans.gridOptionsWrapper.getBusinessKeyForNodeFunc() === 'function') { var businessKey = this.beans.gridOptionsWrapper.getBusinessKeyForNodeFunc()(this.rowNode); return businessKey; } }; RowComp.prototype.lazyCreateCells = function (cols, eRow) { if (this.active) { var cellTemplatesAndComps = this.createCells(cols); eRow.innerHTML = cellTemplatesAndComps.template; this.callAfterRowAttachedOnCells(cellTemplatesAndComps.cellComps, eRow); } }; RowComp.prototype.createRowContainer = function (rowContainerComp, cols, callback) { var _this = this; var cellTemplatesAndComps; if (this.useAnimationFrameForCreate) { cellTemplatesAndComps = { cellComps: [], template: '' }; } else { cellTemplatesAndComps = this.createCells(cols); } var rowTemplate = this.createTemplate(cellTemplatesAndComps.template); rowContainerComp.appendRowTemplate(rowTemplate, function () { var eRow = rowContainerComp.getRowElement(_this.getCompId()); _this.afterRowAttached(rowContainerComp, eRow); callback(eRow); if (_this.useAnimationFrameForCreate) { _this.beans.taskQueue.addP1Task(_this.lazyCreateCells.bind(_this, cols, eRow)); } else { _this.callAfterRowAttachedOnCells(cellTemplatesAndComps.cellComps, eRow); } }); }; RowComp.prototype.createChildScopeOrNull = function (data) { if (this.beans.gridOptionsWrapper.isAngularCompileRows()) { var newChildScope_1 = this.parentScope.$new(); newChildScope_1.data = data; newChildScope_1.rowNode = this.rowNode; newChildScope_1.context = this.beans.gridOptionsWrapper.getContext(); this.addDestroyFunc(function () { newChildScope_1.$destroy(); newChildScope_1.data = null; newChildScope_1.rowNode = null; newChildScope_1.context = null; }); return newChildScope_1; } else { return null; } }; RowComp.prototype.setupRowContainers = function () { var isFullWidthCellFunc = this.beans.gridOptionsWrapper.getIsFullWidthCellFunc(); var isFullWidthCell = isFullWidthCellFunc ? isFullWidthCellFunc(this.rowNode) : false; var isDetailCell = this.beans.doingMasterDetail && this.rowNode.detail; var isGroupSpanningRow = this.rowNode.group && this.beans.gridOptionsWrapper.isGroupUseEntireRow(); if (this.rowNode.stub) { this.createFullWidthRows(RowComp.LOADING_CELL_RENDERER, RowComp.LOADING_CELL_RENDERER_COMP_NAME); } else if (isDetailCell) { this.createFullWidthRows(RowComp.DETAIL_CELL_RENDERER, RowComp.DETAIL_CELL_RENDERER_COMP_NAME); } else if (isFullWidthCell) { this.createFullWidthRows(RowComp.FULL_WIDTH_CELL_RENDERER, null); } else if (isGroupSpanningRow) { this.createFullWidthRows(RowComp.GROUP_ROW_RENDERER, RowComp.GROUP_ROW_RENDERER_COMP_NAME); } else { this.setupNormalRowContainers(); } }; RowComp.prototype.setupNormalRowContainers = function () { var _this = this; var centerCols = this.beans.columnController.getAllDisplayedCenterVirtualColumnsForRow(this.rowNode); this.createRowContainer(this.bodyContainerComp, centerCols, function (eRow) { return _this.eBodyRow = eRow; }); if (!this.beans.forPrint) { var leftCols = this.beans.columnController.getDisplayedLeftColumnsForRow(this.rowNode); var rightCols = this.beans.columnController.getDisplayedRightColumnsForRow(this.rowNode); this.createRowContainer(this.pinnedRightContainerComp, rightCols, function (eRow) { return _this.ePinnedRightRow = eRow; }); this.createRowContainer(this.pinnedLeftContainerComp, leftCols, function (eRow) { return _this.ePinnedLeftRow = eRow; }); } }; RowComp.prototype.createFullWidthRows = function (type, name) { var _this = this; this.fullWidthRow = true; this.fullWidthRowEmbedded = this.beans.gridOptionsWrapper.isEmbedFullWidthRows(); if (this.fullWidthRowEmbedded) { this.createFullWidthRowContainer(this.bodyContainerComp, null, null, type, name, function (eRow) { _this.eFullWidthRowBody = eRow; }, function (cellRenderer) { _this.fullWidthRowComponentBody = cellRenderer; }); this.createFullWidthRowContainer(this.pinnedLeftContainerComp, column_1.Column.PINNED_LEFT, 'ag-cell-last-left-pinned', type, name, function (eRow) { _this.eFullWidthRowLeft = eRow; }, function (cellRenderer) { _this.fullWidthRowComponentLeft = cellRenderer; }); this.createFullWidthRowContainer(this.pinnedRightContainerComp, column_1.Column.PINNED_RIGHT, 'ag-cell-first-right-pinned', type, name, function (eRow) { _this.eFullWidthRowRight = eRow; }, function (cellRenderer) { _this.fullWidthRowComponentRight = cellRenderer; }); } else { // otherwise we add to the fullWidth container as normal // let previousFullWidth = ensureDomOrder ? this.lastPlacedElements.eFullWidth : null; this.createFullWidthRowContainer(this.fullWidthContainerComp, null, null, type, name, function (eRow) { _this.eFullWidthRow = eRow; // and fake the mouse wheel for the fullWidth container if (!_this.beans.forPrint) { _this.addMouseWheelListenerToFullWidthRow(); } }, function (cellRenderer) { _this.fullWidthRowComponent = cellRenderer; }); } }; RowComp.prototype.addMouseWheelListenerToFullWidthRow = function () { var mouseWheelListener = this.beans.gridPanel.genericMouseWheelListener.bind(this.beans.gridPanel); // IE9, Chrome, Safari, Opera this.addDestroyableEventListener(this.eFullWidthRow, 'mousewheel', mouseWheelListener); // Firefox this.addDestroyableEventListener(this.eFullWidthRow, 'DOMMouseScroll', mouseWheelListener); }; RowComp.prototype.setAnimateFlags = function (animateIn) { if (animateIn) { var oldRowTopExists = utils_1._.exists(this.rowNode.oldRowTop); // if the row had a previous position, we slide it in (animate row top) this.slideRowIn = oldRowTopExists; // if the row had no previous position, we fade it in (animate this.fadeRowIn = !oldRowTopExists; } else { this.slideRowIn = false; this.fadeRowIn = false; } }; RowComp.prototype.isEditing = function () { return this.editingRow; }; RowComp.prototype.stopRowEditing = function (cancel) { this.stopEditing(cancel); }; RowComp.prototype.isFullWidth = function () { return this.fullWidthRow; }; RowComp.prototype.addListeners = function () { this.addDestroyableEventListener(this.rowNode, rowNode_1.RowNode.EVENT_HEIGHT_CHANGED, this.onRowHeightChanged.bind(this)); this.addDestroyableEventListener(this.rowNode, rowNode_1.RowNode.EVENT_ROW_SELECTED, this.onRowSelected.bind(this)); this.addDestroyableEventListener(this.rowNode, rowNode_1.RowNode.EVENT_ROW_INDEX_CHANGED, this.onRowIndexChanged.bind(this)); this.addDestroyableEventListener(this.rowNode, rowNode_1.RowNode.EVENT_TOP_CHANGED, this.onTopChanged.bind(this)); this.addDestroyableEventListener(this.rowNode, rowNode_1.RowNode.EVENT_EXPANDED_CHANGED, this.onExpandedChanged.bind(this)); this.addDestroyableEventListener(this.rowNode, rowNode_1.RowNode.EVENT_DATA_CHANGED, this.onRowNodeDataChanged.bind(this)); this.addDestroyableEventListener(this.rowNode, rowNode_1.RowNode.EVENT_CELL_CHANGED, this.onRowNodeCellChanged.bind(this)); this.addDestroyableEventListener(this.rowNode, rowNode_1.RowNode.EVENT_DRAGGING_CHANGED, this.onRowNodeDraggingChanged.bind(this)); var eventService = this.beans.eventService; this.addDestroyableEventListener(eventService, events_1.Events.EVENT_HEIGHT_SCALE_CHANGED, this.onTopChanged.bind(this)); this.addDestroyableEventListener(eventService, events_1.Events.EVENT_DISPLAYED_COLUMNS_CHANGED, this.onDisplayedColumnsChanged.bind(this)); this.addDestroyableEventListener(eventService, events_1.Events.EVENT_VIRTUAL_COLUMNS_CHANGED, this.onVirtualColumnsChanged.bind(this)); this.addDestroyableEventListener(eventService, events_1.Events.EVENT_COLUMN_RESIZED, this.onColumnResized.bind(this)); this.addDestroyableEventListener(eventService, events_1.Events.EVENT_CELL_FOCUSED, this.onCellFocusChanged.bind(this)); this.addDestroyableEventListener(eventService, events_1.Events.EVENT_PAGINATION_CHANGED, this.onPaginationChanged.bind(this)); this.addDestroyableEventListener(eventService, events_1.Events.EVENT_GRID_COLUMNS_CHANGED, this.onGridColumnsChanged.bind(this)); }; // when grid columns change, then all cells should be cleaned out, // as the new columns could have same id as the previous columns and may conflict RowComp.prototype.onGridColumnsChanged = function () { var allRenderedCellIds = Object.keys(this.cellComps); this.removeRenderedCells(allRenderedCellIds); }; RowComp.prototype.onRowNodeDataChanged = function (event) { // if this is an update, we want to refresh, as this will allow the user to put in a transition // into the cellRenderer refresh method. otherwise this might be completely new data, in which case // we will want to completely replace the cells this.forEachCellComp(function (cellComp) { return cellComp.refreshCell({ suppressFlash: !event.update, newData: !event.update }); }); // check for selected also, as this could be after lazy loading of the row data, in which case // the id might of just gotten set inside the row and the row selected state may of changed // as a result. this is what happens when selected rows are loaded in virtual pagination. // - niall note - since moving to the stub component, this may no longer be true, as replacing // the stub component now replaces the entire row this.onRowSelected(); // as data has changed, then the style and class needs to be recomputed this.postProcessCss(); }; RowComp.prototype.onRowNodeCellChanged = function (event) { // as data has changed, then the style and class needs to be recomputed this.postProcessCss(); }; RowComp.prototype.postProcessCss = function () { this.postProcessStylesFromGridOptions(); this.postProcessClassesFromGridOptions(); this.postProcessRowClassRules(); this.postProcessRowDragging(); }; RowComp.prototype.onRowNodeDraggingChanged = function () { this.postProcessRowDragging(); }; RowComp.prototype.postProcessRowDragging = function () { var dragging = this.rowNode.dragging; this.eAllRowContainers.forEach(function (row) { return utils_1._.addOrRemoveCssClass(row, 'ag-row-dragging', dragging); }); }; RowComp.prototype.onExpandedChanged = function () { if (this.rowNode.group && !this.rowNode.footer) { var expanded_1 = this.rowNode.expanded; this.eAllRowContainers.forEach(function (row) { return utils_1._.addOrRemoveCssClass(row, 'ag-row-group-expanded', expanded_1); }); this.eAllRowContainers.forEach(function (row) { return utils_1._.addOrRemoveCssClass(row, 'ag-row-group-contracted', !expanded_1); }); } }; RowComp.prototype.onDisplayedColumnsChanged = function () { if (!this.fullWidthRow) { this.refreshCells(); } }; RowComp.prototype.destroyFullWidthComponents = function () { if (this.fullWidthRowComponent) { if (this.fullWidthRowComponent.destroy) { this.fullWidthRowComponent.destroy(); } this.fullWidthRowComponent = null; } if (this.fullWidthRowComponentBody) { if (this.fullWidthRowComponentBody.destroy) { this.fullWidthRowComponentBody.destroy(); } this.fullWidthRowComponent = null; } if (this.fullWidthRowComponentLeft) { if (this.fullWidthRowComponentLeft.destroy) { this.fullWidthRowComponentLeft.destroy(); } this.fullWidthRowComponentLeft = null; } if (this.fullWidthRowComponentRight) { if (this.fullWidthRowComponentRight.destroy) { this.fullWidthRowComponentRight.destroy(); } this.fullWidthRowComponent = null; } }; RowComp.prototype.getContainerForCell = function (pinnedType) { switch (pinnedType) { case column_1.Column.PINNED_LEFT: return this.ePinnedLeftRow; case column_1.Column.PINNED_RIGHT: return this.ePinnedRightRow; default: return this.eBodyRow; } }; RowComp.prototype.onVirtualColumnsChanged = function () { if (!this.fullWidthRow) { this.refreshCells(); } }; RowComp.prototype.onColumnResized = function () { if (!this.fullWidthRow) { this.refreshCells(); } }; RowComp.prototype.refreshCells = function () { if (this.beans.gridOptionsWrapper.isSuppressAnimationFrame()) { this.refreshCellsInAnimationFrame(); } else { if (this.columnRefreshPending) { return; } this.beans.taskQueue.addP1Task(this.refreshCellsInAnimationFrame.bind(this)); } }; RowComp.prototype.refreshCellsInAnimationFrame = function () { if (!this.active) { return; } this.columnRefreshPending = false; var centerCols = this.beans.columnController.getAllDisplayedCenterVirtualColumnsForRow(this.rowNode); var leftCols = this.beans.columnController.getDisplayedLeftColumnsForRow(this.rowNode); var rightCols = this.beans.columnController.getDisplayedRightColumnsForRow(this.rowNode); this.insertCellsIntoContainer(this.eBodyRow, centerCols); this.insertCellsIntoContainer(this.ePinnedLeftRow, leftCols); this.insertCellsIntoContainer(this.ePinnedRightRow, rightCols); var colIdsToRemove = Object.keys(this.cellComps); centerCols.forEach(function (col) { return utils_1._.removeFromArray(colIdsToRemove, col.getId()); }); leftCols.forEach(function (col) { return utils_1._.removeFromArray(colIdsToRemove, col.getId()); }); rightCols.forEach(function (col) { return utils_1._.removeFromArray(colIdsToRemove, col.getId()); }); // we never remove editing cells, as this would cause the cells to loose their values while editing // as the grid is scrolling horizontally. colIdsToRemove = utils_1._.filter(colIdsToRemove, this.isCellEligibleToBeRemoved.bind(this)); // remove old cells from gui, but we don't destroy them, we might use them again this.removeRenderedCells(colIdsToRemove); }; RowComp.prototype.removeRenderedCells = function (colIds) { var _this = this; colIds.forEach(function (key) { var cellComp = _this.cellComps[key]; // could be old reference, ie removed cell if (utils_1._.missing(cellComp)) { return; } cellComp.detach(); cellComp.destroy(); _this.cellComps[key] = null; }); }; RowComp.prototype.isCellEligibleToBeRemoved = function (indexStr) { var displayedColumns = this.beans.columnController.getAllDisplayedColumns(); var REMOVE_CELL = true; var KEEP_CELL = false; var renderedCell = this.cellComps[indexStr]; if (!renderedCell) { return REMOVE_CELL; } // always remove the cell if it's in the wrong pinned location if (this.isCellInWrongRow(renderedCell)) { return REMOVE_CELL; } // we want to try and keep editing and focused cells var editing = renderedCell.isEditing(); var focused = this.beans.focusedCellController.isCellFocused(renderedCell.getGridCell()); var mightWantToKeepCell = editing || focused; if (mightWantToKeepCell) { var column = renderedCell.getColumn(); var cellStillDisplayed = displayedColumns.indexOf(column) >= 0; return cellStillDisplayed ? KEEP_CELL : REMOVE_CELL; } else { return REMOVE_CELL; } }; RowComp.prototype.ensureCellInCorrectContainer = function (cellComp) { var element = cellComp.getGui(); var column = cellComp.getColumn(); var pinnedType = column.getPinned(); var eContainer = this.getContainerForCell(pinnedType); // if in wrong container, remove it var eOldContainer = cellComp.getParentRow(); var inWrongRow = eOldContainer !== eContainer; if (inWrongRow) { // take out from old row if (eOldContainer) { eOldContainer.removeChild(element); } eContainer.appendChild(element); cellComp.setParentRow(eContainer); } }; RowComp.prototype.isCellInWrongRow = function (cellComp) { var column = cellComp.getColumn(); var rowWeWant = this.getContainerForCell(column.getPinned()); // if in wrong container, remove it var oldRow = cellComp.getParentRow(); return oldRow !== rowWeWant; }; RowComp.prototype.insertCellsIntoContainer = function (eRow, cols) { var _this = this; if (!eRow) { return; } var cellTemplates = []; var newCellComps = []; cols.forEach(function (col) { var colId = col.getId(); var oldCell = _this.cellComps[colId]; if (oldCell) { _this.ensureCellInCorrectContainer(oldCell); } else { _this.createNewCell(col, eRow, cellTemplates, newCellComps); } }); if (cellTemplates.length > 0) { utils_1._.appendHtml(eRow, cellTemplates.join('')); this.callAfterRowAttachedOnCells(newCellComps, eRow); } }; RowComp.prototype.addDomData = function (eRowContainer) { var gow = this.beans.gridOptionsWrapper; gow.setDomData(eRowContainer, RowComp.DOM_DATA_KEY_RENDERED_ROW, this); this.addDestroyFunc(function () { gow.setDomData(eRowContainer, RowComp.DOM_DATA_KEY_RENDERED_ROW, null); }); }; RowComp.prototype.createNewCell = function (col, eContainer, cellTemplates, newCellComps) { var newCellComp = new cellComp_1.CellComp(this.scope, this.beans, col, this.rowNode, this); var cellTemplate = newCellComp.getCreateTemplate(); cellTemplates.push(cellTemplate); newCellComps.push(newCellComp); this.cellComps[col.getId()] = newCellComp; newCellComp.setParentRow(eContainer); }; RowComp.prototype.onMouseEvent = function (eventName, mouseEvent) { switch (eventName) { case 'dblclick': this.onRowDblClick(mouseEvent); break; case 'click': this.onRowClick(mouseEvent); break; } }; RowComp.prototype.createRowEvent = function (type, domEvent) { return { type: type, node: this.rowNode, data: this.rowNode.data, rowIndex: this.rowNode.rowIndex, rowPinned: this.rowNode.rowPinned, context: this.beans.gridOptionsWrapper.getContext(), api: this.beans.gridOptionsWrapper.getApi(), columnApi: this.beans.gridOptionsWrapper.getColumnApi(), event: domEvent }; }; RowComp.prototype.createRowEventWithSource = function (type, domEvent) { var event = this.createRowEvent(type, domEvent); // when first developing this, we included the rowComp in the event. // this seems very weird. so when introducing the event types, i left the 'source' // out of the type, and just include the source in the two places where this event // was fired (rowClicked and rowDoubleClicked). it doesn't make sense for any // users to be using this, as the rowComp isn't an object we expose, so would be // very surprising if a user was using it. event.source = this; return event; }; RowComp.prototype.onRowDblClick = function (mouseEvent) { if (utils_1._.isStopPropagationForAgGrid(mouseEvent)) { return; } var agEvent = this.createRowEventWithSource(events_1.Events.EVENT_ROW_DOUBLE_CLICKED, mouseEvent); this.beans.eventService.dispatchEvent(agEvent); }; RowComp.prototype.onRowClick = function (mouseEvent) { if (utils_1._.isStopPropagationForAgGrid(mouseEvent)) { return; } var agEvent = this.createRowEventWithSource(events_1.Events.EVENT_ROW_CLICKED, mouseEvent); this.beans.eventService.dispatchEvent(agEvent); // ctrlKey for windows, metaKey for Apple var multiSelectKeyPressed = mouseEvent.ctrlKey || mouseEvent.metaKey; var shiftKeyPressed = mouseEvent.shiftKey; // we do not allow selecting groups by clicking (as the click here expands the group) // so return if it's a group row if (this.rowNode.group) { return; } // we also don't allow selection of pinned rows if (this.rowNode.rowPinned) { return; } // if no selection method enabled, do nothing if (!this.beans.gridOptionsWrapper.isRowSelection()) { return; } // if click selection suppressed, do nothing if (this.beans.gridOptionsWrapper.isSuppressRowClickSelection()) { return; } var multiSelectOnClick = this.beans.gridOptionsWrapper.isRowMultiSelectWithClick(); var rowDeselectionWithCtrl = this.beans.gridOptionsWrapper.isRowDeselection(); if (this.rowNode.isSelected()) { if (multiSelectOnClick) { this.rowNode.setSelectedParams({ newValue: false }); } else if (multiSelectKeyPressed) { if (rowDeselectionWithCtrl) { this.rowNode.setSelectedParams({ newValue: false }); } } else { // selected with no multi key, must make sure anything else is unselected this.rowNode.setSelectedParams({ newValue: true, clearSelection: true }); } } else { var clearSelection = multiSelectOnClick ? false : !multiSelectKeyPressed; this.rowNode.setSelectedParams({ newValue: true, clearSelection: clearSelection, rangeSelect: shiftKeyPressed }); } }; RowComp.prototype.createFullWidthRowContainer = function (rowContainerComp, pinned, extraCssClass, cellRendererType, cellRendererName, eRowCallback, cellRendererCallback) { var _this = this; var rowTemplate = this.createTemplate('', extraCssClass); rowContainerComp.appendRowTemplate(rowTemplate, function () { var eRow = rowContainerComp.getRowElement(_this.getCompId()); var params = _this.createFullWidthParams(eRow, pinned); var callback = function (cellRenderer) { if (_this.isAlive()) { var gui = cellRenderer.getGui(); eRow.appendChild(gui); cellRendererCallback(cellRenderer); } else { if (cellRenderer.destroy) { cellRenderer.destroy(); } } }; _this.beans.componentResolver.createAgGridComponent(null, params, cellRendererType, params, cellRendererName).then(callback); _this.afterRowAttached(rowContainerComp, eRow); eRowCallback(eRow); _this.angular1Compile(eRow); }); }; RowComp.prototype.angular1Compile = function (element) { if (this.scope) { this.beans.$compile(element)(this.scope); } }; RowComp.prototype.createFullWidthParams = function (eRow, pinned) { var params = { fullWidth: true, data: this.rowNode.data, node: this.rowNode, value: this.rowNode.key, $scope: this.scope, rowIndex: this.rowNode.rowIndex, api: this.beans.gridOptionsWrapper.getApi(), columnApi: this.beans.gridOptionsWrapper.getColumnApi(), context: this.beans.gridOptionsWrapper.getContext(), // these need to be taken out, as part of 'afterAttached' now eGridCell: eRow, eParentOfValue: eRow, pinned: pinned, addRenderedRowListener: this.addEventListener.bind(this) }; return params; }; RowComp.prototype.getInitialRowClasses = function (extraCssClass) { var classes = []; if (utils_1._.exists(extraCssClass)) { classes.push(extraCssClass); } classes.push('ag-row'); classes.push(this.rowFocused ? 'ag-row-focus' : 'ag-row-no-focus'); if (this.fadeRowIn) { classes.push('ag-opacity-zero'); } if (this.rowIsEven) { classes.push('ag-row-even'); } else { classes.push('ag-row-odd'); } if (this.rowNode.isSelected()) { classes.push('ag-row-selected'); } if (this.rowNode.group) { classes.push('ag-row-group'); // if a group, put the level of the group in classes.push('ag-row-level-' + this.rowNode.level); if (this.rowNode.footer) { classes.push('ag-row-footer'); } } else { // if a leaf, and a parent exists, put a level of the parent, else put level of 0 for top level item if (this.rowNode.parent) { classes.push('ag-row-level-' + (this.rowNode.parent.level + 1)); } else { classes.push('ag-row-level-0'); } } if (this.rowNode.stub) { classes.push('ag-row-stub'); } if (this.fullWidthRow) { classes.push('ag-full-width-row'); } if (this.rowNode.group && !this.rowNode.footer) { classes.push(this.rowNode.expanded ? 'ag-row-group-expanded' : 'ag-row-group-contracted'); } if (this.rowNode.dragging) { classes.push('ag-row-dragging'); } utils_1._.pushAll(classes, this.processClassesFromGridOptions()); utils_1._.pushAll(classes, this.preProcessRowClassRules()); return classes; }; RowComp.prototype.preProcessRowClassRules = function () { var res = []; this.processRowClassRules(function (className) { res.push(className); }, function (className) { // not catered for, if creating, no need // to remove class as it was never there }); return res; }; RowComp.prototype.processRowClassRules = function (onApplicableClass, onNotApplicableClass) { this.beans.stylingService.processClassRules(this.beans.gridOptionsWrapper.rowClassRules(), { value: undefined, colDef: undefined, data: this.rowNode.data, node: this.rowNode, rowIndex: this.rowNode.rowIndex, api: this.beans.gridOptionsWrapper.getApi(), $scope: this.scope, context: this.beans.gridOptionsWrapper.getContext() }, onApplicableClass, onNotApplicableClass); }; RowComp.prototype.stopEditing = function (cancel) { if (cancel === void 0) { cancel = false; } this.forEachCellComp(function (renderedCell) { renderedCell.stopEditing(cancel); }); if (this.editingRow) { if (!cancel) { var event_1 = this.createRowEvent(events_1.Events.EVENT_ROW_VALUE_CHANGED); this.beans.eventService.dispatchEvent(event_1); } this.setEditingRow(false); } }; RowComp.prototype.setEditingRow = function (value) { this.editingRow = value; this.eAllRowContainers.forEach(function (row) { return utils_1._.addOrRemoveCssClass(row, 'ag-row-editing', value); }); var event = value ? this.createRowEvent(events_1.Events.EVENT_ROW_EDITING_STARTED) : this.createRowEvent(events_1.Events.EVENT_ROW_EDITING_STOPPED); this.beans.eventService.dispatchEvent(event); }; RowComp.prototype.startRowEditing = function (keyPress, charPress, sourceRenderedCell) { if (keyPress === void 0) { keyPress = null; } if (charPress === void 0) { charPress = null; } if (sourceRenderedCell === void 0) { sourceRenderedCell = null; } // don't do it if already editing if (this.editingRow) { return; } this.forEachCellComp(function (renderedCell) { var cellStartedEdit = renderedCell === sourceRenderedCell; if (cellStartedEdit) { renderedCell.startEditingIfEnabled(keyPress, charPress, cellStartedEdit); } else { renderedCell.startEditingIfEnabled(null, null, cellStartedEdit); } }); this.setEditingRow(true); }; RowComp.prototype.forEachCellComp = function (callback) { utils_1._.iterateObject(this.cellComps, function (key, cellComp) { if (cellComp) { callback(cellComp); } }); }; RowComp.prototype.postProcessClassesFromGridOptions = function () { var _this = this; var cssClasses = this.processClassesFromGridOptions(); if (cssClasses) { cssClasses.forEach(function (classStr) { _this.eAllRowContainers.forEach(function (row) { return utils_1._.addCssClass(row, classStr); }); }); } }; RowComp.prototype.postProcessRowClassRules = function () { var _this = this; this.processRowClassRules(function (className) { _this.eAllRowContainers.forEach(function (row) { return utils_1._.addCssClass(row, className); }); }, function (className) { _this.eAllRowContainers.forEach(function (row) { return utils_1._.removeCssClass(row, className); }); }); }; RowComp.prototype.processClassesFromGridOptions = function () { var res = []; var process = function (rowClass) { if (typeof rowClass === 'string') { res.push(rowClass); } else if (Array.isArray(rowClass)) { rowClass.forEach(function (e) { return res.push(e); }); } }; // part 1 - rowClass var rowClass = this.beans.gridOptionsWrapper.getRowClass(); if (rowClass) { if (typeof rowClass === 'function') { console.warn('ag-Grid: rowClass should not be a function, please use getRowClass instead'); return; } process(rowClass); } // part 2 - rowClassFunc var rowClassFunc = this.beans.gridOptionsWrapper.getRowClassFunc(); if (rowClassFunc) { var params = { node: this.rowNode, data: this.rowNode.data, rowIndex: this.rowNode.rowIndex, context: this.beans.gridOptionsWrapper.getContext(), api: this.beans.gridOptionsWrapper.getApi() }; var rowClassFuncResult = rowClassFunc(params); process(rowClassFuncResult); } return res; }; RowComp.prototype.preProcessStylesFromGridOptions = function () { var rowStyles = this.processStylesFromGridOptions(); return utils_1._.cssStyleObjectToMarkup(rowStyles); }; RowComp.prototype.postProcessStylesFromGridOptions = function () { var rowStyles = this.processStylesFromGridOptions(); this.eAllRowContainers.forEach(function (row) { return utils_1._.addStylesToElement(row, rowStyles); }); }; RowComp.prototype.processStylesFromGridOptions = function () { // part 1 - rowStyle var rowStyle = this.beans.gridOptionsWrapper.getRowStyle(); if (rowStyle && typeof rowStyle === 'function') { console.log('ag-Grid: rowStyle should be an object of key/value styles, not be a function, use getRowStyle() instead'); return; } // part 1 - rowStyleFunc var rowStyleFunc = this.beans.gridOptionsWrapper.getRowStyleFunc(); var rowStyleFuncResult; if (rowStyleFunc) { var params = { data: this.rowNode.data, node: this.rowNode, api: this.beans.gridOptionsWrapper.getApi(), context: this.beans.gridOptionsWrapper.getContext(), $scope: this.scope }; rowStyleFuncResult = rowStyleFunc(params); } return utils_1._.assign({}, rowStyle, rowStyleFuncResult); }; RowComp.prototype.createCells = function (cols) { var _this = this; var templateParts = []; var newCellComps = []; cols.forEach(function (col) { var newCellComp = new cellComp_1.CellComp(_this.scope, _this.beans, col, _this.rowNode, _this); var cellTemplate = newCellComp.getCreateTemplate(); templateParts.push(cellTemplate); newCellComps.push(newCellComp); _this.cellComps[col.getId()] = newCellComp; }); var templateAndComps = { template: templateParts.join(''), cellComps: newCellComps }; return templateAndComps; }; RowComp.prototype.onRowSelected = function () { var selected = this.rowNode.isSelected(); this.eAllRowContainers.forEach(function (row) { return utils_1._.addOrRemoveCssClass(row, 'ag-row-selected', selected); }); }; // called: // + after row created for first time // + after horizontal scroll, so new cells due to column virtualisation RowComp.prototype.callAfterRowAttachedOnCells = function (newCellComps, eRow) { var _this = this; newCellComps.forEach(function (cellComp) { cellComp.setParentRow(eRow); cellComp.afterAttached(); // if we are editing the row, then the cell needs to turn // into edit mode if (_this.editingRow) { cellComp.startEditingIfEnabled(); } }); }; RowComp.prototype.afterRowAttached = function (rowContainerComp, eRow) { var _this = this; this.addDomData(eRow); this.removeSecondPassFuncs.push(function () { // console.log(eRow); rowContainerComp.removeRowElement(eRow); }); this.removeFirstPassFuncs.push(function () { if (utils_1._.exists(_this.rowNode.rowTop)) { // the row top is updated anyway, however we set it here again // to something more reasonable for the animation - ie if the // row top is 10000px away, the row will flash out, so this // gives it a rounded value, so row animates out more slowly var rowTop = _this.roundRowTopToBounds(_this.rowNode.rowTop); _this.setRowTop(rowTop); } else { utils_1._.addCssClass(eRow, 'ag-opacity-zero'); } }); this.eAllRowContainers.push(eRow); // adding hover functionality adds listener to this row, so we // do it lazily in an animation frame if (this.useAnimationFrameForCreate) { this.beans.taskQueue.addP1Task(this.addHoverFunctionality.bind(this, eRow)); } else { this.addHoverFunctionality(eRow); } }; RowComp.prototype.addHoverFunctionality = function (eRow) { var _this = this; // because we use animation frames to do this, it's possible the row no longer exists // by the time we get to add it if (!this.active) { return; } // because mouseenter and mouseleave do not propagate, we cannot listen on the gridPanel // like we do for all the other mouse events. // because of the pinning, we cannot simply add / remove the class based on the eRow. we // have to check all eRow's (body & pinned). so the trick is if any of the rows gets a // mouse hover, it sets such in the rowNode, and then all three reflect the change as // all are listening for event on the row node. // step 1 - add listener, to set flag on row node this.addDestroyableEventListener(eRow, 'mouseenter', function () { return _this.rowNode.onMouseEnter(); }); this.addDestroyableEventListener(eRow, 'mouseleave', function () { return _this.rowNode.onMouseLeave(); }); // step 2 - listen for changes on row node (which any eRow can trigger) this.addDestroyableEventListener(this.rowNode, rowNode_1.RowNode.EVENT_MOUSE_ENTER, function () { utils_1._.addCssClass(eRow, 'ag-row-hover'); }); this.addDestroyableEventListener(this.rowNode, rowNode_1.RowNode.EVENT_MOUSE_LEAVE, function () { utils_1._.removeCssClass(eRow, 'ag-row-hover'); }); }; // for animation, we don't want to animate entry or exit to a very far away pixel, // otherwise the row would move so fast, it would appear to disappear. so this method // moves the row closer to the viewport if it is far away, so the row slide in / out // at a speed the user can see. RowComp.prototype.roundRowTopToBounds = function (rowTop) { var range = this.beans.gridPanel.getVScrollPosition(); var minPixel = this.applyPaginationOffset(range.top, true) - 100; var maxPixel = this.applyPaginationOffset(range.bottom, true) + 100; if (rowTop < minPixel) { return minPixel; } else if (rowTop > maxPixel) { return maxPixel; } else { return rowTop; } }; RowComp.prototype.onRowHeightChanged = function () { // check for exists first - if the user is resetting the row height, then // it will be null (or undefined) momentarily until the next time the flatten // stage is called where the row will then update again with a new height if (utils_1._.exists(this.rowNode.rowHeight)) { var heightPx_1 = this.rowNode.rowHeight + 'px'; this.eAllRowContainers.forEach(function (row) { return row.style.height = heightPx_1; }); } }; RowComp.prototype.addEventListener = function (eventType, listener) { if (eventType === 'renderedRowRemoved' || eventType === 'rowRemoved') { eventType = events_1.Events.EVENT_VIRTUAL_ROW_REMOVED; console.warn('ag-Grid: Since version 11, event renderedRowRemoved is now called ' + events_1.Events.EVENT_VIRTUAL_ROW_REMOVED); } _super.prototype.addEventListener.call