import dom = require("dojo/dom-construct"); import { argumentNotNull } from "@implab/core-amd/safe"; import { BuildContextBase } from "./BuildContextBase"; import { DojoNodePosition, isWidget } from "./traits"; // tslint:disable-next-line: class-name export interface _Widget { domNode: Node; containerNode?: Node; placeAt?(refNode: string | Node, position?: DojoNodePosition): void; startup?(): void; addChild?(widget: any, index?: number): void; } export type _WidgetCtor = new (attrs: any, srcNode?: string | Node) => _Widget; export class WidgetContext extends BuildContextBase { readonly widgetClass: _WidgetCtor; _instance: _Widget | undefined; constructor(widgetClass: _WidgetCtor) { super(); argumentNotNull(widgetClass, "widgetClass"); this.widgetClass = widgetClass; } _addChild(child: any): void { const instance = this._getInstance(); if (instance.addChild) { if (child instanceof WidgetContext) // layout containers add custom logic to addChild methods instance.addChild(child.getWidgetInstance()); else if (isWidget(child)) instance.addChild(child); else instance.addChild(this.getChildDom(child)); } else { if (!instance.containerNode) throw new Error("The widget doesn't have neither addChild nor containerNode"); // the current widget isn't started, it's children shouldn't start too dom.place(this.getChildDom(child), instance.containerNode); } } _create(attrs: object, children: any[]) { this._instance = new this.widgetClass(attrs); if (children) children.forEach(x => this._addChild(x)); } private _getInstance() { if (!this._instance) throw new Error("The instance of the widget isn't created"); return this._instance; } _getDomNode() { if (!this._instance) throw new Error("The instance of the widget isn't created"); return this._instance.domNode; } /** Overrides default placeAt implementation. Calls placeAt of the * widget and then starts it. * * @param refNode A node or id of the node where the widget should be placed. * @param position A position relative to refNode. */ placeAt(refNode: string | Node, position?: DojoNodePosition) { this.ensureCreated(); const instance = this._getInstance(); if (typeof instance.placeAt === "function") { instance.placeAt(refNode, position); // do we need to force widget startup? if (typeof instance.startup === "function") instance.startup(); } else { super.placeAt(refNode, position); } } getWidgetInstance() { this.ensureCreated(); return this._getInstance(); } }