Skip to content

Commit

Permalink
added modal
Browse files Browse the repository at this point in the history
  • Loading branch information
pimenovoleg committed Aug 8, 2018
1 parent f00b7ba commit 5a45f60
Show file tree
Hide file tree
Showing 14 changed files with 736 additions and 0 deletions.
45 changes: 45 additions & 0 deletions src/lib/core/services/measure-scrollbar.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { DOCUMENT } from '@angular/common';
import { Inject, Injectable } from '@angular/core';


@Injectable({
providedIn: 'root'
})
export class McMeasureScrollbarService {
private _scrollbarWidth: number;
private scrollbarMeasure = {
position: 'absolute',
top: '-9999px',
width: '50px',
height: '50px',
overflow: 'scroll'
};

get scrollBarWidth(): number {
if (this._scrollbarWidth) {
return this._scrollbarWidth;
}
this.initScrollBarWidth();

return this._scrollbarWidth;
}

initScrollBarWidth(): void {
const scrollDiv = this.document.createElement('div');

for (const scrollProp in this.scrollbarMeasure) {
if (this.scrollbarMeasure.hasOwnProperty(scrollProp)) {
scrollDiv.style[scrollProp] = this.scrollbarMeasure[scrollProp];
}
}
this.document.body.appendChild(scrollDiv);
const width = scrollDiv.offsetWidth - scrollDiv.clientWidth;
this.document.body.removeChild(scrollDiv);
this._scrollbarWidth = width;
}

// tslint:disable-next-line:no-any
constructor(@Inject(DOCUMENT) private document: any) {
this.initScrollBarWidth();
}
}
Empty file added src/lib/modal/README.md
Empty file.
1 change: 1 addition & 0 deletions src/lib/modal/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './public-api';
43 changes: 43 additions & 0 deletions src/lib/modal/modal-abstr-ref.class.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { Observable } from 'rxjs';

import { McModalComponent } from './modal.component';


export abstract class McModalRef<T = any, R = any> {
abstract afterOpen: Observable<void>;
abstract afterClose: Observable<R>;

abstract open(): void;

abstract close(result?: R): void;

abstract destroy(result?: R): void;

/**
* Trigger the mcOnOk/mcOnCancel by manual
*/
abstract triggerOk(): void;

abstract triggerCancel(): void;

// /**
// * Return the ComponentRef of mcContent when specify mcContent as a Component
// * Note: this method may return undefined if the Component has not ready yet. (it only available after Modal's ngOnInit)
// */
// abstract getContentComponentRef(): ComponentRef<{}>;
/**
* Return the component instance of mcContent when specify mcContent as a Component
* Note: this method may return undefined if the Component has not ready yet. (it only available after Modal's ngOnInit)
*/
abstract getContentComponent(): T;

/**
* Get the dom element of this Modal
*/
abstract getElement(): HTMLElement;

/**
* Get the instance of the Modal itself
*/
abstract getInstance(): McModalComponent;
}
78 changes: 78 additions & 0 deletions src/lib/modal/modal-control.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { Injectable, Optional, SkipSelf} from '@angular/core';
import { Subject, Subscription } from 'rxjs';

import { McModalRef } from './modal-abstr-ref.class';


interface IRegisteredMeta {
modalRef: McModalRef;
afterOpenSubscription: Subscription;
afterCloseSubscription: Subscription;
}

@Injectable()
export class McModalControlService {

// Track singleton afterAllClose through over the injection tree
get afterAllClose(): Subject<void> {
return this.parentService ? this.parentService.afterAllClose : this.rootAfterAllClose;
}

// Track singleton openModals array through over the injection tree
get openModals(): McModalRef[] {
return this.parentService ? this.parentService.openModals : this.rootOpenModals;
}

// @ts-ignore
private rootOpenModals: McModalRef[] = this.parentService ? null : [];
// @ts-ignore
private rootAfterAllClose: Subject<void> = this.parentService ? null : new Subject<void>();

// @ts-ignore
private rootRegisteredMetaMap: Map<McModalRef, IRegisteredMeta> = this.parentService ? null : new Map();

private get registeredMetaMap(): Map<McModalRef, IRegisteredMeta> { // Registered modal for later usage
return this.parentService ? this.parentService.registeredMetaMap : this.rootRegisteredMetaMap;
}

constructor(
@Optional() @SkipSelf() private parentService: McModalControlService) {
}

// Register a modal to listen its open/close
registerModal(modalRef: McModalRef): void {
if (!this.hasRegistered(modalRef)) {
const afterOpenSubscription = modalRef.afterOpen.subscribe(() => this.openModals.push(modalRef));
const afterCloseSubscription = modalRef.afterClose.subscribe(() => this.removeOpenModal(modalRef));

this.registeredMetaMap.set(modalRef, { modalRef, afterOpenSubscription, afterCloseSubscription });
}
}

// TODO: allow deregister modals
// deregisterModal(modalRef: McModalRef): void {}
hasRegistered(modalRef: McModalRef): boolean {
return this.registeredMetaMap.has(modalRef);
}

// Close all registered opened modals
closeAll(): void {
let i = this.openModals.length;

while (i--) {
this.openModals[ i ].close();
}
}

private removeOpenModal(modalRef: McModalRef): void {
const index = this.openModals.indexOf(modalRef);

if (index > -1) {
this.openModals.splice(index, 1);

if (!this.openModals.length) {
this.afterAllClose.next();
}
}
}
}
Empty file.
Loading

0 comments on commit 5a45f60

Please sign in to comment.