module Sfx { export class DetailListDirective implements ng . IDirective { public restrict = "E" ; public replace = true ; public controller = DetailListController ; public controllerAs = "ctrl" ; public templateUrl = "partials/detail-list.html" ; public scope = { list : "=" , listSettings : "=" , innerScroll : "=?" , searchText : "=?" } ; public transclude = true ; public link ( $scope , element , attributes , ctrl ) { $scope . $watchCollection ( "list" , ( ) => { if ( $scope . list && ! angular . isDefined ( $scope . list . isRefreshing ) ) { ctrl . updateList ( ) ; } } ) ; $scope . $watch ( "list.isInitialized" , ( newVal , oldVal ) => { if ( $scope . list && newVal === false && oldVal === true ) { ctrl . updateList ( ) ; } } ) ; $scope . $watch ( "list.isRefreshing" , ( ) => { if ( $scope . list && angular . isDefined ( $scope . list . isRefreshing ) && ! $scope . list . isRefreshing ) { ctrl . updateList ( ) ; } } ) ; $scope . $watch ( "listSettings.search" , ( searchText ) => { if ( searchText !== undefined ) { ctrl . updateList ( ) ; } } ) ; } } export class DetailListController { public static $inject = [ "$filter" , "$scope" ] ; public constructor ( private $filter , public $scope ) { } public updateList ( ) { if ( this . $scope . list ) { this . $scope . sortedFilteredList = this . getSortedFilteredList ( ) ; this . $scope . listSettings . count = this . $scope . sortedFilteredList . length ; } } public handleClickRow ( item , event ) { if ( event && event . target !== event . currentTarget ) { return ; } if ( this . $scope . listSettings . secondRowCollapsible && this . $scope . listSettings . showSecondRow ( item ) ) { item . isSecondRowCollapsed = ! item . isSecondRowCollapsed ; } } private getSortedFilteredList ( ) { let list = this . $scope . list . collection || this . $scope . list ; if ( _ . isEmpty ( list ) ) { return list ; } if ( this . $scope . listSettings . hasEnabledFilters || this . $scope . listSettings . search ) { let pluckedList = _ . map ( list , item => { let pluckedObj = this . $scope . listSettings . getPluckedObject ( item ) ; pluckedObj [ "$originalItem" ] = item ; return pluckedObj ; } ) ; pluckedList = this . filterOnColumns ( pluckedList , this . $scope . listSettings ) ; if ( this . $scope . listSettings . search ) { let keywords = this . $scope . listSettings . search . trim ( ) . split ( /\s+/ ) ; _ . forEach ( keywords , keyword => { pluckedList = this . $filter ( "filter" ) ( pluckedList , keyword ) ; } ) ; } list = _ . map ( pluckedList , pluckedObj => pluckedObj [ "$originalItem" ] ) ; } if ( ! _ . isEmpty ( this . $scope . listSettings . sortPropertyPaths ) ) { list = this . $filter ( "orderBy" ) ( list , this . $scope . listSettings . sortPropertyPaths , this . $scope . listSettings . sortReverse ) ; } return list ; } private filterOnColumns ( pluckedList , listSettings ) { let filterMark = new Array ( pluckedList . length ) ; _ . fill ( filterMark , true ) ; _ . forEach ( listSettings . columnSettings , ( columnSetting ) => { if ( ! columnSetting . enableFilter ) { return ; } let hasEffectiveFilters = _ . some ( columnSetting . filterValues , filterValue => ! filterValue . isChecked ) ; let checkedValues = _ . map ( _ . filter ( columnSetting . filterValues , filterValue => filterValue . isChecked ) , "value" ) ; columnSetting . filterValues = _ . sortBy ( _ . union ( _ . map ( _ . filter ( _ . uniq ( _ . filter ( _ . map ( pluckedList , ( item , index ) => { let targetPropertyTextValue = item [ columnSetting . propertyPath ] ; filterMark [ index ] = filterMark [ index ] && ( ! hasEffectiveFilters || ! targetPropertyTextValue || _ . includes ( checkedValues , targetPropertyTextValue ) ) ; return targetPropertyTextValue ; } ) , value => ! _ . isEmpty ( value ) ) ) , value => _ . every ( columnSetting . filterValues , filterValue => filterValue . value !== value ) ) , value => new FilterValue ( value ) ) , columnSetting . filterValues ) , "value" ) ; } ) ; pluckedList = _ . filter ( pluckedList , ( item , index ) => filterMark [ index ] ) ; return pluckedList ; } } }