import { AfterViewInit , Component , ContentChild , ContentChildren , ElementRef , HostBinding , Inject , Input , OnDestroy , Optional , QueryList , Renderer2 , TemplateRef , ViewChildren , ViewEncapsulation } from '@angular/core' ; import { TranslateService } from '@ngx-translate/core' ; import { Observable , Subject } from 'rxjs' ; import { filter , takeUntil } from 'rxjs/operators' ; import { ObMasterLayoutService } from '../master-layout.service' ; import { ObMasterLayoutConfig } from '../master-layout.config' ; import { scrollEnabled } from '../master-layout.utility' ; import { OB_BANNER , WINDOW } from '../../utilities' ; import { ObIBanner } from '../../utilities.model' ; import { ObEMasterLayoutEventValues , ObILocaleObject , ObIMasterLayoutEvent , ObINavigationLink } from '../master-layout.model' ; import { ObScrollingEvents } from '../../scrolling/scrolling-events' ; import { ObGlobalEventsService } from '../../global-events/global-events.service' ; @ Component ( { selector : 'ob-master-layout-header' , templateUrl : './master-layout-header.component.html' , styleUrls : [ './master-layout-header.component.scss' , './master-layout-header.component-controls.scss' ] , encapsulation : ViewEncapsulation . None , host : { class : 'ob-master-layout-header' } } ) export class ObMasterLayoutHeaderComponent implements AfterViewInit , OnDestroy { home$ : Observable < string > ; languages : { code : string ; id ? : string ; } [ ] ; isCustom = this . masterLayout . header . isCustom ; banner : ObIBanner ; @ Input ( ) navigation : ObINavigationLink [ ] ; @ HostBinding ( 'class.ob-master-layout-header-small' ) isSmall = this . masterLayout . header . isSmall ; @ ContentChild ( 'obHeaderLogo' ) readonly obLogo : TemplateRef < any > ; @ ContentChildren ( 'obHeaderControl' ) readonly templates : QueryList < TemplateRef < any > > ; @ ContentChildren ( 'obHeaderMobileControl' ) readonly mobileTemplates : QueryList < TemplateRef < any > > ; @ ViewChildren ( 'headerControl' ) readonly headerControl : QueryList < ElementRef > ; @ ViewChildren ( 'headerMobileControl' ) readonly headerMobileControl : QueryList < ElementRef > ; private readonly unsubscribe = new Subject ( ) ; constructor ( private readonly masterLayout , private readonly translate , private readonly config , private readonly scrollEvents , private readonly el , private readonly renderer , private readonly globalEventsService , @ Inject ( WINDOW ) private readonly window , @ Inject ( OB_BANNER ) @ Optional ( ) bannerToken ) { this . languages = this . formatLanguages ( ) ; this . propertyChanges ( ) ; this . reduceOnScroll ( ) ; this . banner = { color : '#000' , bgColor : '#0f0' , ... bannerToken } ; this . home$ = this . masterLayout . homePageRouteChange$ ; } ngAfterViewInit ( ) { this . globalEventsService . resize$ . pipe ( takeUntil ( this . unsubscribe ) ) . subscribe ( ( ) => this . onResize ( ) ) ; this . setFocusable ( this . masterLayout . layout . isMenuOpened ) ; this . masterLayout . layout . configEvents$ . pipe ( filter ( evt => evt . name === ObEMasterLayoutEventValues . IS_MENU_OPENED ) ) . subscribe ( value => this . setFocusable ( ! value ) ) ; this . headerControl . toArray ( ) . concat ( this . headerMobileControl . toArray ( ) ) . forEach ( elt => this . addActionClass ( elt ) ) ; } ngOnDestroy ( ) { this . unsubscribe . next ( ) ; this . unsubscribe . complete ( ) ; } onResize ( ) { this . setFocusable ( this . masterLayout . layout . isMenuOpened ) ; } isLangActive ( lang ) { return this . translate . currentLang === lang ; } changeLang ( lang ) { this . translate . use ( lang ) ; } private addActionClass ( elt ) { const actionable = [ 'a' , 'button' ] ; if ( actionable . includes ( elt . nativeElement . nodeName . toLowerCase ( ) ) ) { this . renderer . addClass ( elt . nativeElement , 'ob-control-link' ) ; } else { const el = elt . nativeElement . querySelector ( 'a, button' ) ; if ( el ) { this . renderer . addClass ( el , 'ob-control-link' ) ; } } elt . nativeElement . querySelectorAll ( '.ob-control-link .fa, .ob-control-link .fas, .ob-control-link .fab' ) . forEach ( ( item ) => { this . renderer . addClass ( item , 'ob-control-icon' ) ; } ) ; } private reduceOnScroll ( ) { this . scrollEvents . isScrolled . pipe ( takeUntil ( this . unsubscribe ) , scrollEnabled ( this . masterLayout . header ) ) . subscribe ( isScrolling => { this . isSmall = isScrolling ; } ) ; } private propertyChanges ( ) { const events = [ ObEMasterLayoutEventValues . HEADER_IS_CUSTOM , ObEMasterLayoutEventValues . HEADER_IS_SMALL ] ; this . masterLayout . header . configEvents$ . pipe ( filter ( ( evt ) => events . includes ( evt . name ) ) , takeUntil ( this . unsubscribe ) ) . subscribe ( event => { switch ( event . name ) { case ObEMasterLayoutEventValues . HEADER_IS_CUSTOM : this . isCustom = event . value ; break ; case ObEMasterLayoutEventValues . HEADER_IS_SMALL : this . isSmall = event . value ; break ; } } ) ; } private formatLanguages ( ) { return this . config . locale . disabled || ! this . config . locale . display ? [ ] : this . config . locale . locales . map ( locale => ( { code : ( ( locale as ObILocaleObject ) . locale || ( locale as string ) ) . split ( '-' ) [ 0 ] , id : ( locale as ObILocaleObject ) . id } ) ) ; } private setFocusable ( isMenuOpened ) { const isFocusable = this . window . innerWidth > 991 || ! isMenuOpened ; this . el . nativeElement . querySelectorAll ( '.ob-master-layout-header-controls a.ob-control-link' ) . forEach ( el => { this . renderer . setAttribute ( el , 'tabindex' , isFocusable ? '0' : '-1' ) ; } ) ; } }