export class FilterMenu { th : HTMLElement ; tds : Array < HTMLElement > ; column : number ; index : number ; menu : HTMLElement ; inputs : Array < Element > ; selectAllCheckbox : Element ; searchFilter : Element ; options : Options ; target : JQuery ; constructor ( target , th , column , index , options ) { this . options = options ; this . th = th ; this . column = column ; this . index = index ; this . tds = target . find ( 'tbody tr td:nth-child(' + ( this . column + 1 ) + ')' ) . toArray ( ) ; } public initialize ( ) { this . menu = this . dropdownFilterDropdown ( ) ; this . th . appendChild ( this . menu ) ; let $trigger = $ ( this . menu . children [ 0 ] ) ; let $content = $ ( this . menu . children [ 1 ] ) ; let $menu = $ ( this . menu ) ; $trigger . click ( ( ) => $content . toggle ( ) ) ; $ ( document ) . click ( function ( el ) { if ( ! $menu . is ( el . target ) && $menu . has ( el . target ) . length === 0 ) { $content . hide ( ) ; } } ) ; } public searchToggle ( value ) { if ( this . selectAllCheckbox instanceof HTMLInputElement ) this . selectAllCheckbox . checked = false ; if ( value . length === 0 ) { this . toggleAll ( true ) ; if ( this . selectAllCheckbox instanceof HTMLInputElement ) this . selectAllCheckbox . checked = true ; return ; } this . toggleAll ( false ) ; this . inputs . filter ( function ( input ) { return input . value . toLowerCase ( ) . indexOf ( value . toLowerCase ( ) ) > - 1 ; } ) . forEach ( function ( input ) { input . checked = true ; } ) ; } public updateSelectAll ( ) { if ( this . selectAllCheckbox instanceof HTMLInputElement ) { $ ( this . searchFilter ) . val ( '' ) ; this . selectAllCheckbox . checked = ( this . inputs . length === this . inputs . filter ( function ( input ) { return input . checked ; } ) . length ) ; } } public selectAllUpdate ( checked ) { $ ( this . searchFilter ) . val ( '' ) ; this . toggleAll ( checked ) ; } private toggleAll ( checked ) { for ( var i = 0 ; i < this . inputs . length ; i ++ ) { let input = this . inputs [ i ] ; if ( input instanceof HTMLInputElement ) input . checked = checked ; } } private dropdownFilterItem ( td , self ) { let value = td . innerText ; let dropdownFilterItem = document . createElement ( 'div' ) ; dropdownFilterItem . className = 'dropdown-filter-item' ; let input = document . createElement ( 'input' ) ; input . type = 'checkbox' ; input . value = value . trim ( ) . replace ( / +(?= )/g , '' ) ; input . setAttribute ( 'checked' , 'checked' ) ; input . className = 'dropdown-filter-menu-item item' ; input . setAttribute ( 'data-column' , self . column . toString ( ) ) ; input . setAttribute ( 'data-index' , self . index . toString ( ) ) ; dropdownFilterItem . appendChild ( input ) ; dropdownFilterItem . innerHTML = dropdownFilterItem . innerHTML . trim ( ) + ' ' + value ; return dropdownFilterItem ; } private dropdownFilterItemSelectAll ( ) { let value = this . options . captions . select_all ; let dropdownFilterItemSelectAll = document . createElement ( 'div' ) ; dropdownFilterItemSelectAll . className = 'dropdown-filter-item' ; let input = document . createElement ( 'input' ) ; input . type = 'checkbox' ; input . value = this . options . captions . select_all ; input . setAttribute ( 'checked' , 'checked' ) ; input . className = 'dropdown-filter-menu-item select-all' ; input . setAttribute ( 'data-column' , this . column . toString ( ) ) ; input . setAttribute ( 'data-index' , this . index . toString ( ) ) ; dropdownFilterItemSelectAll . appendChild ( input ) ; dropdownFilterItemSelectAll . innerHTML = dropdownFilterItemSelectAll . innerHTML + ' ' + value ; return dropdownFilterItemSelectAll ; } private dropdownFilterSearch ( ) { let dropdownFilterItem = document . createElement ( 'div' ) ; dropdownFilterItem . className = 'dropdown-filter-search' ; let input = document . createElement ( 'input' ) ; input . type = 'text' ; input . className = 'dropdown-filter-menu-search form-control' ; input . setAttribute ( 'data-column' , this . column . toString ( ) ) ; input . setAttribute ( 'data-index' , this . index . toString ( ) ) ; input . setAttribute ( 'placeholder' , this . options . captions . search ) ; dropdownFilterItem . appendChild ( input ) ; return dropdownFilterItem ; } private dropdownFilterSort ( direction ) { let dropdownFilterItem = document . createElement ( 'div' ) ; dropdownFilterItem . className = 'dropdown-filter-sort' ; let span = document . createElement ( 'span' ) ; span . className = direction . toLowerCase ( ) . split ( ' ' ) . join ( '-' ) ; span . setAttribute ( 'data-column' , this . column . toString ( ) ) ; span . setAttribute ( 'data-index' , this . index . toString ( ) ) ; span . innerText = direction ; dropdownFilterItem . appendChild ( span ) ; return dropdownFilterItem ; } private dropdownFilterContent ( ) { let self = this ; let dropdownFilterContent = document . createElement ( 'div' ) ; dropdownFilterContent . className = 'dropdown-filter-content' ; let innerDivs = this . tds . reduce ( function ( arr , el ) { let values = arr . map ( ( el ) => el . innerText . trim ( ) ) ; if ( values . indexOf ( el . innerText . trim ( ) ) < 0 ) arr . push ( el ) ; return arr ; } , [ ] ) . sort ( function ( a , b ) { var A = a . innerText . toLowerCase ( ) ; var B = b . innerText . toLowerCase ( ) ; if ( ! isNaN ( Number ( A ) ) && ! isNaN ( Number ( B ) ) ) { if ( Number ( A ) < Number ( B ) ) return - 1 ; if ( Number ( A ) > Number ( B ) ) return 1 ; } else { if ( A < B ) return - 1 ; if ( A > B ) return 1 ; } return 0 ; } ) . map ( ( td ) => { return this . dropdownFilterItem ( td , self ) ; } ) ; this . inputs = innerDivs . map ( ( div ) => div . firstElementChild ) ; let selectAllCheckboxDiv = this . dropdownFilterItemSelectAll ( ) ; this . selectAllCheckbox = selectAllCheckboxDiv . firstElementChild ; innerDivs . unshift ( selectAllCheckboxDiv ) ; let searchFilterDiv = this . dropdownFilterSearch ( ) ; this . searchFilter = searchFilterDiv . firstElementChild ; let outerDiv = innerDivs . reduce ( function ( outerDiv , innerDiv ) { outerDiv . appendChild ( innerDiv ) ; return outerDiv ; } , document . createElement ( 'div' ) ) ; outerDiv . className = 'checkbox-container' ; let elements = [ ] ; if ( this . options . sort ) elements = elements . concat ( [ this . dropdownFilterSort ( this . options . captions . a_to_z ) , this . dropdownFilterSort ( this . options . captions . z_to_a ) ] ) ; if ( this . options . search ) elements . push ( searchFilterDiv ) ; return elements . concat ( outerDiv ) . reduce ( function ( html , el ) { html . appendChild ( el ) ; return html ; } , dropdownFilterContent ) ; } private dropdownFilterDropdown ( ) { let dropdownFilterDropdown = document . createElement ( 'div' ) ; dropdownFilterDropdown . className = 'dropdown-filter-dropdown' ; let arrow = document . createElement ( 'span' ) ; arrow . className = 'glyphicon glyphicon-arrow-down dropdown-filter-icon' ; let icon = document . createElement ( 'i' ) ; icon . className = 'arrow-down' ; arrow . appendChild ( icon ) ; dropdownFilterDropdown . appendChild ( arrow ) ; dropdownFilterDropdown . appendChild ( this . dropdownFilterContent ( ) ) ; if ( $ ( this . th ) . hasClass ( 'no-sort' ) ) { $ ( dropdownFilterDropdown ) . find ( '.dropdown-filter-sort' ) . remove ( ) ; } if ( $ ( this . th ) . hasClass ( 'no-filter' ) ) { $ ( dropdownFilterDropdown ) . find ( '.checkbox-container' ) . remove ( ) ; } if ( $ ( this . th ) . hasClass ( 'no-search' ) ) { $ ( dropdownFilterDropdown ) . find ( '.dropdown-filter-search' ) . remove ( ) ; } return dropdownFilterDropdown ; } }