UNPKG

@ohayojp.com/components

Version:

Common business components of ohayojp.

585 lines (579 loc) 21.1 kB
import { __decorate, __metadata } from 'tslib'; import { DOCUMENT, CommonModule } from '@angular/common'; import { EventEmitter, Component, ChangeDetectionStrategy, ViewEncapsulation, Renderer2, ChangeDetectorRef, NgZone, Inject, Input, Output, NgModule } from '@angular/core'; import { DomSanitizer } from '@angular/platform-browser'; import { NavigationEnd, Router, RouterModule } from '@angular/router'; import { MenuService, SettingsService, WINDOW } from '@ohayojp.com/theme'; import { InputBoolean, InputNumber, OhayoUtilModule } from '@ohayojp.com/util'; import { Subject } from 'rxjs'; import { takeUntil, filter } from 'rxjs/operators'; import { NzIconModule } from 'ng-zorro-antd/icon'; import { NzToolTipModule } from 'ng-zorro-antd/tooltip'; /** * @fileoverview added by tsickle * Generated from: sidebar-nav.component.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** @type {?} */ const SHOWCLS = 'sidebar-nav__floating-show'; /** @type {?} */ const FLOATINGCLS = 'sidebar-nav__floating'; class SidebarNavComponent { /** * @param {?} menuSrv * @param {?} settings * @param {?} router * @param {?} render * @param {?} cdr * @param {?} ngZone * @param {?} sanitizer * @param {?} doc * @param {?} win */ constructor(menuSrv, settings, router, render, cdr, ngZone, sanitizer, doc, win) { this.menuSrv = menuSrv; this.settings = settings; this.router = router; this.render = render; this.cdr = cdr; this.ngZone = ngZone; this.sanitizer = sanitizer; this.doc = doc; this.win = win; this.unsubscribe$ = new Subject(); this.list = []; this.disabledAcl = false; this.autoCloseUnderPad = true; this.recursivePath = true; this.openStrictly = false; this.maxLevelIcon = 3; // tslint:disable-next-line:no-output-native this.select = new EventEmitter(); } /** * @return {?} */ get collapsed() { return this.settings.layout.collapsed; } /** * @private * @param {?} node * @return {?} */ getLinkNode(node) { node = node.nodeName === 'A' ? node : ((/** @type {?} */ (node.parentNode))); return node.nodeName !== 'A' ? null : node; } /** * @private * @param {?} e * @return {?} */ floatingClickHandle(e) { e.stopPropagation(); /** @type {?} */ const linkNode = this.getLinkNode((/** @type {?} */ (e.target))); if (linkNode == null) { return false; } /** @type {?} */ const id = +(/** @type {?} */ ((/** @type {?} */ (linkNode.dataset)).id)); // Should be ingore children title trigger event if (isNaN(id)) { return false; } /** @type {?} */ let item; this.menuSrv.visit(this.list, (/** * @param {?} i * @return {?} */ (i) => { if (!item && i._id === id) { item = i; } })); this.to((/** @type {?} */ (item))); this.hideAll(); e.preventDefault(); return false; } /** * @private * @return {?} */ clearFloating() { if (!this.floatingEl) return; this.floatingEl.removeEventListener('click', this.floatingClickHandle.bind(this)); // fix ie: https://github.com/ohayojp/ohayo/issues/52 if (this.floatingEl.hasOwnProperty('remove')) { this.floatingEl.remove(); } else if (this.floatingEl.parentNode) { this.floatingEl.parentNode.removeChild(this.floatingEl); } } /** * @private * @return {?} */ genFloating() { this.clearFloating(); this.floatingEl = this.render.createElement('div'); this.floatingEl.classList.add(FLOATINGCLS + '-container'); this.floatingEl.addEventListener('click', this.floatingClickHandle.bind(this), false); this.bodyEl.appendChild(this.floatingEl); } /** * @private * @param {?} linkNode * @param {?} item * @return {?} */ genSubNode(linkNode, item) { /** @type {?} */ const id = `_sidebar-nav-${item._id}`; /** @type {?} */ const childNode = item.badge ? (/** @type {?} */ ((/** @type {?} */ (linkNode.nextElementSibling)).nextElementSibling)) : (/** @type {?} */ (linkNode.nextElementSibling)); /** @type {?} */ const node = (/** @type {?} */ (childNode.cloneNode(true))); node.id = id; node.classList.add(FLOATINGCLS); node.addEventListener('mouseleave', (/** * @return {?} */ () => { node.classList.remove(SHOWCLS); }), false); this.floatingEl.appendChild(node); return node; } /** * @private * @return {?} */ hideAll() { /** @type {?} */ const allNode = this.floatingEl.querySelectorAll('.' + FLOATINGCLS); // tslint:disable-next-line:prefer-for-of for (let i = 0; i < allNode.length; i++) { allNode[i].classList.remove(SHOWCLS); } } // calculate the node position values. /** * @private * @param {?} linkNode * @param {?} node * @return {?} */ calPos(linkNode, node) { /** @type {?} */ const rect = linkNode.getBoundingClientRect(); // bug: https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/14721015/ /** @type {?} */ const scrollTop = Math.max(this.doc.documentElement.scrollTop, this.bodyEl.scrollTop); /** @type {?} */ const docHeight = Math.max(this.doc.documentElement.clientHeight, this.bodyEl.clientHeight); /** @type {?} */ const spacing = 5; /** @type {?} */ let offsetHeight = -spacing; if (docHeight < rect.top + node.clientHeight) { offsetHeight = rect.top + node.clientHeight - docHeight + spacing; } node.style.top = `${rect.top + scrollTop - offsetHeight}px`; node.style.left = `${rect.right + spacing}px`; } /** * @param {?} e * @param {?} item * @return {?} */ showSubMenu(e, item) { if (this.collapsed !== true) { return; } this.ngZone.runOutsideAngular((/** * @return {?} */ () => { e.preventDefault(); /** @type {?} */ const linkNode = (/** @type {?} */ (e.target)); this.genFloating(); /** @type {?} */ const subNode = this.genSubNode((/** @type {?} */ (linkNode)), item); this.hideAll(); subNode.classList.add(SHOWCLS); this.calPos((/** @type {?} */ (linkNode)), subNode); })); } /** * @param {?} item * @return {?} */ to(item) { this.select.emit(item); if (item.disabled) return; if (item.externalLink) { if (item.target === '_blank') { this.win.open(item.externalLink); } else { this.win.location.href = item.externalLink; } return; } this.ngZone.run((/** * @return {?} */ () => this.router.navigateByUrl((/** @type {?} */ (item.link))))); } /** * @param {?} item * @return {?} */ toggleOpen(item) { if (!this.openStrictly) { this.menuSrv.visit(this.list, (/** * @param {?} i * @return {?} */ (i) => { if (i !== item) i._open = false; })); /** @type {?} */ let pItem = (/** @type {?} */ (item._parent)); while (pItem) { pItem._open = true; pItem = (/** @type {?} */ (pItem._parent)); } } item._open = !item._open; this.cdr.markForCheck(); } /** * @return {?} */ _click() { if (this.isPad && this.collapsed) { this.openAside(false); this.hideAll(); } } /** * @return {?} */ _docClick() { if (this.collapsed) { this.hideAll(); } } /** * @private * @param {?} url * @return {?} */ openedByUrl(url) { const { menuSrv, recursivePath, openStrictly } = this; /** @type {?} */ let findItem = menuSrv.getHit(this.menuSrv.menus, (/** @type {?} */ (url)), recursivePath, (/** * @param {?} i * @return {?} */ (i) => { i._selected = false; if (!openStrictly) { i._open = false; } })); if (findItem == null) return; do { findItem._selected = true; if (!openStrictly) { findItem._open = true; } findItem = (/** @type {?} */ (findItem._parent)); } while (findItem); } /** * @return {?} */ ngOnInit() { const { doc, router, unsubscribe$, menuSrv, settings, cdr } = this; this.bodyEl = doc.querySelector('body'); this.openedByUrl(router.url); this.ngZone.runOutsideAngular((/** * @return {?} */ () => this.genFloating())); menuSrv.change.pipe(takeUntil(unsubscribe$)).subscribe((/** * @param {?} data * @return {?} */ data => { menuSrv.visit(data, (/** * @param {?} i * @param {?} _p * @param {?} depth * @return {?} */ (i, _p, depth) => { i._text = this.sanitizer.bypassSecurityTrustHtml((/** @type {?} */ (i.text))); i._needIcon = (/** @type {?} */ (depth)) <= this.maxLevelIcon && !!i.icon; if (!i._aclResult) { if (this.disabledAcl) { i.disabled = true; } else { i._hidden = true; } } if (this.openStrictly) { i._open = i.open != null ? i.open : false; } })); this.list = menuSrv.menus.filter((/** * @param {?} w * @return {?} */ (w) => w._hidden !== true)); cdr.detectChanges(); })); router.events.pipe(takeUntil(unsubscribe$)).subscribe((/** * @param {?} e * @return {?} */ e => { if (e instanceof NavigationEnd) { this.openedByUrl(e.urlAfterRedirects); this.underPad(); this.cdr.detectChanges(); } })); settings.notify .pipe(takeUntil(unsubscribe$), filter((/** * @param {?} t * @return {?} */ t => t.type === 'layout' && t.name === 'collapsed'))) .subscribe((/** * @return {?} */ () => this.clearFloating())); this.underPad(); } /** * @return {?} */ ngOnDestroy() { const { unsubscribe$ } = this; unsubscribe$.next(); unsubscribe$.complete(); this.clearFloating(); } // #region Under pad /** * @private * @return {?} */ get isPad() { return window.innerWidth < 768; } /** * @private * @return {?} */ underPad() { if (this.autoCloseUnderPad && this.isPad && !this.collapsed) { setTimeout((/** * @return {?} */ () => this.openAside(true))); } } /** * @private * @param {?} status * @return {?} */ openAside(status) { this.settings.setLayout('collapsed', status); } } SidebarNavComponent.decorators = [ { type: Component, args: [{ selector: 'sidebar-nav', exportAs: 'sidebarNav', template: "<ng-template #icon let-i>\n <ng-container *ngIf=\"i\" [ngSwitch]=\"i.type\">\n <i\n *ngSwitchCase=\"'icon'\"\n class=\"sidebar-nav__item-icon\"\n nz-icon\n [nzType]=\"i.value\"\n [nzTheme]=\"i.theme\"\n [nzSpin]=\"i.spin\"\n [nzTwotoneColor]=\"i.twoToneColor\"\n [nzIconfont]=\"i.iconfont\"\n [nzRotate]=\"i.rotate\"\n ></i>\n <i *ngSwitchCase=\"'iconfont'\" class=\"sidebar-nav__item-icon\" nz-icon [nzIconfont]=\"i.iconfont\"></i>\n <img *ngSwitchCase=\"'img'\" [src]=\"i.value\" class=\"sidebar-nav__item-icon sidebar-nav__item-img\" />\n <i *ngSwitchDefault class=\"sidebar-nav__item-icon {{ i.value }}\"></i>\n </ng-container>\n</ng-template>\n<ng-template #tree let-ls>\n <ng-container *ngFor=\"let i of ls\">\n <li *ngIf=\"i._hidden !== true\" class=\"sidebar-nav__item\" [class.sidebar-nav__selected]=\"i._selected\" [class.sidebar-nav__open]=\"i._open\">\n <!-- link -->\n <a\n *ngIf=\"i.children.length === 0\"\n (click)=\"to(i)\"\n [attr.data-id]=\"i._id\"\n class=\"sidebar-nav__item-link\"\n [ngClass]=\"{ 'sidebar-nav__item-disabled': i.disabled }\"\n >\n <ng-container *ngIf=\"i._needIcon\">\n <ng-container *ngIf=\"!collapsed\">\n <ng-template [ngTemplateOutlet]=\"icon\" [ngTemplateOutletContext]=\"{ $implicit: i.icon }\"></ng-template>\n </ng-container>\n <span *ngIf=\"collapsed\" nz-tooltip nzTooltipPlacement=\"right\" [nzTooltipTitle]=\"i.text\">\n <ng-template [ngTemplateOutlet]=\"icon\" [ngTemplateOutletContext]=\"{ $implicit: i.icon }\"></ng-template>\n </span>\n </ng-container>\n <span class=\"sidebar-nav__item-text\" [innerHTML]=\"i._text\" [attr.title]=\"i.text\"></span>\n </a>\n <!-- has children link -->\n <a *ngIf=\"i.children.length > 0\" (click)=\"toggleOpen(i)\" (mouseenter)=\"showSubMenu($event, i)\" class=\"sidebar-nav__item-link\">\n <ng-template [ngTemplateOutlet]=\"icon\" [ngTemplateOutletContext]=\"{ $implicit: i.icon }\"></ng-template>\n <span class=\"sidebar-nav__item-text\" [innerHTML]=\"i._text\" [attr.title]=\"i.text\"></span>\n <i class=\"sidebar-nav__sub-arrow\"></i>\n </a>\n <!-- badge -->\n <div *ngIf=\"i.badge\" [attr.title]=\"i.badge\" class=\"badge badge-{{ i.badgeStatus }}\" [class.badge-dot]=\"i.badgeDot\">\n <em>{{ i.badge }}</em>\n </div>\n <ul *ngIf=\"i.children.length > 0\" class=\"sidebar-nav sidebar-nav__sub sidebar-nav__depth{{ i._depth }}\">\n <ng-template [ngTemplateOutlet]=\"tree\" [ngTemplateOutletContext]=\"{ $implicit: i.children }\"></ng-template>\n </ul>\n </li>\n </ng-container>\n</ng-template>\n<ul class=\"sidebar-nav\">\n <ng-container *ngFor=\"let group of list\">\n <li class=\"sidebar-nav__item sidebar-nav__group-title\" *ngIf=\"group.group\">\n <span [innerHTML]=\"group._text\"></span>\n </li>\n <ng-template [ngTemplateOutlet]=\"tree\" [ngTemplateOutletContext]=\"{ $implicit: group.children }\"></ng-template>\n </ng-container>\n</ul>\n", host: { '(click)': '_click()', '(document:click)': '_docClick()', }, preserveWhitespaces: false, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None }] } ]; /** @nocollapse */ SidebarNavComponent.ctorParameters = () => [ { type: MenuService }, { type: SettingsService }, { type: Router }, { type: Renderer2 }, { type: ChangeDetectorRef }, { type: NgZone }, { type: DomSanitizer }, { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] }, { type: Window, decorators: [{ type: Inject, args: [WINDOW,] }] } ]; SidebarNavComponent.propDecorators = { disabledAcl: [{ type: Input }], autoCloseUnderPad: [{ type: Input }], recursivePath: [{ type: Input }], openStrictly: [{ type: Input }], maxLevelIcon: [{ type: Input }], select: [{ type: Output }] }; __decorate([ InputBoolean(), __metadata("design:type", Object) ], SidebarNavComponent.prototype, "disabledAcl", void 0); __decorate([ InputBoolean(), __metadata("design:type", Object) ], SidebarNavComponent.prototype, "autoCloseUnderPad", void 0); __decorate([ InputBoolean(), __metadata("design:type", Object) ], SidebarNavComponent.prototype, "recursivePath", void 0); __decorate([ InputBoolean(), __metadata("design:type", Object) ], SidebarNavComponent.prototype, "openStrictly", void 0); __decorate([ InputNumber(), __metadata("design:type", Object) ], SidebarNavComponent.prototype, "maxLevelIcon", void 0); if (false) { /** @type {?} */ SidebarNavComponent.ngAcceptInputType_disabledAcl; /** @type {?} */ SidebarNavComponent.ngAcceptInputType_autoCloseUnderPad; /** @type {?} */ SidebarNavComponent.ngAcceptInputType_recursivePath; /** @type {?} */ SidebarNavComponent.ngAcceptInputType_openStrictly; /** @type {?} */ SidebarNavComponent.ngAcceptInputType_maxLevelIcon; /** * @type {?} * @private */ SidebarNavComponent.prototype.bodyEl; /** * @type {?} * @private */ SidebarNavComponent.prototype.unsubscribe$; /** * @type {?} * @private */ SidebarNavComponent.prototype.floatingEl; /** @type {?} */ SidebarNavComponent.prototype.list; /** @type {?} */ SidebarNavComponent.prototype.disabledAcl; /** @type {?} */ SidebarNavComponent.prototype.autoCloseUnderPad; /** @type {?} */ SidebarNavComponent.prototype.recursivePath; /** @type {?} */ SidebarNavComponent.prototype.openStrictly; /** @type {?} */ SidebarNavComponent.prototype.maxLevelIcon; /** @type {?} */ SidebarNavComponent.prototype.select; /** * @type {?} * @private */ SidebarNavComponent.prototype.menuSrv; /** * @type {?} * @private */ SidebarNavComponent.prototype.settings; /** * @type {?} * @private */ SidebarNavComponent.prototype.router; /** * @type {?} * @private */ SidebarNavComponent.prototype.render; /** * @type {?} * @private */ SidebarNavComponent.prototype.cdr; /** * @type {?} * @private */ SidebarNavComponent.prototype.ngZone; /** * @type {?} * @private */ SidebarNavComponent.prototype.sanitizer; /** * @type {?} * @private */ SidebarNavComponent.prototype.doc; /** * @type {?} * @private */ SidebarNavComponent.prototype.win; } /** * @fileoverview added by tsickle * Generated from: sidebar-nav.module.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ class SidebarNavModule { } SidebarNavModule.decorators = [ { type: NgModule, args: [{ imports: [CommonModule, RouterModule, NzIconModule, NzToolTipModule, OhayoUtilModule], declarations: [SidebarNavComponent], exports: [SidebarNavComponent], },] } ]; /** * @fileoverview added by tsickle * Generated from: public_api.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @fileoverview added by tsickle * Generated from: sidebarNav.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ export { SidebarNavComponent, SidebarNavModule }; //# sourceMappingURL=sidebarNav.js.map