diff --git a/misc/tutorial/303_customizing_column_menu.ngdoc b/misc/tutorial/303_customizing_column_menu.ngdoc index 2f1cd12ea9..5853446467 100644 --- a/misc/tutorial/303_customizing_column_menu.ngdoc +++ b/misc/tutorial/303_customizing_column_menu.ngdoc @@ -12,7 +12,8 @@ The column menu will add the column's `GridColumn` object to the context as `thi You can then show/hide the the menu item based on conditions that use the grid and column. You could also use a custom column builder to add some item to the every column definition. -You can remove the column hide option using the `disableHiding` columnDef option. You can disable +You can remove the column hide option using the `disableHiding` columnDef option, which will also prevent +this column being hidden in the gridMenu (once it is finished and merged). You can disable the column menu entirely using the `disableColumnMenu` columnDef option. You can supply an icon class with the `icon` property. diff --git a/src/features/cellnav/js/cellnav.js b/src/features/cellnav/js/cellnav.js index 0174457479..40cea094f8 100644 --- a/src/features/cellnav/js/cellnav.js +++ b/src/features/cellnav/js/cellnav.js @@ -354,11 +354,11 @@ var args = {}; if (gridRow !== null) { - args.y = { percentage: gridRow.index / grid.renderContainers.body.visibleRowCache.length }; + args.y = { percentage: grid.renderContainers.body.visibleRowCache.indexOf(gridRow) / grid.renderContainers.body.visibleRowCache.length }; } if (gridCol !== null) { - args.x = { percentage: this.getLeftWidth(grid, gridCol.index) / this.getLeftWidth(grid, grid.renderContainers.body.visibleColumnCache.length - 1) }; + args.x = { percentage: this.getLeftWidth(grid, gridCol) / this.getLeftWidth(grid, grid.renderContainers.body.visibleColumnCache[grid.renderContainers.body.visibleColumnCache.length - 1] ) }; } if (args.y || args.x) { @@ -371,26 +371,37 @@ * @methodOf ui.grid.cellNav.service:uiGridCellNavService * @name getLeftWidth * @description Get the current drawn width of the columns in the - * grid up to and including the numbered column + * grid up to the numbered column, and add an apportionment for the + * column that we're on. So if we are on column 0, we want to scroll + * 0% (i.e. exclude this column from calc). If we're on the last column + * we want to scroll to 100% (i.e. include this column in the calc). So + * we include (thisColIndex / totalNumberCols) % of this column width * @param {Grid} grid the grid you'd like to act upon, usually available * from gridApi.grid - * @param {object} colIndex the column to total up to and including + * @param {gridCol} upToCol the column to total up to and including */ - getLeftWidth: function (grid, colIndex) { + getLeftWidth: function (grid, upToCol) { var width = 0; - if (!colIndex) { - return; + if (!upToCol) { + return width; } - - for (var i = 0; i <= colIndex; i++) { - if (grid.renderContainers.body.visibleColumnCache[i].drawnWidth) { - width += grid.renderContainers.body.visibleColumnCache[i].drawnWidth; + + var lastIndex = grid.renderContainers.body.visibleColumnCache.indexOf( upToCol ); + + // total column widths up-to but not including the passed in column + grid.renderContainers.body.visibleColumnCache.forEach( function( col, index ) { + if ( index < lastIndex ){ + width += col.drawnWidth; } - } + }); + + // pro-rata the final column based on % of total columns. + var percentage = lastIndex === 0 ? 0 : (lastIndex + 1) / grid.renderContainers.body.visibleColumnCache.length; + width += upToCol.drawnWidth * percentage; + return width; } - }; return service; @@ -516,7 +527,6 @@ var rowCol = $scope.colContainer.cellNav.getNextRowCol(direction, $scope.row, $scope.col); - //$log.debug('next row ' + rowCol.row.index + ' next Col ' + rowCol.col.colDef.name); uiGridCtrl.cellNav.broadcastCellNav(rowCol); setTabEnabled(); @@ -534,7 +544,6 @@ $scope.$on(uiGridCellNavConstants.CELL_NAV_EVENT, function (evt, rowCol) { if (rowCol.row === $scope.row && rowCol.col === $scope.col) { - // $log.debug('Setting focus on Row ' + rowCol.row.index + ' Col ' + rowCol.col.colDef.name); setFocused(); } }); diff --git a/src/features/cellnav/test/uiGridCellNavService.spec.js b/src/features/cellnav/test/uiGridCellNavService.spec.js index ff93d23ce7..a8b4b29c8b 100644 --- a/src/features/cellnav/test/uiGridCellNavService.spec.js +++ b/src/features/cellnav/test/uiGridCellNavService.spec.js @@ -182,7 +182,7 @@ describe('ui.grid.edit uiGridCellNavService', function () { it('should request scroll to row and column', function () { uiGridCellNavService.scrollTo( grid, $scope, grid.options.data[2], grid.columns[1].colDef); - expect(args).toEqual( { y : { percentage : 2/3 }, x : { percentage : 300/600 } }); + expect(args).toEqual( { y : { percentage : 2/3 }, x : { percentage : (100 + 2/3 * 200)/600 } }); }); it('should request scroll to row only', function () { @@ -192,9 +192,9 @@ describe('ui.grid.edit uiGridCellNavService', function () { }); it('should request scroll to column only', function () { - uiGridCellNavService.scrollTo( grid, $scope, null, grid.columns[1].colDef); + uiGridCellNavService.scrollTo( grid, $scope, null, grid.columns[0].colDef); - expect(args).toEqual( { x : { percentage : 300/600 } }); + expect(args).toEqual( { x : { percentage : (1/3 * 100)/600 } }); }); it('should request no scroll as no row or column', function () { diff --git a/src/features/resize-columns/js/ui-grid-column-resizer.js b/src/features/resize-columns/js/ui-grid-column-resizer.js index 7965f4550a..e90d1bcd0d 100644 --- a/src/features/resize-columns/js/ui-grid-column-resizer.js +++ b/src/features/resize-columns/js/ui-grid-column-resizer.js @@ -167,12 +167,11 @@ var otherCol = renderContainer.renderedColumns[$scope.renderIndex - 1]; // Don't append the left resizer if this is the first column or the column to the left of this one has resizing disabled - if (otherCol && $scope.col.index !== 0 && otherCol.colDef.enableColumnResizing !== false) { + if (otherCol && renderContainer.visibleColumnCache.indexOf($scope.col) !== 0 && otherCol.colDef.enableColumnResizing !== false) { $elm.prepend(resizerLeft); } // Don't append the right resizer if this column has resizing disabled - //if ($scope.col.index !== $scope.grid.renderedColumns.length - 1 && $scope.col.colDef.enableColumnResizing !== false) { if ($scope.col.colDef.enableColumnResizing !== false) { $elm.append(resizerRight); } @@ -259,7 +258,7 @@ renderContainer.visibleColumnCache.forEach(function (column) { // Skip the column we just resized - if (column.index === col.index) { return; } + if (column === col) { return; } var colDef = column.colDef; if (!colDef.width || (angular.isString(colDef.width) && (colDef.width.indexOf('*') !== -1 || colDef.width.indexOf('%') !== -1))) { diff --git a/src/js/core/directives/ui-grid-column-menu.js b/src/js/core/directives/ui-grid-column-menu.js index 874ef54175..2e934fbac8 100644 --- a/src/js/core/directives/ui-grid-column-menu.js +++ b/src/js/core/directives/ui-grid-column-menu.js @@ -89,8 +89,8 @@ angular.module('ui.grid').directive('uiGridColumnMenu', ['$log', '$timeout', '$w * @ngdoc boolean * @name disableHiding * @propertyOf ui.grid.class:GridOptions.columnDef - * @description (optional) True by default. When enabled, this setting allows a user to hide the column - * using the column menu. + * @description (optional) False by default. When enabled, this setting prevents a user from hiding the column + * using the column menu or the grid menu. */ $scope.hideable = function() { if (typeof($scope.col) !== 'undefined' && $scope.col && $scope.col.colDef && $scope.col.colDef.disableHiding) { diff --git a/src/js/core/directives/ui-grid-header-cell.js b/src/js/core/directives/ui-grid-header-cell.js index 95ccc916ce..5458ed8421 100644 --- a/src/js/core/directives/ui-grid-header-cell.js +++ b/src/js/core/directives/ui-grid-header-cell.js @@ -41,13 +41,6 @@ $elm.addClass($scope.col.getColClass(false)); - // shane - No need for watch now that we trackby col name - // $scope.$watch('col.index', function (newValue, oldValue) { - // if (newValue === oldValue) { return; } - // var className = $elm.attr('class'); - // className = className.replace(uiGridConstants.COL_CLASS_PREFIX + oldValue, uiGridConstants.COL_CLASS_PREFIX + newValue); - // $elm.attr('class', className); - // }); // Hide the menu by default $scope.menuShown = false; diff --git a/src/js/core/directives/ui-grid-header.js b/src/js/core/directives/ui-grid-header.js index ecb9be274b..57e34402b5 100644 --- a/src/js/core/directives/ui-grid-header.js +++ b/src/js/core/directives/ui-grid-header.js @@ -129,7 +129,6 @@ column.drawnWidth = column.width; - // ret = ret + ' .grid' + uiGridCtrl.grid.id + ' .col' + column.index + ' { width: ' + column.width + 'px; }'; } }); @@ -155,8 +154,6 @@ canvasWidth += colWidth; column.drawnWidth = colWidth; - // ret = ret + ' .grid' + uiGridCtrl.grid.id + ' .col' + column.index + ' { width: ' + colWidth + 'px; }'; - // Remove this element from the percent array so it's not processed below percentArray.splice(i, 1); } @@ -168,8 +165,6 @@ canvasWidth += colWidth; column.drawnWidth = colWidth; - // ret = ret + ' .grid' + uiGridCtrl.grid.id + ' .col' + column.index + ' { width: ' + colWidth + 'px; }'; - // Remove this element from the percent array so it's not processed below percentArray.splice(i, 1); } @@ -182,8 +177,6 @@ canvasWidth += colWidth; column.drawnWidth = colWidth; - - // ret = ret + ' .grid' + uiGridCtrl.grid.id + ' .col' + column.index + ' { width: ' + colWidth + 'px; }'; }); } @@ -205,8 +198,6 @@ canvasWidth += colWidth; column.drawnWidth = colWidth; - // ret = ret + ' .grid' + uiGridCtrl.grid.id + ' .col' + column.index + ' { width: ' + colWidth + 'px; }'; - lastColumn = column; // Remove this element from the percent array so it's not processed below @@ -221,8 +212,6 @@ canvasWidth += colWidth; column.drawnWidth = colWidth; - // ret = ret + ' .grid' + uiGridCtrl.grid.id + ' .col' + column.index + ' { width: ' + colWidth + 'px; }'; - // Remove this element from the percent array so it's not processed below asterisksArray.splice(i, 1); } @@ -237,8 +226,6 @@ canvasWidth += colWidth; column.drawnWidth = colWidth; - - // ret = ret + ' .grid' + uiGridCtrl.grid.id + ' .col' + column.index + ' { width: ' + colWidth + 'px; }'; }); } diff --git a/src/js/core/factories/Grid.js b/src/js/core/factories/Grid.js index 2247b0314a..616f9f13e7 100644 --- a/src/js/core/factories/Grid.js +++ b/src/js/core/factories/Grid.js @@ -340,6 +340,7 @@ angular.module('ui.grid') .then(function(){ rowHeaderCol.enableFiltering = false; rowHeaderCol.enableSorting = false; + rowHeaderCol.disableHiding = true; self.rowHeaderColumns.push(rowHeaderCol); self.buildColumns() .then( function() { @@ -363,20 +364,21 @@ angular.module('ui.grid') var builderPromises = []; var headerOffset = self.rowHeaderColumns.length; - // Synchronize self.columns with self.options.columnDefs so that columns can also be removed. + // Remove any columns for which a columnDef cannot be found self.columns.forEach(function (column, index) { if (!self.getColDef(column.name)) { self.columns.splice(index, 1); } }); - //add row header columns to the grid columns array _after_ columns without columnDefs have been removed self.rowHeaderColumns.forEach(function (rowHeaderColumn) { self.columns.unshift(rowHeaderColumn); }); + // look at each column def, and update column properties to match. If the column def + // new, then splice in a new gridCol self.options.columnDefs.forEach(function (colDef, index) { self.preprocessColDef(colDef); var col = self.getColumn(colDef.name); @@ -386,13 +388,18 @@ angular.module('ui.grid') self.columns.splice(index + headerOffset, 0, col); } else { - col.updateColumnDef(colDef, col.index); + col.updateColumnDef(colDef); } self.columnBuilders.forEach(function (builder) { builderPromises.push(builder.call(self, colDef, col, self.options)); }); }); + + // col.index is still used in the cell templates, so just renumber it every time + self.columns.forEach( function( col, index ){ + col.index = index; + }); return $q.all(builderPromises); }; diff --git a/src/js/core/factories/GridColumn.js b/src/js/core/factories/GridColumn.js index cc363bd8f9..6923dc25b5 100644 --- a/src/js/core/factories/GridColumn.js +++ b/src/js/core/factories/GridColumn.js @@ -110,16 +110,34 @@ angular.module('ui.grid') * */ - + /** + * @ngdoc method + * @methodOf ui.grid.class:GridColumn + * @name GridColumn + * @description Initializes a gridColumn + * @param {ColumnDef} colDef the column def to associate with this column + * @param {number} index deprecated, but not yet removed from signature - null can be passed + * @param {Grid} grid the grid we'd like to create this column in + */ function GridColumn(colDef, index, grid) { var self = this; self.grid = grid; - colDef.index = index; self.updateColumnDef(colDef); } + + /** + * @ngdoc method + * @methodOf ui.grid.class:GridColumn + * @name setPropertyOrDefault + * @description Sets a property on the column using the passed in columnDef, and + * setting the defaultValue if the value cannot be found on the colDef + * @param {ColumnDef} colDef the column def to look in for the property value + * @param {string} propName the property name we'd like to set + * @param {object} defaultValue the value to use if the colDef doesn't provide the setting + */ GridColumn.prototype.setPropertyOrDefault = function (colDef, propName, defaultValue) { var self = this; @@ -296,16 +314,23 @@ angular.module('ui.grid') * ] }]; * */ + + /** + * @ngdoc method + * @methodOf ui.grid.class:GridColumn + * @name updateColumnDef + * @description Moves settings from the columnDef down onto the column, + * and sets properties as appropriate + * @param {ColumnDef} colDef the column def to look in for the property value + * @param {number} index deprecated but not yet removed from method signature. Null is valid. + */ GridColumn.prototype.updateColumnDef = function(colDef, index) { var self = this; self.colDef = colDef; - //position of column - self.index = (typeof(index) === 'undefined') ? colDef.index : index; - if (colDef.name === undefined) { - throw new Error('colDef.name is required for column at index ' + self.index); + throw new Error('colDef.name is required for column at index ' + self.grid.options.columnDefs.indexOf(colDef)); } var parseErrorMsg = "Cannot parse column width '" + colDef.width + "' for column named '" + colDef.name + "'"; diff --git a/src/js/core/factories/GridRenderContainer.js b/src/js/core/factories/GridRenderContainer.js index 29df1b366b..167c8fcce7 100644 --- a/src/js/core/factories/GridRenderContainer.js +++ b/src/js/core/factories/GridRenderContainer.js @@ -498,8 +498,6 @@ angular.module('ui.grid') canvasWidth = parseInt(canvasWidth, 10) + parseInt(column.width, 10); column.drawnWidth = column.width; - - // ret = ret + ' .grid' + uiGridCtrl.grid.id + ' .col' + column.index + ' { width: ' + column.width + 'px; }'; } }); @@ -525,8 +523,6 @@ angular.module('ui.grid') canvasWidth += colWidth; column.drawnWidth = colWidth; - // ret = ret + ' .grid' + uiGridCtrl.grid.id + ' .col' + column.index + ' { width: ' + colWidth + 'px; }'; - // Remove this element from the percent array so it's not processed below percentArray.splice(i, 1); } @@ -538,8 +534,6 @@ angular.module('ui.grid') canvasWidth += colWidth; column.drawnWidth = colWidth; - // ret = ret + ' .grid' + uiGridCtrl.grid.id + ' .col' + column.index + ' { width: ' + colWidth + 'px; }'; - // Remove this element from the percent array so it's not processed below percentArray.splice(i, 1); } @@ -552,8 +546,6 @@ angular.module('ui.grid') canvasWidth += colWidth; column.drawnWidth = colWidth; - - // ret = ret + ' .grid' + uiGridCtrl.grid.id + ' .col' + column.index + ' { width: ' + colWidth + 'px; }'; }); } @@ -575,8 +567,6 @@ angular.module('ui.grid') canvasWidth += colWidth; column.drawnWidth = colWidth; - // ret = ret + ' .grid' + uiGridCtrl.grid.id + ' .col' + column.index + ' { width: ' + colWidth + 'px; }'; - lastColumn = column; // Remove this element from the percent array so it's not processed below @@ -591,8 +581,6 @@ angular.module('ui.grid') canvasWidth += colWidth; column.drawnWidth = colWidth; - // ret = ret + ' .grid' + uiGridCtrl.grid.id + ' .col' + column.index + ' { width: ' + colWidth + 'px; }'; - // Remove this element from the percent array so it's not processed below asterisksArray.splice(i, 1); } @@ -607,8 +595,6 @@ angular.module('ui.grid') canvasWidth += colWidth; column.drawnWidth = colWidth; - - // ret = ret + ' .grid' + uiGridCtrl.grid.id + ' .col' + column.index + ' { width: ' + colWidth + 'px; }'; }); } diff --git a/src/js/core/factories/GridRow.js b/src/js/core/factories/GridRow.js index 54a31079e7..7d8e3e097c 100644 --- a/src/js/core/factories/GridRow.js +++ b/src/js/core/factories/GridRow.js @@ -30,15 +30,6 @@ angular.module('ui.grid') */ this.entity = entity; - /** - * @ngdoc object - * @name index - * @propertyOf ui.grid.class:GridRow - * @description the index of the GridRow. It should always be unique and immutable - */ - this.index = index; - - /** * @ngdoc object * @name uid