import { AEventDispatcher , debounce , ISequence , OrderedSet , IDebounceContext , IEventListener , suffix , IEventContext , } from '../internal' ; import { Column , IColumnConstructor , Ranking , AggregateGroupColumn , createAggregateDesc , IAggregateGroupColumnDesc , isSupportType , EDirtyReason , RankColumn , createRankDesc , createSelectionDesc , IColumnDesc , IDataRow , IGroup , IndicesArray , IOrderedGroup , ISelectionColumnDesc , EAggregationState , IColumnDump , IRankingDump , IColorMappingFunctionConstructor , IMappingFunctionConstructor , ITypeFactory , } from '../model' ; import { models } from '../model/models' ; import { forEachIndices , everyIndices , toGroupID , unifyParents } from '../model/internal' ; import { IDataProvider , IDataProviderDump , IDataProviderOptions , SCHEMA_REF , IExportOptions } from './interfaces' ; import { exportRanking , map2Object , object2Map , exportTable , isPromiseLike } from './utils' ; import type { IRenderTasks } from '../renderer' ; import { restoreCategoricalColorMapping } from '../model/CategoricalColorMappingFunction' ; import { createColorMappingFunction , colorMappingFunctions } from '../model/ColorMappingFunction' ; import { createMappingFunction , mappingFunctions } from '../model/MappingFunction' ; import { convertAggregationState } from './internal' ; asMemberOf event export declare function addColumn ( col , index ) ; asMemberOf event export declare function moveColumn ( col , index , oldIndex ) ; asMemberOf event export declare function removeColumn ( col , index ) ; asMemberOf event export declare function orderChanged ( previous , current , previousGroups , currentGroups , dirtyReason ) ; asMemberOf event export declare function dirty ( ) ; asMemberOf event export declare function dirtyHeader ( ) ; asMemberOf event export declare function dirtyValues ( ) ; asMemberOf event export declare function dirtyCaches ( ) ; asMemberOf param rows event export declare function dataChanged ( rows ) ; asMemberOf param dataIndices event export declare function selectionChanged ( dataIndices ) ; asMemberOf event export declare function addRanking ( ranking , index ) ; asMemberOf param ranking event export declare function removeRanking ( ranking , index ) ; asMemberOf event export declare function addDesc ( desc ) ; asMemberOf event export declare function removeDesc ( desc ) ; asMemberOf event export declare function clearDesc ( ) ; asMemberOf event export declare function showTopNChanged ( previous , current ) ; asMemberOf param dataIndices event export declare function jumpToNearest ( dataIndices ) ; asMemberOf event export declare function aggregate ( ranking , group , previousTopN , currentTopN ) ; asMemberOf event export declare function busy ( busy ) ; function toDirtyReason ( ctx ) { const primary = ctx . primaryType ; switch ( primary || '' ) { case Ranking . EVENT_DIRTY_ORDER : return ctx . args [ 0 ] || [ EDirtyReason . UNKNOWN ] ; case Ranking . EVENT_SORT_CRITERIA_CHANGED : return [ EDirtyReason . SORT_CRITERIA_CHANGED ] ; case Ranking . EVENT_GROUP_CRITERIA_CHANGED : return [ EDirtyReason . GROUP_CRITERIA_CHANGED ] ; case Ranking . EVENT_GROUP_SORT_CRITERIA_CHANGED : return [ EDirtyReason . GROUP_SORT_CRITERIA_CHANGED ] ; default : return [ EDirtyReason . UNKNOWN ] ; } } function mergeDirtyOrderContext ( current , next ) { const currentReason = toDirtyReason ( current . self ) ; const nextReason = toDirtyReason ( next . self ) ; const combined = new Set ( currentReason ) ; for ( const r of nextReason ) { combined . add ( r ) ; } const args = [ Array . from ( combined ) ] ; return { self : { primaryType : Ranking . EVENT_DIRTY_ORDER , args , } , args , } ; } /**
 * a basic data provider holding the data and rankings
 */ abstract class ADataProvider extends AEventDispatcher implements IDataProvider { static readonly EVENT_SELECTION_CHANGED = 'selectionChanged' ; static readonly EVENT_DATA_CHANGED = 'dataChanged' ; static readonly EVENT_ADD_COLUMN = Ranking . EVENT_ADD_COLUMN ; static readonly EVENT_MOVE_COLUMN = Ranking . EVENT_MOVE_COLUMN ; static readonly EVENT_REMOVE_COLUMN = Ranking . EVENT_REMOVE_COLUMN ; static readonly EVENT_ADD_RANKING = 'addRanking' ; static readonly EVENT_REMOVE_RANKING = 'removeRanking' ; static readonly EVENT_DIRTY = Ranking . EVENT_DIRTY ; static readonly EVENT_DIRTY_HEADER = Ranking . EVENT_DIRTY_HEADER ; static readonly EVENT_DIRTY_VALUES = Ranking . EVENT_DIRTY_VALUES ; static readonly EVENT_DIRTY_CACHES = Ranking . EVENT_DIRTY_CACHES ; static readonly EVENT_ORDER_CHANGED = Ranking . EVENT_ORDER_CHANGED ; static readonly EVENT_SHOWTOPN_CHANGED = 'showTopNChanged' ; static readonly EVENT_ADD_DESC = 'addDesc' ; static readonly EVENT_CLEAR_DESC = 'clearDesc' ; static readonly EVENT_REMOVE_DESC = 'removeDesc' ; static readonly EVENT_JUMP_TO_NEAREST = 'jumpToNearest' ; static readonly EVENT_GROUP_AGGREGATION_CHANGED = AggregateGroupColumn . EVENT_AGGREGATE ; static readonly EVENT_BUSY = 'busy' ; private static readonly FORWARD_RANKING_EVENTS = suffix ( '.provider' , Ranking . EVENT_ADD_COLUMN , Ranking . EVENT_REMOVE_COLUMN , Ranking . EVENT_DIRTY , Ranking . EVENT_DIRTY_HEADER , Ranking . EVENT_MOVE_COLUMN , Ranking . EVENT_ORDER_CHANGED , Ranking . EVENT_DIRTY_VALUES , Ranking . EVENT_DIRTY_CACHES ) ; type { Array } private private readonly rankings : Ranking [ ] = [ ] ; type { OrderedSet } private readonly selection = new OrderedSet < number > ( ) ; private readonly aggregations = new Map < string , number > ( ) ; private uid = 0 ; private readonly typeFactory : ITypeFactory ; private readonly options : Readonly < IDataProviderOptions > = { columnTypes : { } , colorMappingFunctionTypes : { } , mappingFunctionTypes : { } , singleSelection : false , showTopN : 10 , aggregationStrategy : 'item' , propagateAggregationState : true , } ; /**
     * lookup map of a column type to its column implementation
     */ readonly columnTypes : { [ columnType ] : IColumnConstructor ; } ; readonly colorMappingFunctionTypes : { [ colorMappingFunctionType ] : IColorMappingFunctionConstructor ; } ; readonly mappingFunctionTypes : { [ mappingFunctionType ] : IMappingFunctionConstructor ; } ; private showTopN : number ; constructor ( options = { } ) { super ( ) ; Object . assign ( this . options , options ) ; this . columnTypes = Object . assign ( models ( ) , this . options . columnTypes ) ; this . colorMappingFunctionTypes = Object . assign ( colorMappingFunctions ( ) , this . options . colorMappingFunctionTypes ) ; this . mappingFunctionTypes = Object . assign ( mappingFunctions ( ) , this . options . mappingFunctionTypes ) ; this . showTopN = this . options . showTopN ; this . typeFactory = this . createTypeFactory ( ) ; } private createTypeFactory ( ) { const factory = ( ( d ) => { const desc = this . fromDescRef ( d . desc ) ; if ( ! desc || ! desc . type ) { console . warn ( 'cannot restore column dump' , d ) ; return new Column ( d . id || '' , d . desc || { } ) ; } this . fixDesc ( desc ) ; const type = this . columnTypes [ desc . type ] ; if ( type == null ) { console . warn ( 'invalid column type in column dump using column' , d ) ; return new Column ( d . id || '' , desc ) ; } const c = this . instantiateColumn ( type , '' , desc , this . typeFactory ) ; c . restore ( d , factory ) ; return c ; } ) as ITypeFactory ; factory . colorMappingFunction = createColorMappingFunction ( this . colorMappingFunctionTypes , factory ) ; factory . mappingFunction = createMappingFunction ( this . mappingFunctionTypes ) ; factory . categoricalColorMappingFunction = restoreCategoricalColorMapping ; return factory ; } getTypeFactory ( ) { return this . typeFactory ; } returns { string [ ] } protected createEventList ( ) { return super . createEventList ( ) . concat ( [ ADataProvider . EVENT_DATA_CHANGED , ADataProvider . EVENT_BUSY , ADataProvider . EVENT_SHOWTOPN_CHANGED , ADataProvider . EVENT_ADD_COLUMN , ADataProvider . EVENT_REMOVE_COLUMN , ADataProvider . EVENT_MOVE_COLUMN , ADataProvider . EVENT_ADD_RANKING , ADataProvider . EVENT_REMOVE_RANKING , ADataProvider . EVENT_DIRTY , ADataProvider . EVENT_DIRTY_HEADER , ADataProvider . EVENT_DIRTY_VALUES , ADataProvider . EVENT_DIRTY_CACHES , ADataProvider . EVENT_ORDER_CHANGED , ADataProvider . EVENT_SELECTION_CHANGED , ADataProvider . EVENT_ADD_DESC , ADataProvider . EVENT_CLEAR_DESC , ADataProvider . EVENT_JUMP_TO_NEAREST , ADataProvider . EVENT_GROUP_AGGREGATION_CHANGED , ] ) ; } on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) { return super . on ( type , listener ) ; } abstract getTotalNumberOfRows ( ) ; returns { Array } abstract getColumns ( ) ; abstract getTaskExecutor ( ) ; param existing return pushRanking ( existing ? ) { const r = this . cloneRanking ( existing ) ; this . insertRanking ( r ) ; return r ; } protected fireBusy ( busy ) { this . fire ( ADataProvider . EVENT_BUSY , busy ) ; } takeSnapshot ( col ) { this . fireBusy ( true ) ; const r = this . cloneRanking ( ) ; const ranking = col . findMyRanker ( ) ; let hasString = col . desc . type === 'string' ; let hasColumn = false ; const toClone = ! ranking ? [ col ] : ranking . children . filter ( ( c ) => { if ( c === col ) { hasColumn = true ; return true ; } if ( ! hasString && c . desc . type === 'string' ) { hasString = true ; return true ; } return isSupportType ( c ) ; } ) ; if ( ! hasColumn ) { toClone . push ( col ) ; } toClone . forEach ( ( c ) => { const clone = this . clone ( c ) ; r . push ( clone ) ; if ( c === col ) { clone . sortByMe ( ) ; } } ) ; this . insertRanking ( r ) ; this . fireBusy ( false ) ; return r ; } insertRanking ( r , index = this . rankings . length ) { this . rankings . splice ( index , 0 , r ) ; this . forward ( r , ... ADataProvider . FORWARD_RANKING_EVENTS ) ; const that = this ; r . on ( `${ Ranking . EVENT_DIRTY_ORDER }.provider` , debounce ( function ( this ) { that . triggerReorder ( r , toDirtyReason ( this ) ) ; } , 100 , mergeDirtyOrderContext ) ) ; this . fire ( [ ADataProvider . EVENT_ADD_RANKING , ADataProvider . EVENT_DIRTY_HEADER , ADataProvider . EVENT_DIRTY_VALUES , ADataProvider . EVENT_DIRTY , ] , r , index ) ; this . triggerReorder ( r ) ; } private triggerReorder ( ranking , dirtyReason ? ) { this . fireBusy ( true ) ; const reason = dirtyReason || [ EDirtyReason . UNKNOWN ] ; Promise . resolve ( this . sort ( ranking , reason ) ) . then ( ( { groups , index2pos } ) => { if ( ranking . getGroupSortCriteria ( ) . length === 0 ) { groups = unifyParents ( groups ) ; } this . initAggregateState ( ranking , groups ) ; ranking . setGroups ( groups , index2pos , reason ) ; this . fireBusy ( false ) ; } ) ; } param ranking returns { boolean } removeRanking ( ranking ) { const i = this . rankings . indexOf ( ranking ) ; if ( i < 0 ) { return false ; } this . unforward ( ranking , ... ADataProvider . FORWARD_RANKING_EVENTS ) ; this . rankings . splice ( i , 1 ) ; ranking . on ( `${ Ranking . EVENT_DIRTY_ORDER }.provider` , null ) ; this . cleanUpRanking ( ranking ) ; this . fire ( [ ADataProvider . EVENT_REMOVE_RANKING , ADataProvider . EVENT_DIRTY_HEADER , ADataProvider . EVENT_DIRTY_VALUES , ADataProvider . EVENT_DIRTY , ] , ranking , i ) ; return true ; } /**
     * removes all rankings
     */ clearRankings ( ) { this . rankings . forEach ( ( ranking ) => { this . unforward ( ranking , ... ADataProvider . FORWARD_RANKING_EVENTS ) ; ranking . on ( `${ Ranking . EVENT_DIRTY_ORDER }.provider` , null ) ; this . cleanUpRanking ( ranking ) ; } ) ; this . rankings . splice ( 0 , this . rankings . length ) ; this . fire ( [ ADataProvider . EVENT_REMOVE_RANKING , ADataProvider . EVENT_DIRTY_HEADER , ADataProvider . EVENT_DIRTY_VALUES , ADataProvider . EVENT_DIRTY , ] , null , - 1 ) ; } clearFilters ( ) { this . rankings . forEach ( ( ranking ) => ranking . clearFilters ( ) ) ; } returns { Ranking [ ] } getRankings ( ) { return this . rankings . slice ( ) ; } returns { Ranking } getFirstRanking ( ) { return this . rankings [ 0 ] || null ; } returns { Ranking } getLastRanking ( ) { return this . rankings [ this . rankings . length - 1 ] ; } ensureOneRanking ( ) { if ( this . rankings . length === 0 ) { const r = this . pushRanking ( ) ; this . push ( r , createRankDesc ( ) ) ; } } destroy ( ) { } param _ranking cleanUpRanking ( _ranking ) { } param existing returns { null } abstract cloneRanking ( existing ? ) ; param ranking param desc return { Column } push ( ranking , desc ) { const r = this . create ( desc ) ; if ( r ) { ranking . push ( r ) ; return r ; } return null ; } param ranking param index param desc return { Column } insert ( ranking , index , desc ) { const r = this . create ( desc ) ; if ( r ) { ranking . insert ( r , index ) ; return r ; } return null ; } returns { string } private nextId ( ) { return `col${ this . uid ++ }` ; } private fixDesc ( desc ) { if ( desc . type === 'selection' ) { ( desc as ISelectionColumnDesc ) . accessor = ( row ) => this . isSelected ( row . i ) ; ( desc as ISelectionColumnDesc ) . setter = ( index , value ) => value ? this . select ( index ) : this . deselect ( index ) ; ( desc as ISelectionColumnDesc ) . setterAll = ( indices , value ) => value ? this . selectAll ( indices ) : this . deselectAll ( indices ) ; } else if ( desc . type === 'aggregate' ) { ( desc as IAggregateGroupColumnDesc ) . isAggregated = ( ranking , group ) => this . getAggregationState ( ranking , group ) ; ( desc as IAggregateGroupColumnDesc ) . setAggregated = ( ranking , group , value ) => this . setAggregationState ( ranking , group , value ) ; } return desc ; } protected cleanDesc ( desc ) { if ( desc . type === 'selection' ) { delete ( desc as ISelectionColumnDesc ) . accessor ; delete ( desc as ISelectionColumnDesc ) . setter ; delete ( desc as ISelectionColumnDesc ) . setterAll ; } else if ( desc . type === 'aggregate' ) { delete ( desc as IAggregateGroupColumnDesc ) . isAggregated ; delete ( desc as IAggregateGroupColumnDesc ) . setAggregated ; } return desc ; } param desc returns { Column } create ( desc ) { this . fixDesc ( desc ) ; const type = this . columnTypes [ desc . type ] ; if ( type ) { return this . instantiateColumn ( type , this . nextId ( ) , desc , this . typeFactory ) ; } return null ; } protected instantiateColumn ( type , id , desc , typeFactory ) { return new type ( id , desc , typeFactory ) ; } param col returns { Column } clone ( col ) { const dump = this . dumpColumn ( col ) ; return this . restoreColumn ( dump ) ; } param dump returns { Column } restoreColumn ( dump ) { const c = this . typeFactory ( dump ) ; c . assignNewId ( this . nextId . bind ( this ) ) ; return c ; } param idOrFilter returns { Column } find ( idOrFilter ) { const filter = typeof idOrFilter === 'string' ? ( col ) => col . id === idOrFilter : idOrFilter ; for ( const ranking of this . rankings ) { const r = ranking . find ( filter ) ; if ( r ) { return r ; } } return null ; } returns { { uid : number , selection : number [ ] , rankings : * [ ] } } dump ( ) { return { $schema : SCHEMA_REF , uid : this . uid , selection : this . getSelection ( ) , aggregations : map2Object ( this . aggregations ) , rankings : this . rankings . map ( ( r ) => r . dump ( this . toDescRef . bind ( this ) ) ) , showTopN : this . showTopN , } ; } /**
     * dumps a specific column
     */ dumpColumn ( col ) { return col . dump ( this . toDescRef . bind ( this ) ) ; } /**
     * for better dumping describe reference, by default just return the description
     */ toDescRef ( desc ) { return desc ; } /**
     * inverse operation of toDescRef
     */ fromDescRef ( descRef ) { return descRef ; } restoreRanking ( dump ) { const ranking = this . cloneRanking ( ) ; ranking . restore ( dump , this . typeFactory ) ; const idGenerator = this . nextId . bind ( this ) ; ranking . children . forEach ( ( c ) => c . assignNewId ( idGenerator ) ) ; return ranking ; } restore ( dump ) { this . clearRankings ( ) ; this . uid = dump . uid || 0 ; if ( dump . selection ) { dump . selection . forEach ( ( s ) => this . selection . add ( s ) ) ; } if ( dump . showTopN != null ) { this . showTopN = dump . showTopN ; } if ( dump . aggregations ) { this . aggregations . clear ( ) ; if ( Array . isArray ( dump . aggregations ) ) { dump . aggregations . forEach ( ( a ) => this . aggregations . set ( a , 0 ) ) ; } else { object2Map ( dump . aggregations ) . forEach ( ( v , k ) => this . aggregations . set ( k , v ) ) ; } } if ( dump . rankings ) { dump . rankings . forEach ( ( r ) => { const ranking = this . cloneRanking ( ) ; ranking . restore ( r , this . typeFactory ) ; if ( ! ranking . children . some ( ( d ) => d instanceof RankColumn ) ) { ranking . insert ( this . create ( createRankDesc ( ) ) ! , 0 ) ; } this . insertRanking ( ranking ) ; } ) ; } const idGenerator = this . nextId . bind ( this ) ; this . rankings . forEach ( ( r ) => { r . children . forEach ( ( c ) => c . assignNewId ( idGenerator ) ) ; } ) ; } abstract findDesc ( ref ) ; /**
     * generates a default ranking by using all column descriptions ones
     */ deriveDefault ( addSupportType = true ) { const r = this . pushRanking ( ) ; if ( addSupportType ) { r . push ( this . create ( createAggregateDesc ( ) ) ! ) ; r . push ( this . create ( createRankDesc ( ) ) ! ) ; if ( this . options . singleSelection !== true ) { r . push ( this . create ( createSelectionDesc ( ) ) ! ) ; } } this . getColumns ( ) . forEach ( ( col ) => { const c = this . create ( col ) ; if ( ! c || isSupportType ( c ) ) { return ; } r . push ( c ) ; } ) ; return r ; } isAggregated ( ranking , group ) { return this . getTopNAggregated ( ranking , group ) >= 0 ; } getAggregationState ( ranking , group ) { const n = this . getTopNAggregated ( ranking , group ) ; return n < 0 ? EAggregationState . EXPAND : n === 0 ? EAggregationState . COLLAPSE : EAggregationState . EXPAND_TOP_N ; } setAggregated ( ranking , group , value ) { return this . setAggregationState ( ranking , group , value ? EAggregationState . COLLAPSE : EAggregationState . EXPAND ) ; } setAggregationState ( ranking , group , value ) { this . setTopNAggregated ( ranking , group , value === EAggregationState . COLLAPSE ? 0 : value === EAggregationState . EXPAND_TOP_N ? this . showTopN : - 1 ) ; } getTopNAggregated ( ranking , group ) { let g = group ; while ( g ) { const key = `${ ranking . id }@${ toGroupID ( g ) }` ; if ( this . aggregations . has ( key ) ) { const v = this . aggregations . get ( key ) ! ; if ( this . options . propagateAggregationState && group !== g ) { this . aggregations . set ( `${ ranking . id }@${ toGroupID ( group ) }` , v ) ; } return v ; } g = g . parent ; } return - 1 ; } private unaggregateParents ( ranking , group ) { let g = group . parent ; let changed = false ; while ( g ) { changed = this . aggregations . delete ( `${ ranking . id }@${ toGroupID ( g ) }` ) || changed ; g = g . parent ; } return changed ; } getAggregationStrategy ( ) { return this . options . aggregationStrategy ; } private initAggregateState ( ranking , groups ) { let initial = - 1 ; switch ( this . getAggregationStrategy ( ) ) { case 'group' : initial = 0 ; break ; case 'item' : case 'group+item' : case 'group+item+top' : initial = - 1 ; break ; case 'group+top+item' : initial = this . showTopN ; break ; } for ( const group of groups ) { const key = `${ ranking . id }@${ toGroupID ( group ) }` ; if ( ! this . aggregations . has ( key ) && initial >= 0 ) { this . aggregations . set ( key , initial ) ; } } } setTopNAggregated ( ranking , group , value ) { const groups = Array . isArray ( group ) ? group : [ group ] ; const changed = [ ] ; const previous = [ ] ; let changedParents = false ; for ( let i = 0 ; i < groups . length ; i ++ ) { const group = groups [ i ] ; const target = typeof value === 'number' ? value : value [ i ] ; changedParents = this . unaggregateParents ( ranking , group ) || changedParents ; const current = this . getTopNAggregated ( ranking , group ) ; if ( current === target ) { continue ; } changed . push ( group ) ; previous . push ( current ) ; const key = `${ ranking . id }@${ toGroupID ( group ) }` ; if ( target >= 0 ) { this . aggregations . set ( key , target ) ; } else { this . aggregations . delete ( key ) ; } } if ( ! changedParents && changed . length === 0 ) { return ; } if ( ! Array . isArray ( group ) ) { this . fire ( [ ADataProvider . EVENT_GROUP_AGGREGATION_CHANGED , ADataProvider . EVENT_DIRTY_VALUES , ADataProvider . EVENT_DIRTY ] , ranking , group , previous . length === 0 ? value : previous [ 0 ] , value ) ; } else { this . fire ( [ ADataProvider . EVENT_GROUP_AGGREGATION_CHANGED , ADataProvider . EVENT_DIRTY_VALUES , ADataProvider . EVENT_DIRTY ] , ranking , group , previous , value ) ; } } aggregateAllOf ( ranking , aggregateAll , groups = ranking . getGroups ( ) ) { const value = convertAggregationState ( aggregateAll , this . showTopN ) ; this . setTopNAggregated ( ranking , groups , value ) ; } getShowTopN ( ) { return this . showTopN ; } setShowTopN ( value ) { if ( this . showTopN === value ) { return ; } for ( const [ k , v ] of Array . from ( this . aggregations . entries ( ) ) ) { if ( v === this . showTopN ) { this . aggregations . set ( k , value ) ; } } this . fire ( [ ADataProvider . EVENT_SHOWTOPN_CHANGED , ADataProvider . EVENT_DIRTY_VALUES , ADataProvider . EVENT_DIRTY ] , this . showTopN , ( this . showTopN = value ) ) ; } param ranking return { Promise < any > } abstract sort ( ranking , dirtyReason ) ; param indices return { Promise < any > } abstract view ( indices ) ; abstract getRow ( index ) ; param col return { Promise < any > } abstract mappingSample ( col ) ; param index return { boolean } isSelected ( index ) { return this . selection . has ( index ) ; } param index select ( index ) { if ( this . selection . has ( index ) ) { return ; } if ( this . options . singleSelection === true && this . selection . size > 0 ) { this . selection . clear ( ) ; } this . selection . add ( index ) ; this . fire ( ADataProvider . EVENT_SELECTION_CHANGED , this . getSelection ( ) ) ; } param search param col abstract searchAndJump ( search , col ) ; jumpToNearest ( indices ) { if ( indices . length === 0 ) { return ; } this . fire ( ADataProvider . EVENT_JUMP_TO_NEAREST , indices ) ; } param indices selectAll ( indices ) { if ( everyIndices ( indices , ( i ) => this . selection . has ( i ) ) ) { return ; } if ( this . options . singleSelection === true ) { this . selection . clear ( ) ; if ( indices . length > 0 ) { this . selection . add ( indices [ 0 ] ) ; } } else { forEachIndices ( indices , ( index ) => { this . selection . add ( index ) ; } ) ; } this . fire ( ADataProvider . EVENT_SELECTION_CHANGED , this . getSelection ( ) ) ; } selectAllOf ( ranking ) { this . setSelection ( Array . from ( ranking . getOrder ( ) ) ) ; } param indices setSelection ( indices ) { if ( indices . length === 0 ) { return this . clearSelection ( ) ; } if ( this . selection . size === indices . length && indices . every ( ( i ) => this . selection . has ( i ) ) ) { return ; } this . selection . clear ( ) ; this . selectAll ( indices ) ; } param index param additional returns { boolean } toggleSelection ( index , additional = false ) { if ( this . isSelected ( index ) ) { if ( additional ) { this . deselect ( index ) ; } else { this . clearSelection ( ) ; } return false ; } if ( additional ) { this . select ( index ) ; } else { this . setSelection ( [ index ] ) ; } return true ; } param index deselect ( index ) { if ( ! this . selection . has ( index ) ) { return ; } this . selection . delete ( index ) ; this . fire ( ADataProvider . EVENT_SELECTION_CHANGED , this . getSelection ( ) ) ; } param indices deselectAll ( indices ) { if ( everyIndices ( indices , ( i ) => ! this . selection . has ( i ) ) ) { return ; } forEachIndices ( indices , ( index ) => { this . selection . delete ( index ) ; } ) ; this . fire ( ADataProvider . EVENT_SELECTION_CHANGED , this . getSelection ( ) ) ; } return { Promise < any [ ] > } selectedRows ( ) { if ( this . selection . size === 0 ) { return [ ] ; } return this . view ( this . getSelection ( ) ) ; } returns { Array } getSelection ( ) { return Array . from ( this . selection ) ; } /**
     * clears the selection
     */ clearSelection ( ) { if ( this . selection . size === 0 ) { return ; } this . selection . clear ( ) ; this . fire ( ADataProvider . EVENT_SELECTION_CHANGED , [ ] , false ) ; } param ranking param options returns { Promise < string > } exportTable ( ranking , options = { } ) { const data = this . view ( ranking . getOrder ( ) ) ; if ( isPromiseLike ( data ) ) { return data . then ( ( dataImpl ) => exportRanking ( ranking , dataImpl , options ) ) ; } return exportRanking ( ranking , data , options ) ; } param ranking param options returns { Promise < string > } exportSelection ( options = { } ) { const selection = this . getSelection ( ) ; const ranking = options . ranking || this . getFirstRanking ( ) ; if ( ! ranking ) { return '' ; } const rows = selection . map ( ( s ) => this . getRow ( s ) ) ; if ( rows . some ( ( row ) => isPromiseLike ( row ) ) ) { return Promise . all ( rows ) . then ( ( data ) => { return exportTable ( ranking , data , options ) ; } ) ; } return exportTable ( ranking , rows as IDataRow [ ] , options ) ; } } export default ADataProvider ;