Permalink
Browse files

feat(dialog-settings, dialog-renderer): add host

  • Loading branch information...
StrahilKazlachev committed Mar 17, 2017
1 parent b062757 commit 4aebd63736822cbc48c1c7ff4c36db3b7fa186a0
Showing with 59 additions and 10 deletions.
  1. +27 −10 src/dialog-renderer.ts
  2. +5 −0 src/dialog-settings.ts
  3. +26 −0 test/unit/dialog-renderer.spec.ts
  4. +1 −0 tslint.json
View
@@ -97,8 +97,20 @@ export class DialogRenderer implements Renderer {
public dialogContainer: HTMLElement;
public dialogOverlay: HTMLElement;
+ public host: Element;
public anchor: Element;
+ private getOwnElements(parent: Element, selector: string): Element[] {
+ const elements = parent.querySelectorAll(selector);
+ const own: Element[] = [];
+ for (let i = 0; i < elements.length; i++) {
+ if (elements[i].parentElement === parent) {
+ own.push(elements[i]);
+ }
+ }
+ return own;
+ }
+
private attach(dialogController: DialogController): void {
const spacingWrapper = DOM.createElement('div'); // TODO: check if redundant
spacingWrapper.appendChild(this.anchor);
@@ -110,24 +122,24 @@ export class DialogRenderer implements Renderer {
: null;
this.dialogOverlay.style.zIndex = zIndex;
this.dialogContainer.style.zIndex = zIndex;
- const lastContainer = Array.from(body.querySelectorAll(containerTagName)).pop();
- if (lastContainer && lastContainer.parentNode) {
- lastContainer.parentNode.insertBefore(this.dialogContainer, lastContainer.nextSibling);
- lastContainer.parentNode.insertBefore(this.dialogOverlay, lastContainer.nextSibling);
+ const lastContainer = this.getOwnElements(this.host, containerTagName).pop();
+ if (lastContainer && lastContainer.parentElement) {
+ this.host.insertBefore(this.dialogContainer, lastContainer.nextSibling);
+ this.host.insertBefore(this.dialogOverlay, lastContainer.nextSibling);
} else {
- body.insertBefore(this.dialogContainer, body.firstChild);
- body.insertBefore(this.dialogOverlay, body.firstChild);
+ this.host.insertBefore(this.dialogContainer, this.host.firstChild);
+ this.host.insertBefore(this.dialogOverlay, this.host.firstChild);
}
dialogController.controller.attached();
- body.classList.add('ux-dialog-open');
+ this.host.classList.add('ux-dialog-open');
}
private detach(dialogController: DialogController): void {
- body.removeChild(this.dialogOverlay);
- body.removeChild(this.dialogContainer);
+ this.host.removeChild(this.dialogOverlay);
+ this.host.removeChild(this.dialogContainer);
dialogController.controller.detached();
if (!DialogRenderer.dialogControllers.length) {
- body.classList.remove('ux-dialog-open');
+ this.host.classList.remove('ux-dialog-open');
}
}
@@ -195,6 +207,11 @@ export class DialogRenderer implements Renderer {
}
public showDialog(dialogController: DialogController): Promise<void> {
+ if (dialogController.settings.host) {
+ this.host = dialogController.settings.host;
+ } else {
+ this.host = body;
+ }
const settings = dialogController.settings;
this.attach(dialogController);
View
@@ -23,6 +23,11 @@ export interface DialogSettings {
*/
model?: any;
+ /**
+ * The element that will parent the dialog.
+ */
+ host?: Element;
+
/**
* When set to "false" allows the dialog to be closed with ESC key or clicking outside the dialog.
* When set to "true" the dialog does not close on ESC key or clicking outside of it.
@@ -158,6 +158,32 @@ describe('DialogRenderer', () => {
done();
});
});
+
+ describe('"host"', () => {
+ it('and when provided parents the dialog', async done => {
+ const host = DOM.createElement('div');
+ spyOn(host, 'insertBefore').and.callThrough();
+ spyOn(host, 'removeChild').and.callThrough();
+ body.appendChild(host);
+ const settings: DialogSettings = { host };
+ const renderer = createRenderer(settings);
+ await show(done, renderer);
+ expect(host.insertBefore).toHaveBeenCalledWith(renderer.dialogContainer, null);
+ expect(host.insertBefore).toHaveBeenCalledWith(renderer.dialogOverlay, renderer.dialogContainer);
+ await hide(done, renderer);
+ expect(host.removeChild).toHaveBeenCalledWith(renderer.dialogOverlay);
+ expect(host.removeChild).toHaveBeenCalledWith(renderer.dialogContainer);
+ body.removeChild(host);
+ done();
+ });
+
+ it('and when missing defaults to the "body" element', async done => {
+ const renderer = createRenderer({ host: undefined });
+ await show(done, renderer);
+ expect(renderer.host).toBe(body);
+ done();
+ });
+ });
});
describe('on first open dialog', () => {
View
@@ -8,6 +8,7 @@
"no-string-literal": false,
"object-literal-sort-keys": false,
"ordered-imports": [false],
+ "prefer-for-of": false,
"quotemark": [true, "single"],
"trailing-comma": [false],
"whitespace": [true, "check-branch", "check-decl", "check-operator", "check-module", "check-separator", "check-type"]

0 comments on commit 4aebd63

Please sign in to comment.