fuse-angular/src/app/main/navbar/vertical/navbar-vertical.component.ts

280 lines
7.4 KiB
TypeScript

import { Component, ElementRef, HostBinding, HostListener, Input, OnDestroy, OnInit, Renderer2, ViewChild, ViewEncapsulation } from '@angular/core';
import { Subscription } from 'rxjs/Subscription';
import { FuseMatchMedia } from '../../../core/services/match-media.service';
import { FuseNavbarVerticalService } from './navbar-vertical.service';
import { ObservableMedia } from '@angular/flex-layout';
import { FuseMainComponent } from '../../main.component';
import { NavigationEnd, Router } from '@angular/router';
import { FuseNavigationService } from '../../../core/components/navigation/navigation.service';
import { FusePerfectScrollbarDirective } from '../../../core/directives/fuse-perfect-scrollbar/fuse-perfect-scrollbar.directive';
import { animate, AnimationBuilder, AnimationPlayer, style } from '@angular/animations';
@Component({
selector : 'fuse-navbar-vertical',
templateUrl : './navbar-vertical.component.html',
styleUrls : ['./navbar-vertical.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class FuseNavbarVerticalComponent implements OnInit, OnDestroy
{
private _backdropElement: HTMLElement | null = null;
private _folded = false;
@HostBinding('class.close') isClosed: boolean;
@HostBinding('class.folded') isFoldedActive: boolean;
@HostBinding('class.folded-open') isFoldedOpen: boolean;
@HostBinding('class.initialized') initialized: boolean;
@ViewChild(FusePerfectScrollbarDirective) fusePerfectScrollbarDirective;
@Input()
set folded(value: boolean)
{
this._folded = value;
if ( this._folded )
{
this.activateFolded();
}
else
{
this.deActivateFolded();
}
}
get folded(): boolean
{
return this._folded;
}
matchMediaWatcher: Subscription;
navigationServiceWatcher: Subscription;
fusePerfectScrollbarUpdateTimeout;
player: AnimationPlayer;
constructor(
private fuseMainComponent: FuseMainComponent,
private fuseMatchMedia: FuseMatchMedia,
private fuseNavigationService: FuseNavigationService,
private navBarService: FuseNavbarVerticalService,
public media: ObservableMedia,
private router: Router,
private _renderer: Renderer2,
private _elementRef: ElementRef,
private animationBuilder: AnimationBuilder
)
{
navBarService.setNavBar(this);
this.navigationServiceWatcher =
this.fuseNavigationService.onNavCollapseToggle.subscribe(() => {
this.fusePerfectScrollbarUpdateTimeout = setTimeout(() => {
this.fusePerfectScrollbarDirective.update();
}, 310);
});
this.matchMediaWatcher =
this.fuseMatchMedia.onMediaChange
.subscribe((mediaStep) => {
setTimeout(() => {
if ( this.media.isActive('lt-lg') )
{
this.closeBar();
this.deActivateFolded();
}
else
{
this.openBar();
this._detachBackdrop();
}
});
});
router.events.subscribe(
(event) => {
if ( event instanceof NavigationEnd )
{
if ( this.media.isActive('lt-lg') )
{
setTimeout(() => {
this.closeBar();
});
}
}
}
);
}
ngOnInit()
{
this.isClosed = false;
this.isFoldedActive = this._folded;
this.isFoldedOpen = false;
this.initialized = false;
this.updateCssClasses();
setTimeout(() => {
this.initialized = true;
});
if ( this.media.isActive('lt-lg') )
{
this.closeBar();
this.deActivateFolded();
}
else
{
if ( !this._folded )
{
this.deActivateFolded();
}
else
{
this.activateFolded();
}
}
}
ngOnDestroy()
{
clearTimeout(this.fusePerfectScrollbarUpdateTimeout);
this.matchMediaWatcher.unsubscribe();
this.navigationServiceWatcher.unsubscribe();
}
openBar()
{
if ( !this.isClosed )
{
return;
}
this.isClosed = false;
this.updateCssClasses();
if ( this.media.isActive('lt-lg') )
{
this._attachBackdrop();
}
}
closeBar()
{
if ( this.isClosed )
{
return;
}
this.isClosed = true;
this.updateCssClasses();
this._detachBackdrop();
}
toggleBar()
{
if ( this.isClosed )
{
this.openBar();
}
else
{
this.closeBar();
}
}
toggleFold()
{
if ( !this.isFoldedActive )
{
this.activateFolded();
}
else
{
this.deActivateFolded();
}
}
activateFolded()
{
this.isFoldedActive = true;
this.fuseMainComponent.addClass('fuse-nav-bar-folded');
this.isFoldedOpen = false;
}
deActivateFolded()
{
this.isFoldedActive = false;
this.fuseMainComponent.removeClass('fuse-nav-bar-folded');
this.isFoldedOpen = false;
}
@HostListener('mouseenter')
onMouseEnter()
{
this.isFoldedOpen = true;
}
@HostListener('mouseleave')
onMouseLeave()
{
this.isFoldedOpen = false;
}
updateCssClasses()
{
if ( this.isClosed )
{
this.fuseMainComponent.addClass('fuse-nav-bar-opened');
this.fuseMainComponent.removeClass('fuse-nav-bar-closed');
}
else
{
this.fuseMainComponent.addClass('fuse-nav-bar-closed');
this.fuseMainComponent.removeClass('fuse-nav-bar-opened');
}
}
private _attachBackdrop()
{
this._backdropElement = this._renderer.createElement('div');
this._backdropElement.classList.add('fuse-navbar-backdrop');
this._renderer.appendChild(this._elementRef.nativeElement.parentElement, this._backdropElement);
this.player =
this.animationBuilder
.build([
animate('400ms ease', style({opacity: 1}))
]).create(this._backdropElement);
this.player.play();
this._backdropElement.addEventListener('click', () => {
this.closeBar();
}
);
}
private _detachBackdrop()
{
if ( this._backdropElement )
{
this.player =
this.animationBuilder
.build([
animate('400ms cubic-bezier(.25,.8,.25,1)', style({opacity: 0}))
]).create(this._backdropElement);
this.player.play();
this.player.onDone(() => {
if ( this._backdropElement )
{
this._backdropElement.parentNode.removeChild(this._backdropElement);
this._backdropElement = null;
}
});
}
}
}