1 | import {_} from "../utils";
|
2 | import {CellComp} from "./cellComp";
|
3 | import {CellChangedEvent, DataChangedEvent, RowNode} from "../entities/rowNode";
|
4 | import {GridOptionsWrapper} from "../gridOptionsWrapper";
|
5 | import {Column} from "../entities/column";
|
6 | import {
|
7 | Events,
|
8 | RowClickedEvent,
|
9 | RowDoubleClickedEvent,
|
10 | RowEditingStartedEvent,
|
11 | RowEditingStoppedEvent,
|
12 | RowEvent,
|
13 | RowValueChangedEvent,
|
14 | VirtualRowRemovedEvent
|
15 | } from "../events";
|
16 | import {Autowired} from "../context/context";
|
17 | import {ICellRendererComp, ICellRendererParams} from "./cellRenderers/iCellRenderer";
|
18 | import {RowContainerComponent} from "./rowContainerComponent";
|
19 | import {Component} from "../widgets/component";
|
20 | import {RefSelector} from "../widgets/componentAnnotations";
|
21 | import {Beans} from "./beans";
|
22 | import {ProcessRowParams} from "../entities/gridOptions";
|
23 |
|
24 | export class LoadingCellRenderer extends Component {
|
25 |
|
26 | private static TEMPLATE =
|
27 | `<div class="ag-stub-cell">
|
28 | <span class="ag-loading-icon" ref="eLoadingIcon"></span>
|
29 | <span class="ag-loading-text" ref="eLoadingText"></span>
|
30 | </div>`;
|
31 |
|
32 | @Autowired('gridOptionsWrapper') gridOptionsWrapper: GridOptionsWrapper;
|
33 |
|
34 | @RefSelector('eLoadingIcon') private eLoadingIcon: HTMLElement;
|
35 | @RefSelector('eLoadingText') private eLoadingText: HTMLElement;
|
36 |
|
37 | constructor() {
|
38 | super(LoadingCellRenderer.TEMPLATE);
|
39 | }
|
40 |
|
41 | public init(params: ICellRendererParams): void {
|
42 | let eLoadingIcon = _.createIconNoSpan('groupLoading', this.gridOptionsWrapper, null);
|
43 | this.eLoadingIcon.appendChild(eLoadingIcon);
|
44 |
|
45 | let localeTextFunc = this.gridOptionsWrapper.getLocaleTextFunc();
|
46 | this.eLoadingText.innerText = localeTextFunc('loadingOoo', 'Loading');
|
47 | }
|
48 |
|
49 | public refresh(params: any): boolean {
|
50 | return false;
|
51 | }
|
52 | }
|
53 |
|
54 | export class RowComp extends Component {
|
55 |
|
56 | public static DOM_DATA_KEY_RENDERED_ROW = 'renderedRow';
|
57 |
|
58 | private static FULL_WIDTH_CELL_RENDERER = 'fullWidthCellRenderer';
|
59 |
|
60 | private static GROUP_ROW_RENDERER = 'groupRowRenderer';
|
61 | private static GROUP_ROW_RENDERER_COMP_NAME = 'agGroupRowRenderer';
|
62 |
|
63 | private static LOADING_CELL_RENDERER = 'loadingCellRenderer';
|
64 | private static LOADING_CELL_RENDERER_COMP_NAME = 'agLoadingCellRenderer';
|
65 |
|
66 | private static DETAIL_CELL_RENDERER = 'detailCellRenderer';
|
67 | private static DETAIL_CELL_RENDERER_COMP_NAME = 'agDetailCellRenderer';
|
68 |
|
69 | private rowNode: RowNode;
|
70 |
|
71 | private beans: Beans;
|
72 |
|
73 | private ePinnedLeftRow: HTMLElement;
|
74 | private ePinnedRightRow: HTMLElement;
|
75 | private eBodyRow: HTMLElement;
|
76 | private eAllRowContainers: HTMLElement[] = [];
|
77 |
|
78 | private eFullWidthRow: HTMLElement;
|
79 | private eFullWidthRowBody: HTMLElement;
|
80 | private eFullWidthRowLeft: HTMLElement;
|
81 | private eFullWidthRowRight: HTMLElement;
|
82 |
|
83 | private bodyContainerComp: RowContainerComponent;
|
84 | private fullWidthContainerComp: RowContainerComponent;
|
85 | private pinnedLeftContainerComp: RowContainerComponent;
|
86 | private pinnedRightContainerComp: RowContainerComponent;
|
87 |
|
88 | private fullWidthRowComponent: ICellRendererComp;
|
89 | private fullWidthRowComponentBody: ICellRendererComp;
|
90 | private fullWidthRowComponentLeft: ICellRendererComp;
|
91 | private fullWidthRowComponentRight: ICellRendererComp;
|
92 |
|
93 | private active = true;
|
94 |
|
95 | private fullWidthRow: boolean;
|
96 | private fullWidthRowEmbedded: boolean;
|
97 |
|
98 | private editingRow: boolean;
|
99 | private rowFocused: boolean;
|
100 |
|
101 | private columnRefreshPending = false;
|
102 |
|
103 | private cellComps: {[key: string]: CellComp} = {};
|
104 |
|
105 |
|
106 |
|
107 |
|
108 | private createSecondPassFuncs: Function[] = [];
|
109 |
|
110 |
|
111 |
|
112 |
|
113 | private removeFirstPassFuncs: Function[] = [];
|
114 |
|
115 |
|
116 |
|
117 | private removeSecondPassFuncs: Function[] = [];
|
118 |
|
119 | private fadeRowIn: boolean;
|
120 | private slideRowIn: boolean;
|
121 | private useAnimationFrameForCreate: boolean;
|
122 |
|
123 | private rowIsEven: boolean;
|
124 |
|
125 | private paginationPage: number;
|
126 |
|
127 | private parentScope: any;
|
128 | private scope: any;
|
129 |
|
130 | private initialised = false;
|
131 |
|
132 | constructor(parentScope: any,
|
133 | bodyContainerComp: RowContainerComponent,
|
134 | pinnedLeftContainerComp: RowContainerComponent,
|
135 | pinnedRightContainerComp: RowContainerComponent,
|
136 | fullWidthContainerComp: RowContainerComponent,
|
137 | rowNode: RowNode,
|
138 | beans: Beans,
|
139 | animateIn: boolean,
|
140 | useAnimationFrameForCreate: boolean) {
|
141 | super();
|
142 | this.parentScope = parentScope;
|
143 | this.beans = beans;
|
144 | this.bodyContainerComp = bodyContainerComp;
|
145 | this.pinnedLeftContainerComp = pinnedLeftContainerComp;
|
146 | this.pinnedRightContainerComp = pinnedRightContainerComp;
|
147 | this.fullWidthContainerComp = fullWidthContainerComp;
|
148 | this.rowNode = rowNode;
|
149 | this.rowIsEven = this.rowNode.rowIndex % 2 === 0;
|
150 | this.paginationPage = this.beans.paginationProxy.getCurrentPage();
|
151 | this.useAnimationFrameForCreate = useAnimationFrameForCreate;
|
152 |
|
153 | this.setAnimateFlags(animateIn);
|
154 | }
|
155 |
|
156 | public init(): void {
|
157 | this.rowFocused = this.beans.focusedCellController.isRowFocused(this.rowNode.rowIndex, this.rowNode.rowPinned);
|
158 |
|
159 | this.scope = this.createChildScopeOrNull(this.rowNode.data);
|
160 |
|
161 | this.setupRowContainers();
|
162 |
|
163 | this.addListeners();
|
164 |
|
165 | if (this.slideRowIn) {
|
166 | this.createSecondPassFuncs.push( () => {
|
167 | this.onTopChanged();
|
168 | });
|
169 | }
|
170 | if (this.fadeRowIn) {
|
171 | this.createSecondPassFuncs.push( () => {
|
172 | this.eAllRowContainers.forEach(eRow => _.removeCssClass(eRow, 'ag-opacity-zero'));
|
173 | });
|
174 | }
|
175 | }
|
176 |
|
177 | private createTemplate(contents: string, extraCssClass: string = null): string {
|
178 | let templateParts: string[] = [];
|
179 |
|
180 | let rowHeight = this.rowNode.rowHeight;
|
181 | let rowClasses = this.getInitialRowClasses(extraCssClass).join(' ');
|
182 |
|
183 | let rowIdSanitised = _.escape(this.rowNode.id);
|
184 |
|
185 | let userRowStyles = this.preProcessStylesFromGridOptions();
|
186 |
|
187 | let businessKey = this.getRowBusinessKey();
|
188 | let businessKeySanitised = _.escape(businessKey);
|
189 |
|
190 | let rowTopStyle = this.getInitialRowTopStyle();
|
191 |
|
192 | templateParts.push(`<div`);
|
193 | templateParts.push(` role="row"`);
|
194 | templateParts.push(` row-index="${this.rowNode.getRowIndexString()}"`);
|
195 | templateParts.push(rowIdSanitised ? ` row-id="${rowIdSanitised}"` : ``);
|
196 | templateParts.push(businessKey ? ` row-business-key="${businessKeySanitised}"` : ``);
|
197 | templateParts.push(` comp-id="${this.getCompId()}"`);
|
198 | templateParts.push(` class="${rowClasses}"`);
|
199 | templateParts.push(` style="height: ${rowHeight}px; ${rowTopStyle} ${userRowStyles}">`);
|
200 |
|
201 |
|
202 | templateParts.push(contents);
|
203 |
|
204 | templateParts.push(`</div>`);
|
205 |
|
206 | return templateParts.join('');
|
207 | }
|
208 |
|
209 | public getCellForCol(column: Column): HTMLElement {
|
210 | let cellComp = this.cellComps[column.getColId()];
|
211 | if (cellComp) {
|
212 | return cellComp.getGui();
|
213 | } else {
|
214 | return null;
|
215 | }
|
216 | }
|
217 |
|
218 | public afterFlush(): void {
|
219 | if (!this.initialised) {
|
220 | this.initialised = true;
|
221 | this.executeProcessRowPostCreateFunc();
|
222 | }
|
223 | }
|
224 |
|
225 | private executeProcessRowPostCreateFunc(): void {
|
226 | let func = this.beans.gridOptionsWrapper.getProcessRowPostCreateFunc();
|
227 | if (func) {
|
228 | let params: ProcessRowParams = {
|
229 | eRow: this.eBodyRow,
|
230 | ePinnedLeftRow: this.ePinnedLeftRow,
|
231 | ePinnedRightRow: this.ePinnedRightRow,
|
232 | node: this.rowNode,
|
233 | api: this.beans.gridOptionsWrapper.getApi(),
|
234 | rowIndex: this.rowNode.rowIndex,
|
235 | addRenderedRowListener: this.addEventListener.bind(this),
|
236 | columnApi: this.beans.gridOptionsWrapper.getColumnApi(),
|
237 | context: this.beans.gridOptionsWrapper.getContext()
|
238 | };
|
239 | func(params);
|
240 | }
|
241 | }
|
242 |
|
243 | private getInitialRowTopStyle() {
|
244 |
|
245 | let pixels = this.slideRowIn ? this.roundRowTopToBounds(this.rowNode.oldRowTop) : this.rowNode.rowTop;
|
246 | let afterPaginationPixels = this.applyPaginationOffset(pixels);
|
247 | let afterScalingPixels = this.beans.heightScaler.getRealPixelPosition(afterPaginationPixels);
|
248 |
|
249 | if (this.beans.gridOptionsWrapper.isSuppressRowTransform()) {
|
250 | return `top: ${afterScalingPixels}px; `;
|
251 | } else {
|
252 | return `transform: translateY(${afterScalingPixels}px); `;
|
253 | }
|
254 | }
|
255 |
|
256 | private getRowBusinessKey(): string {
|
257 | if (typeof this.beans.gridOptionsWrapper.getBusinessKeyForNodeFunc() === 'function') {
|
258 | let businessKey = this.beans.gridOptionsWrapper.getBusinessKeyForNodeFunc()(this.rowNode);
|
259 | return businessKey;
|
260 | }
|
261 | }
|
262 |
|
263 | private lazyCreateCells(cols: Column[], eRow: HTMLElement): void {
|
264 | if (this.active) {
|
265 | let cellTemplatesAndComps = this.createCells(cols);
|
266 | eRow.innerHTML = cellTemplatesAndComps.template;
|
267 | this.callAfterRowAttachedOnCells(cellTemplatesAndComps.cellComps, eRow);
|
268 | }
|
269 | }
|
270 |
|
271 | private createRowContainer(rowContainerComp: RowContainerComponent, cols: Column[],
|
272 | callback: (eRow: HTMLElement) => void): void {
|
273 |
|
274 | let cellTemplatesAndComps: {template: string, cellComps: CellComp[]};
|
275 | if (this.useAnimationFrameForCreate) {
|
276 | cellTemplatesAndComps = {cellComps: [], template: ''};
|
277 | } else {
|
278 | cellTemplatesAndComps = this.createCells(cols);
|
279 | }
|
280 |
|
281 | let rowTemplate = this.createTemplate(cellTemplatesAndComps.template);
|
282 | rowContainerComp.appendRowTemplate(rowTemplate, ()=> {
|
283 | let eRow: HTMLElement = rowContainerComp.getRowElement(this.getCompId());
|
284 | this.afterRowAttached(rowContainerComp, eRow);
|
285 | callback(eRow);
|
286 |
|
287 | if (this.useAnimationFrameForCreate) {
|
288 | this.beans.taskQueue.addP1Task(this.lazyCreateCells.bind(this, cols, eRow));
|
289 | } else {
|
290 | this.callAfterRowAttachedOnCells(cellTemplatesAndComps.cellComps, eRow);
|
291 | }
|
292 | });
|
293 | }
|
294 |
|
295 | private createChildScopeOrNull(data: any) {
|
296 | if (this.beans.gridOptionsWrapper.isAngularCompileRows()) {
|
297 | let newChildScope = this.parentScope.$new();
|
298 | newChildScope.data = data;
|
299 | newChildScope.rowNode = this.rowNode;
|
300 | newChildScope.context = this.beans.gridOptionsWrapper.getContext();
|
301 |
|
302 | this.addDestroyFunc(() => {
|
303 | newChildScope.$destroy();
|
304 | newChildScope.data = null;
|
305 | newChildScope.rowNode = null;
|
306 | newChildScope.context = null;
|
307 | });
|
308 |
|
309 | return newChildScope;
|
310 | } else {
|
311 | return null;
|
312 | }
|
313 | }
|
314 |
|
315 | private setupRowContainers(): void {
|
316 |
|
317 | let isFullWidthCellFunc = this.beans.gridOptionsWrapper.getIsFullWidthCellFunc();
|
318 | let isFullWidthCell = isFullWidthCellFunc ? isFullWidthCellFunc(this.rowNode) : false;
|
319 |
|
320 | let isDetailCell = this.beans.doingMasterDetail && this.rowNode.detail;
|
321 |
|
322 | let isGroupSpanningRow = this.rowNode.group && this.beans.gridOptionsWrapper.isGroupUseEntireRow();
|
323 |
|
324 | if (this.rowNode.stub) {
|
325 | this.createFullWidthRows(RowComp.LOADING_CELL_RENDERER, RowComp.LOADING_CELL_RENDERER_COMP_NAME);
|
326 | } else if (isDetailCell) {
|
327 | this.createFullWidthRows(RowComp.DETAIL_CELL_RENDERER, RowComp.DETAIL_CELL_RENDERER_COMP_NAME);
|
328 | } else if (isFullWidthCell) {
|
329 | this.createFullWidthRows(RowComp.FULL_WIDTH_CELL_RENDERER, null);
|
330 | } else if (isGroupSpanningRow) {
|
331 | this.createFullWidthRows(RowComp.GROUP_ROW_RENDERER, RowComp.GROUP_ROW_RENDERER_COMP_NAME);
|
332 | } else {
|
333 | this.setupNormalRowContainers();
|
334 | }
|
335 | }
|
336 |
|
337 | private setupNormalRowContainers(): void {
|
338 | let centerCols = this.beans.columnController.getAllDisplayedCenterVirtualColumnsForRow(this.rowNode);
|
339 | this.createRowContainer(this.bodyContainerComp, centerCols, eRow => this.eBodyRow = eRow);
|
340 |
|
341 | let leftCols = this.beans.columnController.getDisplayedLeftColumnsForRow(this.rowNode);
|
342 | let rightCols = this.beans.columnController.getDisplayedRightColumnsForRow(this.rowNode);
|
343 | this.createRowContainer(this.pinnedRightContainerComp, rightCols, eRow => this.ePinnedRightRow = eRow);
|
344 | this.createRowContainer(this.pinnedLeftContainerComp, leftCols, eRow => this.ePinnedLeftRow = eRow);
|
345 | }
|
346 |
|
347 | private createFullWidthRows(type: string, name: string): void {
|
348 |
|
349 | this.fullWidthRow = true;
|
350 | this.fullWidthRowEmbedded = this.beans.gridOptionsWrapper.isEmbedFullWidthRows();
|
351 |
|
352 | if (this.fullWidthRowEmbedded) {
|
353 |
|
354 | this.createFullWidthRowContainer(this.bodyContainerComp, null,
|
355 | null, type, name,
|
356 | (eRow: HTMLElement) => {
|
357 | this.eFullWidthRowBody = eRow;
|
358 | },
|
359 | (cellRenderer: ICellRendererComp) => {
|
360 | this.fullWidthRowComponentBody = cellRenderer;
|
361 | });
|
362 | this.createFullWidthRowContainer(this.pinnedLeftContainerComp, Column.PINNED_LEFT,
|
363 | 'ag-cell-last-left-pinned', type, name,
|
364 | (eRow: HTMLElement) => {
|
365 | this.eFullWidthRowLeft = eRow;
|
366 | },
|
367 | (cellRenderer: ICellRendererComp) => {
|
368 | this.fullWidthRowComponentLeft = cellRenderer;
|
369 | });
|
370 | this.createFullWidthRowContainer(this.pinnedRightContainerComp, Column.PINNED_RIGHT,
|
371 | 'ag-cell-first-right-pinned', type, name,
|
372 | (eRow: HTMLElement) => {
|
373 | this.eFullWidthRowRight = eRow;
|
374 | },
|
375 | (cellRenderer: ICellRendererComp) => {
|
376 | this.fullWidthRowComponentRight = cellRenderer;
|
377 | });
|
378 |
|
379 | } else {
|
380 |
|
381 |
|
382 |
|
383 | this.createFullWidthRowContainer(this.fullWidthContainerComp, null,
|
384 | null, type, name,
|
385 | (eRow: HTMLElement) => {
|
386 | this.eFullWidthRow = eRow;
|
387 | },
|
388 | (cellRenderer: ICellRendererComp) => {
|
389 | this.fullWidthRowComponent = cellRenderer;
|
390 | });
|
391 | }
|
392 | }
|
393 |
|
394 | private setAnimateFlags(animateIn: boolean): void {
|
395 | if (animateIn) {
|
396 | let oldRowTopExists = _.exists(this.rowNode.oldRowTop);
|
397 |
|
398 | this.slideRowIn = oldRowTopExists;
|
399 |
|
400 | this.fadeRowIn = !oldRowTopExists;
|
401 | } else {
|
402 | this.slideRowIn = false;
|
403 | this.fadeRowIn = false;
|
404 | }
|
405 | }
|
406 |
|
407 | public isEditing(): boolean {
|
408 | return this.editingRow;
|
409 | }
|
410 |
|
411 | public stopRowEditing(cancel: boolean): void {
|
412 | this.stopEditing(cancel);
|
413 | }
|
414 |
|
415 | public isFullWidth(): boolean {
|
416 | return this.fullWidthRow;
|
417 | }
|
418 |
|
419 | private addListeners(): void {
|
420 | this.addDestroyableEventListener(this.rowNode, RowNode.EVENT_HEIGHT_CHANGED, this.onRowHeightChanged.bind(this));
|
421 | this.addDestroyableEventListener(this.rowNode, RowNode.EVENT_ROW_SELECTED, this.onRowSelected.bind(this));
|
422 | this.addDestroyableEventListener(this.rowNode, RowNode.EVENT_ROW_INDEX_CHANGED, this.onRowIndexChanged.bind(this));
|
423 | this.addDestroyableEventListener(this.rowNode, RowNode.EVENT_TOP_CHANGED, this.onTopChanged.bind(this));
|
424 | this.addDestroyableEventListener(this.rowNode, RowNode.EVENT_EXPANDED_CHANGED, this.onExpandedChanged.bind(this));
|
425 | this.addDestroyableEventListener(this.rowNode, RowNode.EVENT_DATA_CHANGED, this.onRowNodeDataChanged.bind(this));
|
426 | this.addDestroyableEventListener(this.rowNode, RowNode.EVENT_CELL_CHANGED, this.onRowNodeCellChanged.bind(this));
|
427 | this.addDestroyableEventListener(this.rowNode, RowNode.EVENT_DRAGGING_CHANGED, this.onRowNodeDraggingChanged.bind(this));
|
428 |
|
429 | let eventService = this.beans.eventService;
|
430 | this.addDestroyableEventListener(eventService, Events.EVENT_HEIGHT_SCALE_CHANGED, this.onTopChanged.bind(this));
|
431 | this.addDestroyableEventListener(eventService, Events.EVENT_DISPLAYED_COLUMNS_CHANGED, this.onDisplayedColumnsChanged.bind(this));
|
432 | this.addDestroyableEventListener(eventService, Events.EVENT_VIRTUAL_COLUMNS_CHANGED, this.onVirtualColumnsChanged.bind(this));
|
433 | this.addDestroyableEventListener(eventService, Events.EVENT_COLUMN_RESIZED, this.onColumnResized.bind(this));
|
434 | this.addDestroyableEventListener(eventService, Events.EVENT_CELL_FOCUSED, this.onCellFocusChanged.bind(this));
|
435 | this.addDestroyableEventListener(eventService, Events.EVENT_PAGINATION_CHANGED, this.onPaginationChanged.bind(this));
|
436 | this.addDestroyableEventListener(eventService, Events.EVENT_GRID_COLUMNS_CHANGED, this.onGridColumnsChanged.bind(this));
|
437 | }
|
438 |
|
439 |
|
440 |
|
441 | private onGridColumnsChanged(): void {
|
442 | let allRenderedCellIds = Object.keys(this.cellComps);
|
443 | this.removeRenderedCells(allRenderedCellIds);
|
444 | }
|
445 |
|
446 | private onRowNodeDataChanged(event: DataChangedEvent): void {
|
447 |
|
448 |
|
449 |
|
450 | this.forEachCellComp(cellComp =>
|
451 | cellComp.refreshCell({
|
452 | suppressFlash: !event.update,
|
453 | newData: !event.update
|
454 | })
|
455 | );
|
456 |
|
457 |
|
458 |
|
459 |
|
460 |
|
461 |
|
462 | this.onRowSelected();
|
463 |
|
464 |
|
465 | this.postProcessCss();
|
466 | }
|
467 |
|
468 | private onRowNodeCellChanged(event: CellChangedEvent): void {
|
469 |
|
470 | this.postProcessCss();
|
471 | }
|
472 |
|
473 | private postProcessCss(): void {
|
474 | this.postProcessStylesFromGridOptions();
|
475 | this.postProcessClassesFromGridOptions();
|
476 | this.postProcessRowClassRules();
|
477 | this.postProcessRowDragging();
|
478 | }
|
479 |
|
480 | private onRowNodeDraggingChanged(): void {
|
481 | this.postProcessRowDragging();
|
482 | }
|
483 |
|
484 | private postProcessRowDragging(): void {
|
485 | let dragging = this.rowNode.dragging;
|
486 | this.eAllRowContainers.forEach( (row) => _.addOrRemoveCssClass(row, 'ag-row-dragging', dragging) );
|
487 | }
|
488 |
|
489 | private onExpandedChanged(): void {
|
490 | if (this.rowNode.group && !this.rowNode.footer) {
|
491 | let expanded = this.rowNode.expanded;
|
492 | this.eAllRowContainers.forEach( row => _.addOrRemoveCssClass(row, 'ag-row-group-expanded', expanded));
|
493 | this.eAllRowContainers.forEach( row => _.addOrRemoveCssClass(row, 'ag-row-group-contracted', !expanded));
|
494 | }
|
495 | }
|
496 |
|
497 | private onDisplayedColumnsChanged(): void {
|
498 | if (!this.fullWidthRow) {
|
499 | this.refreshCells();
|
500 | }
|
501 | }
|
502 |
|
503 | private destroyFullWidthComponents(): void {
|
504 | if (this.fullWidthRowComponent) {
|
505 | if (this.fullWidthRowComponent.destroy) {
|
506 | this.fullWidthRowComponent.destroy();
|
507 | }
|
508 | this.fullWidthRowComponent = null;
|
509 | }
|
510 | if (this.fullWidthRowComponentBody) {
|
511 | if (this.fullWidthRowComponentBody.destroy) {
|
512 | this.fullWidthRowComponentBody.destroy();
|
513 | }
|
514 | this.fullWidthRowComponent = null;
|
515 | }
|
516 | if (this.fullWidthRowComponentLeft) {
|
517 | if (this.fullWidthRowComponentLeft.destroy) {
|
518 | this.fullWidthRowComponentLeft.destroy();
|
519 | }
|
520 | this.fullWidthRowComponentLeft = null;
|
521 | }
|
522 | if (this.fullWidthRowComponentRight) {
|
523 | if (this.fullWidthRowComponentRight.destroy) {
|
524 | this.fullWidthRowComponentRight.destroy();
|
525 | }
|
526 | this.fullWidthRowComponent = null;
|
527 | }
|
528 | }
|
529 |
|
530 | private getContainerForCell(pinnedType: string): HTMLElement {
|
531 | switch (pinnedType) {
|
532 | case Column.PINNED_LEFT: return this.ePinnedLeftRow;
|
533 | case Column.PINNED_RIGHT: return this.ePinnedRightRow;
|
534 | default: return this.eBodyRow;
|
535 | }
|
536 | }
|
537 |
|
538 | private onVirtualColumnsChanged(): void {
|
539 | if (!this.fullWidthRow) {
|
540 | this.refreshCells();
|
541 | }
|
542 | }
|
543 |
|
544 | private onColumnResized(): void {
|
545 | if (!this.fullWidthRow) {
|
546 | this.refreshCells();
|
547 | }
|
548 | }
|
549 |
|
550 | private refreshCells() {
|
551 | if (this.beans.gridOptionsWrapper.isSuppressAnimationFrame()) {
|
552 | this.refreshCellsInAnimationFrame();
|
553 | } else {
|
554 | if (this.columnRefreshPending) { return; }
|
555 | this.beans.taskQueue.addP1Task(this.refreshCellsInAnimationFrame.bind(this));
|
556 | }
|
557 | }
|
558 |
|
559 | private refreshCellsInAnimationFrame() {
|
560 |
|
561 | if (!this.active) { return; }
|
562 | this.columnRefreshPending = false;
|
563 |
|
564 | let centerCols = this.beans.columnController.getAllDisplayedCenterVirtualColumnsForRow(this.rowNode);
|
565 | let leftCols = this.beans.columnController.getDisplayedLeftColumnsForRow(this.rowNode);
|
566 | let rightCols = this.beans.columnController.getDisplayedRightColumnsForRow(this.rowNode);
|
567 |
|
568 | this.insertCellsIntoContainer(this.eBodyRow, centerCols);
|
569 | this.insertCellsIntoContainer(this.ePinnedLeftRow, leftCols);
|
570 | this.insertCellsIntoContainer(this.ePinnedRightRow, rightCols);
|
571 |
|
572 | let colIdsToRemove = Object.keys(this.cellComps);
|
573 | centerCols.forEach( (col: Column) => _.removeFromArray(colIdsToRemove, col.getId()));
|
574 | leftCols.forEach( (col: Column) => _.removeFromArray(colIdsToRemove, col.getId()));
|
575 | rightCols.forEach( (col: Column) => _.removeFromArray(colIdsToRemove, col.getId()));
|
576 |
|
577 |
|
578 |
|
579 | colIdsToRemove = _.filter(colIdsToRemove, this.isCellEligibleToBeRemoved.bind(this));
|
580 |
|
581 |
|
582 | this.removeRenderedCells(colIdsToRemove);
|
583 | }
|
584 |
|
585 | private removeRenderedCells(colIds: string[]): void {
|
586 | colIds.forEach( (key: string)=> {
|
587 | let cellComp = this.cellComps[key];
|
588 |
|
589 | if (_.missing(cellComp)) { return; }
|
590 |
|
591 | cellComp.detach();
|
592 | cellComp.destroy();
|
593 | this.cellComps[key] = null;
|
594 | });
|
595 | }
|
596 |
|
597 | private isCellEligibleToBeRemoved(indexStr: string): boolean {
|
598 | let displayedColumns = this.beans.columnController.getAllDisplayedColumns();
|
599 |
|
600 | let REMOVE_CELL: boolean = true;
|
601 | let KEEP_CELL: boolean = false;
|
602 | let renderedCell = this.cellComps[indexStr];
|
603 |
|
604 | if (!renderedCell) { return REMOVE_CELL; }
|
605 |
|
606 |
|
607 | if (this.isCellInWrongRow(renderedCell)) { return REMOVE_CELL; }
|
608 |
|
609 |
|
610 | let editing = renderedCell.isEditing();
|
611 | let focused = this.beans.focusedCellController.isCellFocused(renderedCell.getGridCell());
|
612 |
|
613 | let mightWantToKeepCell = editing || focused;
|
614 |
|
615 | if (mightWantToKeepCell) {
|
616 | let column = renderedCell.getColumn();
|
617 | let cellStillDisplayed = displayedColumns.indexOf(column) >= 0;
|
618 | return cellStillDisplayed ? KEEP_CELL : REMOVE_CELL;
|
619 | } else {
|
620 | return REMOVE_CELL;
|
621 | }
|
622 | }
|
623 |
|
624 | private ensureCellInCorrectContainer(cellComp: CellComp): void {
|
625 | let element = cellComp.getGui();
|
626 | let column = cellComp.getColumn();
|
627 | let pinnedType = column.getPinned();
|
628 | let eContainer = this.getContainerForCell(pinnedType);
|
629 |
|
630 |
|
631 | let eOldContainer = cellComp.getParentRow();
|
632 | let inWrongRow = eOldContainer !== eContainer;
|
633 | if (inWrongRow) {
|
634 |
|
635 | if (eOldContainer) {
|
636 | eOldContainer.removeChild(element);
|
637 | }
|
638 |
|
639 | eContainer.appendChild(element);
|
640 | cellComp.setParentRow(eContainer);
|
641 | }
|
642 | }
|
643 |
|
644 | private isCellInWrongRow(cellComp: CellComp): boolean {
|
645 | let column = cellComp.getColumn();
|
646 | let rowWeWant = this.getContainerForCell(column.getPinned());
|
647 |
|
648 |
|
649 | let oldRow = cellComp.getParentRow();
|
650 | return oldRow !== rowWeWant;
|
651 | }
|
652 |
|
653 | private insertCellsIntoContainer(eRow: HTMLElement, cols: Column[]): void {
|
654 | if (!eRow) { return; }
|
655 |
|
656 | let cellTemplates: string[] = [];
|
657 | let newCellComps: CellComp[] = [];
|
658 |
|
659 | cols.forEach( col => {
|
660 |
|
661 | let colId = col.getId();
|
662 | let oldCell = this.cellComps[colId];
|
663 |
|
664 | if (oldCell) {
|
665 | this.ensureCellInCorrectContainer(oldCell);
|
666 | } else {
|
667 | this.createNewCell(col, eRow, cellTemplates, newCellComps);
|
668 | }
|
669 |
|
670 | });
|
671 |
|
672 | if (cellTemplates.length>0) {
|
673 | _.appendHtml(eRow, cellTemplates.join(''));
|
674 | this.callAfterRowAttachedOnCells(newCellComps, eRow);
|
675 | }
|
676 | }
|
677 |
|
678 | private addDomData(eRowContainer: Element): void {
|
679 | let gow = this.beans.gridOptionsWrapper;
|
680 | gow.setDomData(eRowContainer, RowComp.DOM_DATA_KEY_RENDERED_ROW, this);
|
681 | this.addDestroyFunc( ()=> {
|
682 | gow.setDomData(eRowContainer, RowComp.DOM_DATA_KEY_RENDERED_ROW, null); }
|
683 | );
|
684 | }
|
685 |
|
686 | private createNewCell(col: Column, eContainer: HTMLElement, cellTemplates: string[], newCellComps: CellComp[]): void {
|
687 | let newCellComp = new CellComp(this.scope, this.beans, col, this.rowNode, this, false);
|
688 | let cellTemplate = newCellComp.getCreateTemplate();
|
689 | cellTemplates.push(cellTemplate);
|
690 | newCellComps.push(newCellComp);
|
691 | this.cellComps[col.getId()] = newCellComp;
|
692 | newCellComp.setParentRow(eContainer);
|
693 | }
|
694 |
|
695 | public onMouseEvent(eventName: string, mouseEvent: MouseEvent): void {
|
696 | switch (eventName) {
|
697 | case 'dblclick': this.onRowDblClick(mouseEvent); break;
|
698 | case 'click': this.onRowClick(mouseEvent); break;
|
699 | }
|
700 | }
|
701 |
|
702 | private createRowEvent(type: string, domEvent?: Event): RowEvent {
|
703 | return {
|
704 | type: type,
|
705 | node: this.rowNode,
|
706 | data: this.rowNode.data,
|
707 | rowIndex: this.rowNode.rowIndex,
|
708 | rowPinned: this.rowNode.rowPinned,
|
709 | context: this.beans.gridOptionsWrapper.getContext(),
|
710 | api: this.beans.gridOptionsWrapper.getApi(),
|
711 | columnApi: this.beans.gridOptionsWrapper.getColumnApi(),
|
712 | event: domEvent
|
713 | };
|
714 | }
|
715 |
|
716 | private createRowEventWithSource(type: string, domEvent: Event): RowEvent {
|
717 | let event = this.createRowEvent(type, domEvent);
|
718 |
|
719 |
|
720 |
|
721 |
|
722 |
|
723 |
|
724 | (<any>event).source = this;
|
725 | return event;
|
726 | }
|
727 |
|
728 | private onRowDblClick(mouseEvent: MouseEvent): void {
|
729 | if (_.isStopPropagationForAgGrid(mouseEvent)) { return; }
|
730 |
|
731 | let agEvent: RowDoubleClickedEvent = this.createRowEventWithSource(Events.EVENT_ROW_DOUBLE_CLICKED, mouseEvent);
|
732 |
|
733 | this.beans.eventService.dispatchEvent(agEvent);
|
734 | }
|
735 |
|
736 | public onRowClick(mouseEvent: MouseEvent) {
|
737 |
|
738 | let stop = _.isStopPropagationForAgGrid(mouseEvent);
|
739 | if (stop) {
|
740 | return;
|
741 | }
|
742 |
|
743 | let agEvent: RowClickedEvent = this.createRowEventWithSource(Events.EVENT_ROW_CLICKED, mouseEvent);
|
744 |
|
745 | this.beans.eventService.dispatchEvent(agEvent);
|
746 |
|
747 |
|
748 | let multiSelectKeyPressed = mouseEvent.ctrlKey || mouseEvent.metaKey;
|
749 |
|
750 | let shiftKeyPressed = mouseEvent.shiftKey;
|
751 |
|
752 |
|
753 |
|
754 | if (this.rowNode.group) {
|
755 | return;
|
756 | }
|
757 |
|
758 |
|
759 | if (this.rowNode.rowPinned) {
|
760 | return;
|
761 | }
|
762 |
|
763 |
|
764 | if (!this.beans.gridOptionsWrapper.isRowSelection()) {
|
765 | return;
|
766 | }
|
767 |
|
768 |
|
769 | if (this.beans.gridOptionsWrapper.isSuppressRowClickSelection()) {
|
770 | return;
|
771 | }
|
772 |
|
773 | let multiSelectOnClick = this.beans.gridOptionsWrapper.isRowMultiSelectWithClick();
|
774 | let rowDeselectionWithCtrl = this.beans.gridOptionsWrapper.isRowDeselection();
|
775 |
|
776 | if (this.rowNode.isSelected()) {
|
777 |
|
778 | if (multiSelectOnClick) {
|
779 | this.rowNode.setSelectedParams({newValue: false});
|
780 | } else if (multiSelectKeyPressed) {
|
781 | if (rowDeselectionWithCtrl) {
|
782 | this.rowNode.setSelectedParams({newValue: false});
|
783 | }
|
784 | } else {
|
785 |
|
786 | this.rowNode.setSelectedParams({newValue: true, clearSelection: true});
|
787 | }
|
788 | } else {
|
789 | let clearSelection = multiSelectOnClick ? false : !multiSelectKeyPressed;
|
790 | this.rowNode.setSelectedParams({newValue: true, clearSelection: clearSelection, rangeSelect: shiftKeyPressed});
|
791 | }
|
792 | }
|
793 |
|
794 | private createFullWidthRowContainer(rowContainerComp: RowContainerComponent, pinned: string,
|
795 | extraCssClass: string, cellRendererType: string, cellRendererName: string,
|
796 | eRowCallback: (eRow: HTMLElement) => void,
|
797 | cellRendererCallback: (comp: ICellRendererComp) => void): void {
|
798 |
|
799 | let rowTemplate = this.createTemplate('', extraCssClass);
|
800 | rowContainerComp.appendRowTemplate(rowTemplate, ()=> {
|
801 |
|
802 | let eRow: HTMLElement = rowContainerComp.getRowElement(this.getCompId());
|
803 |
|
804 | let params = this.createFullWidthParams(eRow, pinned);
|
805 |
|
806 | let callback = (cellRenderer: ICellRendererComp)=> {
|
807 | if (this.isAlive()) {
|
808 | let gui = cellRenderer.getGui();
|
809 | eRow.appendChild(gui);
|
810 | cellRendererCallback(cellRenderer);
|
811 | } else {
|
812 | if (cellRenderer.destroy) {
|
813 | cellRenderer.destroy();
|
814 | }
|
815 | }
|
816 | };
|
817 |
|
818 | this.beans.componentResolver.createAgGridComponent<ICellRendererComp>(null, params, cellRendererType, params, cellRendererName).then(callback);
|
819 |
|
820 | this.afterRowAttached(rowContainerComp, eRow);
|
821 | eRowCallback(eRow);
|
822 |
|
823 | this.angular1Compile(eRow);
|
824 | });
|
825 | }
|
826 |
|
827 | private angular1Compile(element: Element): void {
|
828 | if (this.scope) {
|
829 | this.beans.$compile(element)(this.scope);
|
830 | }
|
831 | }
|
832 |
|
833 | private createFullWidthParams(eRow: HTMLElement, pinned: string): any {
|
834 | let params = {
|
835 | fullWidth: true,
|
836 | data: this.rowNode.data,
|
837 | node: this.rowNode,
|
838 | value: this.rowNode.key,
|
839 | $scope: this.scope,
|
840 | rowIndex: this.rowNode.rowIndex,
|
841 | api: this.beans.gridOptionsWrapper.getApi(),
|
842 | columnApi: this.beans.gridOptionsWrapper.getColumnApi(),
|
843 | context: this.beans.gridOptionsWrapper.getContext(),
|
844 |
|
845 | eGridCell: eRow,
|
846 | eParentOfValue: eRow,
|
847 | pinned: pinned,
|
848 | addRenderedRowListener: this.addEventListener.bind(this)
|
849 | };
|
850 |
|
851 | return params;
|
852 | }
|
853 |
|
854 | private getInitialRowClasses(extraCssClass: string): string[] {
|
855 | let classes: string[] = [];
|
856 |
|
857 | if (_.exists(extraCssClass)) {
|
858 | classes.push(extraCssClass);
|
859 | }
|
860 |
|
861 | classes.push('ag-row');
|
862 | classes.push(this.rowFocused ? 'ag-row-focus' : 'ag-row-no-focus');
|
863 |
|
864 | if (this.fadeRowIn) {
|
865 | classes.push('ag-opacity-zero');
|
866 | }
|
867 |
|
868 | if (this.rowIsEven) {
|
869 | classes.push('ag-row-even');
|
870 | } else {
|
871 | classes.push('ag-row-odd');
|
872 | }
|
873 |
|
874 | if (this.rowNode.isSelected()) {
|
875 | classes.push('ag-row-selected');
|
876 | }
|
877 |
|
878 | if (this.rowNode.group) {
|
879 | classes.push('ag-row-group');
|
880 |
|
881 | classes.push('ag-row-level-' + this.rowNode.level);
|
882 |
|
883 | if (this.rowNode.footer) {
|
884 | classes.push('ag-row-footer');
|
885 | }
|
886 | } else {
|
887 |
|
888 | if (this.rowNode.parent) {
|
889 | classes.push('ag-row-level-' + (this.rowNode.parent.level + 1));
|
890 | } else {
|
891 | classes.push('ag-row-level-0');
|
892 | }
|
893 | }
|
894 |
|
895 | if (this.rowNode.stub) {
|
896 | classes.push('ag-row-stub');
|
897 | }
|
898 |
|
899 | if (this.fullWidthRow) {
|
900 | classes.push('ag-full-width-row');
|
901 | }
|
902 |
|
903 | if (this.rowNode.group && !this.rowNode.footer) {
|
904 | classes.push(this.rowNode.expanded ? 'ag-row-group-expanded' : 'ag-row-group-contracted');
|
905 | }
|
906 |
|
907 | if (this.rowNode.dragging) {
|
908 | classes.push('ag-row-dragging');
|
909 | }
|
910 |
|
911 | _.pushAll(classes, this.processClassesFromGridOptions());
|
912 | _.pushAll(classes, this.preProcessRowClassRules());
|
913 |
|
914 | return classes;
|
915 | }
|
916 |
|
917 | private preProcessRowClassRules(): string[] {
|
918 | let res: string[] = [];
|
919 |
|
920 | this.processRowClassRules(
|
921 | (className: string)=> {
|
922 | res.push(className);
|
923 | },
|
924 | (className: string)=> {
|
925 |
|
926 |
|
927 | }
|
928 | );
|
929 |
|
930 | return res;
|
931 | }
|
932 |
|
933 | private processRowClassRules(onApplicableClass: (className: string)=>void, onNotApplicableClass?: (className: string)=>void): void {
|
934 | this.beans.stylingService.processClassRules(
|
935 | this.beans.gridOptionsWrapper.rowClassRules(),
|
936 | {
|
937 | value: undefined,
|
938 | colDef:undefined,
|
939 | data: this.rowNode.data,
|
940 | node: this.rowNode,
|
941 | rowIndex: this.rowNode.rowIndex,
|
942 | api: this.beans.gridOptionsWrapper.getApi(),
|
943 | $scope: this.scope,
|
944 | context: this.beans.gridOptionsWrapper.getContext()
|
945 | }, onApplicableClass, onNotApplicableClass);
|
946 | }
|
947 |
|
948 | public stopEditing(cancel = false): void {
|
949 | this.forEachCellComp(renderedCell => {
|
950 | renderedCell.stopEditing(cancel);
|
951 | });
|
952 | if (this.editingRow) {
|
953 | if (!cancel) {
|
954 | let event: RowValueChangedEvent = this.createRowEvent(Events.EVENT_ROW_VALUE_CHANGED);
|
955 | this.beans.eventService.dispatchEvent(event);
|
956 | }
|
957 | this.setEditingRow(false);
|
958 | }
|
959 | }
|
960 |
|
961 | private setEditingRow(value: boolean): void {
|
962 | this.editingRow = value;
|
963 | this.eAllRowContainers.forEach( (row) => _.addOrRemoveCssClass(row, 'ag-row-editing', value) );
|
964 |
|
965 | let event: RowEvent = value ?
|
966 | <RowEditingStartedEvent> this.createRowEvent(Events.EVENT_ROW_EDITING_STARTED)
|
967 | : <RowEditingStoppedEvent> this.createRowEvent(Events.EVENT_ROW_EDITING_STOPPED);
|
968 |
|
969 | this.beans.eventService.dispatchEvent(event);
|
970 | }
|
971 |
|
972 | public startRowEditing(keyPress: number = null, charPress: string = null, sourceRenderedCell: CellComp = null): void {
|
973 |
|
974 | if (this.editingRow) { return; }
|
975 |
|
976 | this.forEachCellComp(renderedCell => {
|
977 | let cellStartedEdit = renderedCell === sourceRenderedCell;
|
978 | if (cellStartedEdit) {
|
979 | renderedCell.startEditingIfEnabled(keyPress, charPress, cellStartedEdit);
|
980 | } else {
|
981 | renderedCell.startEditingIfEnabled(null, null, cellStartedEdit);
|
982 | }
|
983 | });
|
984 | this.setEditingRow(true);
|
985 | }
|
986 |
|
987 | public forEachCellComp(callback: (renderedCell: CellComp)=>void): void {
|
988 | _.iterateObject(this.cellComps, (key: any, cellComp: CellComp)=> {
|
989 | if (cellComp) {
|
990 | callback(cellComp);
|
991 | }
|
992 | });
|
993 | }
|
994 |
|
995 | private postProcessClassesFromGridOptions(): void {
|
996 | let cssClasses = this.processClassesFromGridOptions();
|
997 | if (cssClasses) {
|
998 | cssClasses.forEach( (classStr: string) => {
|
999 | this.eAllRowContainers.forEach( row => _.addCssClass(row, classStr));
|
1000 | });
|
1001 | }
|
1002 | }
|
1003 |
|
1004 | private postProcessRowClassRules(): void {
|
1005 | this.processRowClassRules(
|
1006 | (className: string)=> {
|
1007 | this.eAllRowContainers.forEach( row => _.addCssClass(row, className));
|
1008 | },
|
1009 | (className: string)=> {
|
1010 | this.eAllRowContainers.forEach( row => _.removeCssClass(row, className));
|
1011 | }
|
1012 | );
|
1013 | }
|
1014 |
|
1015 | private processClassesFromGridOptions(): string[] {
|
1016 | let res: string[] = [];
|
1017 |
|
1018 | let process = (rowClass: string | string[]) => {
|
1019 | if (typeof rowClass === 'string') {
|
1020 | res.push(rowClass);
|
1021 | } else if (Array.isArray(rowClass)) {
|
1022 | rowClass.forEach( e => res.push(e) );
|
1023 | }
|
1024 | };
|
1025 |
|
1026 |
|
1027 | let rowClass = this.beans.gridOptionsWrapper.getRowClass();
|
1028 | if (rowClass) {
|
1029 | if (typeof rowClass === 'function') {
|
1030 | console.warn('ag-Grid: rowClass should not be a function, please use getRowClass instead');
|
1031 | return;
|
1032 | }
|
1033 | process(rowClass);
|
1034 | }
|
1035 |
|
1036 |
|
1037 | let rowClassFunc = this.beans.gridOptionsWrapper.getRowClassFunc();
|
1038 | if (rowClassFunc) {
|
1039 | let params = {
|
1040 | node: this.rowNode,
|
1041 | data: this.rowNode.data,
|
1042 | rowIndex: this.rowNode.rowIndex,
|
1043 | context: this.beans.gridOptionsWrapper.getContext(),
|
1044 | api: this.beans.gridOptionsWrapper.getApi()
|
1045 | };
|
1046 | let rowClassFuncResult = rowClassFunc(params);
|
1047 | process(rowClassFuncResult);
|
1048 | }
|
1049 |
|
1050 | return res;
|
1051 | }
|
1052 |
|
1053 | private preProcessStylesFromGridOptions(): string {
|
1054 | let rowStyles = this.processStylesFromGridOptions();
|
1055 | return _.cssStyleObjectToMarkup(rowStyles);
|
1056 | }
|
1057 |
|
1058 | private postProcessStylesFromGridOptions(): void {
|
1059 | let rowStyles = this.processStylesFromGridOptions();
|
1060 | this.eAllRowContainers.forEach( row => _.addStylesToElement(row, rowStyles));
|
1061 | }
|
1062 |
|
1063 | private processStylesFromGridOptions(): any {
|
1064 |
|
1065 |
|
1066 | let rowStyle = this.beans.gridOptionsWrapper.getRowStyle();
|
1067 |
|
1068 | if (rowStyle && typeof rowStyle === 'function') {
|
1069 | console.log('ag-Grid: rowStyle should be an object of key/value styles, not be a function, use getRowStyle() instead');
|
1070 | return;
|
1071 | }
|
1072 |
|
1073 |
|
1074 | let rowStyleFunc = this.beans.gridOptionsWrapper.getRowStyleFunc();
|
1075 | let rowStyleFuncResult: any;
|
1076 | if (rowStyleFunc) {
|
1077 | let params = {
|
1078 | data: this.rowNode.data,
|
1079 | node: this.rowNode,
|
1080 | api: this.beans.gridOptionsWrapper.getApi(),
|
1081 | context: this.beans.gridOptionsWrapper.getContext(),
|
1082 | $scope: this.scope
|
1083 | };
|
1084 | rowStyleFuncResult = rowStyleFunc(params);
|
1085 | }
|
1086 |
|
1087 | return _.assign({}, rowStyle, rowStyleFuncResult);
|
1088 | }
|
1089 |
|
1090 | private createCells(cols: Column[]): {template: string, cellComps: CellComp[]} {
|
1091 | let templateParts: string[] = [];
|
1092 | let newCellComps: CellComp[] = [];
|
1093 | cols.forEach( col => {
|
1094 | let newCellComp = new CellComp(this.scope, this.beans, col, this.rowNode, this, false);
|
1095 | let cellTemplate = newCellComp.getCreateTemplate();
|
1096 | templateParts.push(cellTemplate);
|
1097 | newCellComps.push(newCellComp);
|
1098 | this.cellComps[col.getId()] = newCellComp;
|
1099 | });
|
1100 | let templateAndComps = {
|
1101 | template: templateParts.join(''),
|
1102 | cellComps: newCellComps
|
1103 | };
|
1104 | return templateAndComps;
|
1105 | }
|
1106 |
|
1107 | private onRowSelected(): void {
|
1108 | let selected = this.rowNode.isSelected();
|
1109 | this.eAllRowContainers.forEach( (row) => _.addOrRemoveCssClass(row, 'ag-row-selected', selected) );
|
1110 | }
|
1111 |
|
1112 |
|
1113 |
|
1114 |
|
1115 | private callAfterRowAttachedOnCells(newCellComps: CellComp[], eRow: HTMLElement): void {
|
1116 | newCellComps.forEach( cellComp => {
|
1117 | cellComp.setParentRow(eRow);
|
1118 | cellComp.afterAttached();
|
1119 |
|
1120 |
|
1121 |
|
1122 | if (this.editingRow) {
|
1123 | cellComp.startEditingIfEnabled();
|
1124 | }
|
1125 | });
|
1126 | }
|
1127 |
|
1128 | private afterRowAttached(rowContainerComp: RowContainerComponent, eRow: HTMLElement): void {
|
1129 |
|
1130 | this.addDomData(eRow);
|
1131 |
|
1132 | this.removeSecondPassFuncs.push( ()=> {
|
1133 |
|
1134 | rowContainerComp.removeRowElement(eRow);
|
1135 | });
|
1136 | this.removeFirstPassFuncs.push( ()=> {
|
1137 | if (_.exists(this.rowNode.rowTop)) {
|
1138 |
|
1139 |
|
1140 |
|
1141 |
|
1142 | let rowTop = this.roundRowTopToBounds(this.rowNode.rowTop);
|
1143 | this.setRowTop(rowTop);
|
1144 | } else {
|
1145 | _.addCssClass(eRow, 'ag-opacity-zero');
|
1146 | }
|
1147 | });
|
1148 |
|
1149 | this.eAllRowContainers.push(eRow);
|
1150 |
|
1151 |
|
1152 |
|
1153 | if (this.useAnimationFrameForCreate) {
|
1154 | this.beans.taskQueue.addP1Task(this.addHoverFunctionality.bind(this, eRow));
|
1155 | } else {
|
1156 | this.addHoverFunctionality(eRow);
|
1157 | }
|
1158 | }
|
1159 |
|
1160 | private addHoverFunctionality(eRow: HTMLElement): void {
|
1161 |
|
1162 |
|
1163 |
|
1164 | if (!this.active) {
|
1165 | return;
|
1166 | }
|
1167 |
|
1168 |
|
1169 |
|
1170 |
|
1171 |
|
1172 |
|
1173 |
|
1174 |
|
1175 |
|
1176 |
|
1177 | this.addDestroyableEventListener(eRow, 'mouseenter', () => this.rowNode.onMouseEnter() );
|
1178 | this.addDestroyableEventListener(eRow, 'mouseleave', () => this.rowNode.onMouseLeave() );
|
1179 |
|
1180 |
|
1181 | this.addDestroyableEventListener(this.rowNode, RowNode.EVENT_MOUSE_ENTER, ()=> {
|
1182 |
|
1183 |
|
1184 |
|
1185 | if (!this.beans.gridOptionsWrapper.isSuppressRowHoverHighlight()) {
|
1186 | _.addCssClass(eRow, 'ag-row-hover');
|
1187 | }
|
1188 | });
|
1189 | this.addDestroyableEventListener(this.rowNode, RowNode.EVENT_MOUSE_LEAVE, ()=> {
|
1190 | _.removeCssClass(eRow, 'ag-row-hover');
|
1191 | });
|
1192 | }
|
1193 |
|
1194 |
|
1195 |
|
1196 |
|
1197 |
|
1198 | private roundRowTopToBounds(rowTop: number): number {
|
1199 | let range = this.beans.gridPanel.getVScrollPosition();
|
1200 |
|
1201 | let minPixel = this.applyPaginationOffset(range.top, true) - 100;
|
1202 | let maxPixel = this.applyPaginationOffset(range.bottom, true) + 100;
|
1203 |
|
1204 | if (rowTop < minPixel) {
|
1205 | return minPixel;
|
1206 | } else if (rowTop > maxPixel) {
|
1207 | return maxPixel;
|
1208 | } else {
|
1209 | return rowTop;
|
1210 | }
|
1211 | }
|
1212 |
|
1213 | private onRowHeightChanged(): void {
|
1214 |
|
1215 |
|
1216 |
|
1217 | if (_.exists(this.rowNode.rowHeight)) {
|
1218 | let heightPx = this.rowNode.rowHeight + 'px';
|
1219 | this.eAllRowContainers.forEach( row => row.style.height = heightPx);
|
1220 | }
|
1221 | }
|
1222 |
|
1223 | public addEventListener(eventType: string, listener: Function): void {
|
1224 | if (eventType==='renderedRowRemoved' || eventType==='rowRemoved') {
|
1225 | eventType = Events.EVENT_VIRTUAL_ROW_REMOVED;
|
1226 | console.warn('ag-Grid: Since version 11, event renderedRowRemoved is now called ' + Events.EVENT_VIRTUAL_ROW_REMOVED);
|
1227 | }
|
1228 | super.addEventListener(eventType, listener);
|
1229 | }
|
1230 |
|
1231 | public removeEventListener(eventType: string, listener: Function): void {
|
1232 | if (eventType==='renderedRowRemoved' || eventType==='rowRemoved') {
|
1233 | eventType = Events.EVENT_VIRTUAL_ROW_REMOVED;
|
1234 | console.warn('ag-Grid: Since version 11, event renderedRowRemoved and rowRemoved is now called ' + Events.EVENT_VIRTUAL_ROW_REMOVED);
|
1235 | }
|
1236 | super.removeEventListener(eventType, listener);
|
1237 | }
|
1238 |
|
1239 | public destroy(animate = false): void {
|
1240 | super.destroy();
|
1241 |
|
1242 | this.active = false;
|
1243 |
|
1244 |
|
1245 |
|
1246 |
|
1247 | this.destroyFullWidthComponents();
|
1248 |
|
1249 | if (animate) {
|
1250 |
|
1251 | this.removeFirstPassFuncs.forEach( func => func() );
|
1252 | this.removeSecondPassFuncs.push(this.destroyContainingCells.bind(this));
|
1253 |
|
1254 | } else {
|
1255 | this.destroyContainingCells();
|
1256 |
|
1257 |
|
1258 |
|
1259 | let delayedDestroyFunctions = this.getAndClearDelayedDestroyFunctions();
|
1260 | delayedDestroyFunctions.forEach( func => func() );
|
1261 | }
|
1262 |
|
1263 | let event: VirtualRowRemovedEvent = this.createRowEvent(Events.EVENT_VIRTUAL_ROW_REMOVED);
|
1264 |
|
1265 | this.dispatchEvent(event);
|
1266 | this.beans.eventService.dispatchEvent(event);
|
1267 | }
|
1268 |
|
1269 | private destroyContainingCells(): void {
|
1270 | this.forEachCellComp(renderedCell => renderedCell.destroy() );
|
1271 | this.destroyFullWidthComponents();
|
1272 | }
|
1273 |
|
1274 |
|
1275 | public getAndClearDelayedDestroyFunctions(): Function[] {
|
1276 | let result = this.removeSecondPassFuncs;
|
1277 | this.removeSecondPassFuncs = [];
|
1278 | return result;
|
1279 | }
|
1280 |
|
1281 | private onCellFocusChanged(): void {
|
1282 | let rowFocused = this.beans.focusedCellController.isRowFocused(this.rowNode.rowIndex, this.rowNode.rowPinned);
|
1283 | if (rowFocused !== this.rowFocused) {
|
1284 | this.eAllRowContainers.forEach( (row) => _.addOrRemoveCssClass(row, 'ag-row-focus', rowFocused) );
|
1285 | this.eAllRowContainers.forEach( (row) => _.addOrRemoveCssClass(row, 'ag-row-no-focus', !rowFocused) );
|
1286 | this.rowFocused = rowFocused;
|
1287 | }
|
1288 |
|
1289 |
|
1290 | if (!rowFocused && this.editingRow) {
|
1291 | this.stopEditing(false);
|
1292 | }
|
1293 | }
|
1294 |
|
1295 | private onPaginationChanged(): void {
|
1296 | let currentPage = this.beans.paginationProxy.getCurrentPage();
|
1297 |
|
1298 |
|
1299 | if (this.paginationPage!==currentPage) {
|
1300 | this.paginationPage = currentPage;
|
1301 | this.onTopChanged();
|
1302 | }
|
1303 | }
|
1304 |
|
1305 | private onTopChanged(): void {
|
1306 | this.setRowTop(this.rowNode.rowTop);
|
1307 | }
|
1308 |
|
1309 |
|
1310 |
|
1311 |
|
1312 | private applyPaginationOffset(topPx: number, reverse = false): number {
|
1313 | if (this.rowNode.isRowPinned()) {
|
1314 | return topPx;
|
1315 | } else {
|
1316 | let pixelOffset = this.beans.paginationProxy.getPixelOffset();
|
1317 | if (reverse) {
|
1318 | return topPx + pixelOffset;
|
1319 | } else {
|
1320 | return topPx - pixelOffset;
|
1321 | }
|
1322 | }
|
1323 | }
|
1324 |
|
1325 | private setRowTop(pixels: number): void {
|
1326 |
|
1327 |
|
1328 | if (_.exists(pixels)) {
|
1329 | let afterPaginationPixels = this.applyPaginationOffset(pixels);
|
1330 |
|
1331 | let afterScalingPixels = this.beans.heightScaler.getRealPixelPosition(afterPaginationPixels);
|
1332 |
|
1333 | let topPx = afterScalingPixels + "px";
|
1334 | if (this.beans.gridOptionsWrapper.isSuppressRowTransform()) {
|
1335 | this.eAllRowContainers.forEach( row => row.style.top = `${topPx}` );
|
1336 | } else {
|
1337 | this.eAllRowContainers.forEach( row => row.style.transform = `translateY(${topPx})` );
|
1338 | }
|
1339 | }
|
1340 | }
|
1341 |
|
1342 |
|
1343 | public getAndClearNextVMTurnFunctions(): Function[] {
|
1344 | let result = this.createSecondPassFuncs;
|
1345 | this.createSecondPassFuncs = [];
|
1346 | return result;
|
1347 | }
|
1348 |
|
1349 | public getRowNode(): RowNode {
|
1350 | return this.rowNode;
|
1351 | }
|
1352 |
|
1353 | public getRenderedCellForColumn(column: Column): CellComp {
|
1354 | return this.cellComps[column.getColId()];
|
1355 | }
|
1356 |
|
1357 | private onRowIndexChanged(): void {
|
1358 | this.onCellFocusChanged();
|
1359 | this.updateRowIndexes();
|
1360 | }
|
1361 |
|
1362 | private updateRowIndexes(): void {
|
1363 | let rowIndexStr = this.rowNode.getRowIndexString();
|
1364 |
|
1365 | let rowIsEven = this.rowNode.rowIndex % 2 === 0;
|
1366 | let rowIsEvenChanged = this.rowIsEven !== rowIsEven;
|
1367 | if (rowIsEvenChanged) {
|
1368 | this.rowIsEven = rowIsEven;
|
1369 | }
|
1370 |
|
1371 | this.eAllRowContainers.forEach( eRow => {
|
1372 | eRow.setAttribute('row-index', rowIndexStr);
|
1373 |
|
1374 | if (rowIsEvenChanged) {
|
1375 | _.addOrRemoveCssClass(eRow, 'ag-row-even', rowIsEven);
|
1376 | _.addOrRemoveCssClass(eRow, 'ag-row-odd', !rowIsEven);
|
1377 | }
|
1378 | });
|
1379 | }
|
1380 |
|
1381 | public ensureDomOrder(): void {
|
1382 | let body = this.getBodyRowElement();
|
1383 | if (body) {
|
1384 | this.bodyContainerComp.ensureDomOrder(body);
|
1385 | }
|
1386 |
|
1387 | let left = this.getPinnedLeftRowElement();
|
1388 | if (left) {
|
1389 | this.pinnedLeftContainerComp.ensureDomOrder(left);
|
1390 | }
|
1391 |
|
1392 | let right = this.getPinnedRightRowElement();
|
1393 | if (right) {
|
1394 | this.pinnedRightContainerComp.ensureDomOrder(right);
|
1395 | }
|
1396 |
|
1397 | let fullWidth = this.getFullWidthRowElement();
|
1398 | if (fullWidth) {
|
1399 | this.fullWidthContainerComp.ensureDomOrder(fullWidth);
|
1400 | }
|
1401 | }
|
1402 |
|
1403 |
|
1404 | public getPinnedLeftRowElement(): HTMLElement {
|
1405 | return this.ePinnedLeftRow ? this.ePinnedLeftRow : this.eFullWidthRowLeft;
|
1406 | }
|
1407 |
|
1408 |
|
1409 | public getPinnedRightRowElement(): HTMLElement {
|
1410 | return this.ePinnedRightRow ? this.ePinnedRightRow : this.eFullWidthRowRight;
|
1411 | }
|
1412 |
|
1413 |
|
1414 | public getBodyRowElement(): HTMLElement {
|
1415 | return this.eBodyRow ? this.eBodyRow : this.eFullWidthRowBody;
|
1416 | }
|
1417 |
|
1418 |
|
1419 | public getFullWidthRowElement(): HTMLElement {
|
1420 | return this.eFullWidthRow;
|
1421 | }
|
1422 |
|
1423 | } |
\ | No newline at end of file |