UNPKG

ag-grid

Version:

Advanced Javascript Datagrid. Supports raw Javascript, AngularJS 1.x, AngularJS 2.0 and Web Components

368 lines (308 loc) 15.7 kB
/// <reference path='../utils.ts' /> /// <reference path='../filter/filterManager.ts' /> /// <reference path='../gridOptionsWrapper.ts' /> /// <reference path='../columnController.ts' /> /// <reference path='renderedHeaderElement.ts' /> module ag.grid { var _ = Utils; var constants = Constants; var svgFactory = SvgFactory.getInstance(); export class RenderedHeaderCell extends RenderedHeaderElement { private static DEFAULT_SORTING_ORDER = [constants.ASC, constants.DESC, null]; private eHeaderCell: HTMLElement; private eSortAsc: HTMLElement; private eSortDesc: HTMLElement; private eSortNone: HTMLElement; private eFilterIcon: HTMLElement; private column: Column; private gridOptionsWrapper: GridOptionsWrapper; private parentScope: any; private childScope: any; //todo: destroy this private filterManager: FilterManager; private columnController: ColumnController; private $compile: any; private angularGrid: Grid; private parentGroup: RenderedHeaderGroupCell; private startWidth: number; constructor(column: Column, parentGroup: RenderedHeaderGroupCell, gridOptionsWrapper: GridOptionsWrapper, parentScope: any, filterManager: FilterManager, columnController: ColumnController, $compile: any, angularGrid: Grid, eRoot: HTMLElement) { super(eRoot); this.column = column; this.parentGroup = parentGroup; this.gridOptionsWrapper = gridOptionsWrapper; this.parentScope = parentScope; this.filterManager = filterManager; this.columnController = columnController; this.$compile = $compile; this.angularGrid = angularGrid; this.setupComponents(); } public getGui(): HTMLElement { return this.eHeaderCell; } public destroy(): void { if (this.childScope) { this.childScope.$destroy(); } } private createScope(): void { if (this.gridOptionsWrapper.isAngularCompileHeaders()) { this.childScope = this.parentScope.$new(); this.childScope.colDef = this.column.colDef; this.childScope.colIndex = this.column.index; this.childScope.colDefWrapper = this.column; } } private addAttributes(): void { this.eHeaderCell.setAttribute("col", (this.column.index !== undefined && this.column.index !== null) ? this.column.index.toString() : ''); this.eHeaderCell.setAttribute("colId", this.column.colId); } private addClasses(): void { _.addCssClass(this.eHeaderCell, 'ag-header-cell'); if (this.gridOptionsWrapper.isGroupHeaders()) { _.addCssClass(this.eHeaderCell, 'ag-header-cell-grouped'); // this takes 50% height } else { _.addCssClass(this.eHeaderCell, 'ag-header-cell-not-grouped'); // this takes 100% height } } private addMenu(): void { var showMenu = this.gridOptionsWrapper.isEnableFilter() && !this.column.colDef.suppressMenu; if (!showMenu) { return; } var eMenuButton = _.createIcon('menu', this.gridOptionsWrapper, this.column, svgFactory.createMenuSvg); _.addCssClass(eMenuButton, 'ag-header-icon'); eMenuButton.setAttribute("class", "ag-header-cell-menu-button"); var that = this; eMenuButton.onclick = function () { that.filterManager.showFilter(that.column, this); }; this.eHeaderCell.appendChild(eMenuButton); if (!this.gridOptionsWrapper.isSuppressMenuHide()) { eMenuButton.style.opacity = '0'; this.eHeaderCell.onmouseenter = function () { eMenuButton.style.opacity = '1'; }; this.eHeaderCell.onmouseleave = function () { eMenuButton.style.opacity = '0'; }; } eMenuButton.style['transition'] = 'opacity 0.5s, border 0.2s'; var style: any = eMenuButton.style; style['-webkit-transition'] = 'opacity 0.5s, border 0.2s'; } private addSortIcons(headerCellLabel: HTMLElement): void { var addSortIcons = this.gridOptionsWrapper.isEnableSorting() && !this.column.colDef.suppressSorting; if (!addSortIcons) { return; } this.eSortAsc = _.createIcon('sortAscending', this.gridOptionsWrapper, this.column, svgFactory.createArrowUpSvg); this.eSortDesc = _.createIcon('sortDescending', this.gridOptionsWrapper, this.column, svgFactory.createArrowDownSvg); _.addCssClass(this.eSortAsc, 'ag-header-icon ag-sort-ascending-icon'); _.addCssClass(this.eSortDesc, 'ag-header-icon ag-sort-descending-icon'); headerCellLabel.appendChild(this.eSortAsc); headerCellLabel.appendChild(this.eSortDesc); // 'no sort' icon if (this.column.colDef.unSortIcon || this.gridOptionsWrapper.isUnSortIcon()) { this.eSortNone = _.createIcon('sortUnSort', this.gridOptionsWrapper, this.column, svgFactory.createArrowUpDownSvg); _.addCssClass(this.eSortNone, 'ag-header-icon ag-sort-none-icon'); headerCellLabel.appendChild(this.eSortNone); } this.eSortAsc.style.display = 'none'; this.eSortDesc.style.display = 'none'; this.addSortHandling(headerCellLabel); } private setupComponents(): void { this.eHeaderCell = document.createElement("div"); this.createScope(); this.addClasses(); this.addAttributes(); this.addHeaderClassesFromCollDef(); // add tooltip if exists if (this.column.colDef.headerTooltip) { this.eHeaderCell.title = this.column.colDef.headerTooltip; } if (this.gridOptionsWrapper.isEnableColResize() && !this.column.colDef.suppressResize) { var headerCellResize = document.createElement("div"); headerCellResize.className = "ag-header-cell-resize"; this.eHeaderCell.appendChild(headerCellResize); this.addDragHandler(headerCellResize); } this.addMenu(); // label div var headerCellLabel = document.createElement("div"); headerCellLabel.className = "ag-header-cell-label"; // add in sort icons this.addSortIcons(headerCellLabel); // add in filter icon this.eFilterIcon = _.createIcon('filter', this.gridOptionsWrapper, this.column, svgFactory.createFilterSvg); _.addCssClass(this.eFilterIcon, 'ag-header-icon'); headerCellLabel.appendChild(this.eFilterIcon); // render the cell, use a renderer if one is provided var headerCellRenderer: any; if (this.column.colDef.headerCellRenderer) { // first look for a renderer in col def headerCellRenderer = this.column.colDef.headerCellRenderer; } else if (this.gridOptionsWrapper.getHeaderCellRenderer()) { // second look for one in grid options headerCellRenderer = this.gridOptionsWrapper.getHeaderCellRenderer(); } var headerNameValue = this.columnController.getDisplayNameForCol(this.column); if (headerCellRenderer) { this.useRenderer(headerNameValue, headerCellRenderer, headerCellLabel); } else { // no renderer, default text render var eInnerText = document.createElement("span"); eInnerText.className = 'ag-header-cell-text'; eInnerText.innerHTML = headerNameValue; headerCellLabel.appendChild(eInnerText); } this.eHeaderCell.appendChild(headerCellLabel); this.eHeaderCell.style.width = _.formatWidth(this.column.actualWidth); this.refreshFilterIcon(); this.refreshSortIcon(); } private useRenderer(headerNameValue: string, headerCellRenderer: Function, headerCellLabel: HTMLElement): void { // renderer provided, use it var cellRendererParams = { colDef: this.column.colDef, $scope: this.childScope, context: this.gridOptionsWrapper.getContext(), value: headerNameValue, api: this.gridOptionsWrapper.getApi(), eHeaderCell: this.eHeaderCell }; var cellRendererResult = headerCellRenderer(cellRendererParams); var childToAppend: any; if (_.isNodeOrElement(cellRendererResult)) { // a dom node or element was returned, so add child childToAppend = cellRendererResult; } else { // otherwise assume it was html, so just insert var eTextSpan = document.createElement("span"); eTextSpan.innerHTML = cellRendererResult; childToAppend = eTextSpan; } // angular compile header if option is turned on if (this.gridOptionsWrapper.isAngularCompileHeaders()) { var childToAppendCompiled = this.$compile(childToAppend)(this.childScope)[0]; headerCellLabel.appendChild(childToAppendCompiled); } else { headerCellLabel.appendChild(childToAppend); } } public refreshFilterIcon(): void { if (this.eFilterIcon) { var filterPresent = this.filterManager.isFilterPresentForCol(this.column.colId); var displayStyle = filterPresent ? 'inline' : 'none'; this.eFilterIcon.style.display = displayStyle; } } public refreshSortIcon(): void { // update visibility of icons var sortAscending = this.column.sort === constants.ASC; var sortDescending = this.column.sort === constants.DESC; var unSort = this.column.sort !== constants.DESC && this.column.sort !== constants.ASC; if (this.eSortAsc) { _.setVisible(this.eSortAsc, sortAscending); } if (this.eSortDesc) { _.setVisible(this.eSortDesc, sortDescending); } if (this.eSortNone) { _.setVisible(this.eSortNone, unSort); } } private getNextSortDirection(): string { var sortingOrder: string[]; if (this.column.colDef.sortingOrder) { sortingOrder = this.column.colDef.sortingOrder; } else if (this.gridOptionsWrapper.getSortingOrder()) { sortingOrder = this.gridOptionsWrapper.getSortingOrder(); } else { sortingOrder = RenderedHeaderCell.DEFAULT_SORTING_ORDER; } if ( !Array.isArray(sortingOrder) || sortingOrder.length <= 0) { console.warn('ag-grid: sortingOrder must be an array with at least one element, currently it\'s ' + sortingOrder); return; } var currentIndex = sortingOrder.indexOf(this.column.sort); var notInArray = currentIndex < 0; var lastItemInArray = currentIndex == sortingOrder.length - 1; var result: string; if (notInArray || lastItemInArray) { result = sortingOrder[0]; } else { result = sortingOrder[currentIndex + 1]; } // verify the sort type exists, as the user could provide the sortOrder, need to make sure it's valid if (RenderedHeaderCell.DEFAULT_SORTING_ORDER.indexOf(result) < 0) { console.warn('ag-grid: invalid sort type ' + result); return null; } return result; } private addSortHandling(headerCellLabel: HTMLElement) { var that = this; headerCellLabel.addEventListener("click", function (event: any) { // update sort on current col that.column.sort = that.getNextSortDirection(); // sortedAt used for knowing order of cols when multi-col sort if (that.column.sort) { that.column.sortedAt = new Date().valueOf(); } else { that.column.sortedAt = null; } var doingMultiSort = !that.gridOptionsWrapper.isSuppressMultiSort() && event.shiftKey; // clear sort on all columns except this one, and update the icons if (!doingMultiSort) { that.columnController.getAllColumns().forEach(function (columnToClear: any) { // Do not clear if either holding shift, or if column in question was clicked if (!(columnToClear === that.column)) { columnToClear.sort = null; } }); } that.angularGrid.onSortingChanged(); }); } public onDragStart(): void { this.startWidth = this.column.actualWidth; } public onDragging(dragChange: number): void { var newWidth = this.startWidth + dragChange; this.columnController.setColumnWidth(this.column, newWidth); } public onIndividualColumnResized(column: Column) { if (this.column !== column) { return; } var newWidthPx = column.actualWidth + "px"; this.eHeaderCell.style.width = newWidthPx; } private addHeaderClassesFromCollDef() { if (this.column.colDef.headerClass) { var classToUse: string | string[]; if (typeof this.column.colDef.headerClass === 'function') { var params = { colDef: this.column.colDef, $scope: this.childScope, context: this.gridOptionsWrapper.getContext(), api: this.gridOptionsWrapper.getApi() }; var headerClassFunc = <(params: any) => string | string[]> this.column.colDef.headerClass; classToUse = headerClassFunc(params); } else { classToUse = <string | string[]> this.column.colDef.headerClass; } if (typeof classToUse === 'string') { _.addCssClass(this.eHeaderCell, classToUse); } else if (Array.isArray(classToUse)) { classToUse.forEach(function (cssClassItem: any) { _.addCssClass(this.eHeaderCell, cssClassItem); }); } } } } }