import { Injectable , QueryList } from '@angular/core' ; import { BaseResizableTableService , ResizableTableType } from '../resizable-table-base.service' ; import { ResizableTableColumnComponent } from '../resizable-table-column.component' ; @ Injectable ( ) export class ResizableExpandingTableService extends BaseResizableTableService { /** Define the type of resizing we should use */ type : ResizableTableType = ResizableTableType . Expand ; /** Store the QueryList of columns */ private _columns : QueryList < ResizableTableColumnComponent > ; /** Store the size of each column */ setColumns ( columns ) { this . _columns = columns ; this . columns = columns . map ( column => ( column . getNaturalWidth ( ) / this . tableWidth ) * 100 ) ; this . _columns . forEach ( ( column , idx ) => { if ( ! column . disabled ) { this . columns = this . setColumnWidth ( idx , this . columns [ idx ] , ColumnUnit . Percentage , this . columns ) ; } } ) ; if ( this . isInitialised$ . value === false ) { this . isInitialised$ . next ( true ) ; } } /** Set all resizable columns to the same width */ setUniformWidths ( ) { this . columns = this . _columns . map ( column => column . disabled ? ( column . getNaturalWidth ( ) / this . tableWidth ) * 100 : 0 ) ; const totalWidth = this . columns . reduce ( ( partial , columnWidth ) => partial + columnWidth ) ; if ( totalWidth > 98 ) { this . columns = this . ensureNoOverflow ( this . columns ) ; } else { const resizableColumns = this . _columns . toArray ( ) . filter ( column => ! column . disabled ) ; const newWidth = ( 98 - totalWidth ) / resizableColumns . length ; this . columns = this . _columns . map ( ( column , idx ) => column . disabled ? this . columns [ idx ] : newWidth ) ; } this . _columns . forEach ( ( column , idx ) => { if ( ! column . disabled ) { this . resizeColumn ( idx , 0 , false ) ; } } ) ; } ensureNoOverflow ( columns ) { const total = columns . reduce ( ( width , column ) => width + column ) ; if ( total <= 100 ) { return columns ; } const variableColumns = this . _columns . filter ( column => ! column . disabled && this . getColumnWidth ( column . getCellIndex ( ) , ColumnUnit . Pixel , columns ) > column . minWidth ) ; if ( variableColumns . length === 0 ) { return columns ; } const totalWidth = this . _columns . reduce ( ( width , column ) => width + this . getColumnWidth ( column . getCellIndex ( ) , ColumnUnit . Pixel , columns ) , 0 ) ; const variableColumnsWidth = variableColumns . reduce ( ( width , column ) => width + this . getColumnWidth ( column . getCellIndex ( ) , ColumnUnit . Pixel , columns ) , 0 ) ; const targetWidth = this . tableWidth - ( totalWidth - variableColumnsWidth ) ; const difference = variableColumnsWidth - targetWidth ; const target = variableColumns . reduce ( ( widest , column ) => { const columnWidth = this . getColumnWidth ( column . getCellIndex ( ) , ColumnUnit . Pixel , columns ) ; const widestWidth = this . getColumnWidth ( widest . getCellIndex ( ) , ColumnUnit . Pixel , columns ) ; return columnWidth > widestWidth ? column : widest ; } ) ; columns = this . setColumnWidth ( target . getCellIndex ( ) , this . getColumnWidth ( target . getCellIndex ( ) , ColumnUnit . Pixel , columns ) - difference , ColumnUnit . Pixel , columns ) ; if ( columns . reduce ( ( width , column ) => width + column ) > 100.01 ) { return this . ensureNoOverflow ( columns ) ; } return columns ; } /** Allow setting the column size in any unit */ setColumnWidth ( index , value , unit , columns = this . columns ) { const sizes = [ ... columns ] ; switch ( unit ) { case ColumnUnit . Percentage : sizes [ index ] = value ; break ; case ColumnUnit . Pixel : sizes [ index ] = ( value / this . tableWidth ) * 100 ; break ; } return sizes ; } /** Resize a column by a specific pixel amount */ resizeColumn ( index , delta , isDragging = true ) { const sibling = this . getSiblingColumn ( index ) ; let columns = [ ... this . columns ] as number [ ] ; columns = this . setColumnWidth ( index , Math . round ( this . getColumnWidth ( index , ColumnUnit . Pixel ) + delta ) , ColumnUnit . Pixel ) as number [ ] ; columns = this . setColumnWidth ( sibling , Math . round ( this . getColumnWidth ( sibling , ColumnUnit . Pixel ) ) , ColumnUnit . Pixel , columns ) as number [ ] ; if ( ! this . isWidthValid ( index , this . getColumnWidth ( index , ColumnUnit . Pixel , columns ) ) ) { return ; } this . columns = columns ; this . onResize$ . next ( ) ; } /** Get the next column in the sequence of columns */ private getSiblingColumn ( index ) { for ( let idx = index + 1 ; idx < this . columns . length ; idx ++ ) { const sibling = this . getColumn ( idx ) ; if ( ! sibling || ! sibling . disabled ) { return idx ; } } return null ; } /** Return true if this column is above the minimum width */ private isWidthValid ( index , width ) { const column = this . getColumn ( index ) ; return column && width >= column . minWidth ; } getColumn ( index ) { return this . _columns ? this . _columns . toArray ( ) [ index ] : null ; } getColumnDisabled ( index ) { return this . getColumn ( index ) ? this . getColumn ( index ) . disabled : false ; } } export enum ColumnUnit { Pixel , Percentage }