backdrop of context menu is removed

This commit is contained in:
병준 박 2019-10-25 15:56:03 +09:00
parent c3fc458b0c
commit e42a698df5
6 changed files with 255 additions and 5 deletions

View File

@ -40,7 +40,11 @@
#chatContextMenuTrigger="matMenuTrigger" #chatContextMenuTrigger="matMenuTrigger"
[matMenuTriggerFor]="chatContextMenu" [matMenuTriggerFor]="chatContextMenu"
></div> ></div>
<mat-menu #chatContextMenu="matMenu" [hasBackdrop]="false"> <mat-menu
#chatContextMenu="matMenu"
[hasBackdrop]="false"
(ucapUiClickOutside)="chatContextMenuTrigger.closeMenu()"
>
<ng-template matMenuContent let-roomInfo="roomInfo"> <ng-template matMenuContent let-roomInfo="roomInfo">
<button mat-menu-item (click)="onSelectedRoom(roomInfo)"> <button mat-menu-item (click)="onSelectedRoom(roomInfo)">
대화방 열기 대화방 열기

View File

@ -8,8 +8,10 @@
</button> </button>
<button <button
mat-icon-button mat-icon-button
#groupMenuTrigger="matMenuTrigger"
[matMenuTriggerFor]="groupMenu" [matMenuTriggerFor]="groupMenu"
aria-label="group menu" aria-label="group menu"
(ucapUiClickOutside)="groupMenuTrigger.closeMenu()"
> >
<mat-icon>more_vert</mat-icon> <mat-icon>more_vert</mat-icon>
</button> </button>
@ -92,7 +94,11 @@
#profileContextMenuTrigger="matMenuTrigger" #profileContextMenuTrigger="matMenuTrigger"
[matMenuTriggerFor]="profileContextMenu" [matMenuTriggerFor]="profileContextMenu"
></div> ></div>
<mat-menu #profileContextMenu="matMenu" [hasBackdrop]="false"> <mat-menu
#profileContextMenu="matMenu"
[hasBackdrop]="false"
(ucapUiClickOutside)="profileContextMenuTrigger.closeMenu()"
>
<ng-template matMenuContent let-userInfo="userInfo"> <ng-template matMenuContent let-userInfo="userInfo">
<button <button
mat-menu-item mat-menu-item
@ -155,7 +161,11 @@
#groupContextMenuTrigger="matMenuTrigger" #groupContextMenuTrigger="matMenuTrigger"
[matMenuTriggerFor]="groupContextMenu" [matMenuTriggerFor]="groupContextMenu"
></div> ></div>
<mat-menu #groupContextMenu="matMenu" [hasBackdrop]="false"> <mat-menu
#groupContextMenu="matMenu"
[hasBackdrop]="false"
(ucapUiClickOutside)="groupContextMenuTrigger.closeMenu()"
>
<ng-template matMenuContent let-group="group"> <ng-template matMenuContent let-group="group">
<button mat-menu-item (click)="onClickGroupContextMenu('CHAT', group)"> <button mat-menu-item (click)="onClickGroupContextMenu('CHAT', group)">
그룹 대화하기 그룹 대화하기

View File

@ -113,7 +113,11 @@
#messageContextMenuTrigger="matMenuTrigger" #messageContextMenuTrigger="matMenuTrigger"
[matMenuTriggerFor]="messageContextMenu" [matMenuTriggerFor]="messageContextMenu"
></div> ></div>
<mat-menu #messageContextMenu="matMenu" [hasBackdrop]="false"> <mat-menu
#messageContextMenu="matMenu"
[hasBackdrop]="false"
(ucapUiClickOutside)="messageContextMenuTrigger.closeMenu()"
>
<ng-template matMenuContent let-message="message" let-loginRes="loginRes"> <ng-template matMenuContent let-message="message" let-loginRes="loginRes">
<ng-container *ngIf="!isRecalledMessage(message.type)"> <ng-container *ngIf="!isRecalledMessage(message.type)">
<button <button

View File

@ -0,0 +1,226 @@
import {
Directive,
ElementRef,
EventEmitter,
Inject,
Injectable,
Input,
OnChanges,
OnDestroy,
OnInit,
Output,
PLATFORM_ID,
SimpleChanges,
NgZone
} from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
@Directive({ selector: '[ucapUiClickOutside]' })
export class ClickOutsideDirective implements OnInit, OnChanges, OnDestroy {
@Input()
clickOutsideEnabled = true;
@Input()
attachOutsideOnClick = false;
@Input()
delayClickOutsideInit = false;
@Input()
emitOnBlur = false;
@Input()
exclude = '';
@Input()
excludeBeforeClick = false;
@Input()
clickOutsideEvents = '';
@Output()
ucapUiClickOutside: EventEmitter<Event> = new EventEmitter<Event>();
private nodesExcluded: Array<HTMLElement> = [];
private events: Array<string> = ['click', 'contextmenu'];
constructor(
private elementRef: ElementRef,
private ngZone: NgZone,
@Inject(PLATFORM_ID) private platformId: object
) {
this._initOnClickBody = this._initOnClickBody.bind(this);
this._onClickBody = this._onClickBody.bind(this);
this._onWindowBlur = this._onWindowBlur.bind(this);
}
ngOnInit() {
if (!isPlatformBrowser(this.platformId)) {
return;
}
this._init();
}
ngOnDestroy() {
if (!isPlatformBrowser(this.platformId)) {
return;
}
this._removeClickOutsideListener();
this._removeAttachOutsideOnClickListener();
this._removeWindowBlurListener();
}
ngOnChanges(changes: SimpleChanges) {
if (!isPlatformBrowser(this.platformId)) {
return;
}
if (changes.attachOutsideOnClick || changes.exclude || changes.emitOnBlur) {
this._init();
}
}
private _init() {
if (this.clickOutsideEvents !== '') {
this.events = this.clickOutsideEvents.split(',').map(e => e.trim());
}
this._excludeCheck();
if (this.attachOutsideOnClick) {
this._initAttachOutsideOnClickListener();
} else {
this._initOnClickBody();
}
if (this.emitOnBlur) {
this._initWindowBlurListener();
}
}
private _initOnClickBody() {
if (this.delayClickOutsideInit) {
setTimeout(this._initClickOutsideListener.bind(this));
} else {
this._initClickOutsideListener();
}
}
private _excludeCheck() {
if (this.exclude) {
try {
const nodes = Array.from(
document.querySelectorAll(this.exclude)
) as Array<HTMLElement>;
if (nodes) {
this.nodesExcluded = nodes;
}
} catch (err) {
console.error(
'[ng-click-outside] Check your exclude selector syntax.',
err
);
}
}
}
private _onClickBody(ev: Event) {
if (!this.clickOutsideEnabled) {
return;
}
if (this.excludeBeforeClick) {
this._excludeCheck();
}
if (
!this.elementRef.nativeElement.contains(ev.target) &&
!this._shouldExclude(ev.target)
) {
this._emit(ev);
if (this.attachOutsideOnClick) {
this._removeClickOutsideListener();
}
}
}
/**
* Resolves problem with outside click on iframe
* @see https://github.com/arkon/ng-click-outside/issues/32
*/
private _onWindowBlur(ev: Event) {
setTimeout(() => {
if (!document.hidden) {
this._emit(ev);
}
});
}
private _emit(ev: Event) {
if (!this.clickOutsideEnabled) {
return;
}
this.ngZone.run(() => this.ucapUiClickOutside.emit(ev));
}
private _shouldExclude(target): boolean {
for (const excludedNode of this.nodesExcluded) {
if (excludedNode.contains(target)) {
return true;
}
}
return false;
}
private _initClickOutsideListener() {
this.ngZone.runOutsideAngular(() => {
this.events.forEach(e =>
document.body.addEventListener(e, this._onClickBody)
);
});
}
private _removeClickOutsideListener() {
this.ngZone.runOutsideAngular(() => {
this.events.forEach(e =>
document.body.removeEventListener(e, this._onClickBody)
);
});
}
private _initAttachOutsideOnClickListener() {
this.ngZone.runOutsideAngular(() => {
this.events.forEach(e =>
this.elementRef.nativeElement.addEventListener(e, this._initOnClickBody)
);
});
}
private _removeAttachOutsideOnClickListener() {
this.ngZone.runOutsideAngular(() => {
this.events.forEach(e =>
this.elementRef.nativeElement.removeEventListener(
e,
this._initOnClickBody
)
);
});
}
private _initWindowBlurListener() {
this.ngZone.runOutsideAngular(() => {
window.addEventListener('blur', this._onWindowBlur);
});
}
private _removeWindowBlurListener() {
this.ngZone.runOutsideAngular(() => {
window.removeEventListener('blur', this._onWindowBlur);
});
}
}

View File

@ -18,6 +18,7 @@ import { ClipboardService } from './services/clipboard.service';
import { DialogService } from './services/dialog.service'; import { DialogService } from './services/dialog.service';
import { SnackBarService } from './services/snack-bar.service'; import { SnackBarService } from './services/snack-bar.service';
import { ClickOutsideDirective } from './directives/click-outside.directive';
import { FileUploadForDirective } from './directives/file-upload-for.directive'; import { FileUploadForDirective } from './directives/file-upload-for.directive';
import { ImageDirective } from './directives/image.directive'; import { ImageDirective } from './directives/image.directive';
@ -28,7 +29,11 @@ import { BytesPipe } from './pipes/bytes.pipe';
const COMPONENTS = [FileUploadQueueComponent]; const COMPONENTS = [FileUploadQueueComponent];
const DIALOGS = [AlertDialogComponent, ConfirmDialogComponent]; const DIALOGS = [AlertDialogComponent, ConfirmDialogComponent];
const DIRECTIVES = [FileUploadForDirective, ImageDirective]; const DIRECTIVES = [
ClickOutsideDirective,
FileUploadForDirective,
ImageDirective
];
const PIPES = [BytesPipe]; const PIPES = [BytesPipe];
const SERVICES = [ const SERVICES = [
BottomSheetService, BottomSheetService,

View File

@ -9,6 +9,7 @@ export * from './lib/components/file-upload-queue.component';
export * from './lib/dialogs/alert.dialog.component'; export * from './lib/dialogs/alert.dialog.component';
export * from './lib/dialogs/confirm.dialog.component'; export * from './lib/dialogs/confirm.dialog.component';
export * from './lib/directives/click-outside.directive';
export * from './lib/directives/file-upload-for.directive'; export * from './lib/directives/file-upload-for.directive';
export * from './lib/directives/image.directive'; export * from './lib/directives/image.directive';