WidgetContext.ts
128 lines
| 4.5 KiB
| video/mp2t
|
TypeScriptLexer
cin
|
r7 | import dom = require("dojo/dom-construct"); | ||
import { argumentNotNull } from "@implab/core-amd/safe"; | ||||
import { BuildContextBase } from "./BuildContextBase"; | ||||
cin
|
r48 | import { DojoNodePosition, isInPage, isWidget } from "./traits"; | ||
import registry = require("dijit/registry"); | ||||
import ContentPane = require("dijit/layout/ContentPane"); | ||||
cin
|
r7 | |||
cin
|
r19 | // tslint:disable-next-line: class-name | ||
export interface _Widget { | ||||
domNode: Node; | ||||
cin
|
r38 | containerNode?: Node; | ||
cin
|
r19 | |||
cin
|
r38 | placeAt?(refNode: string | Node, position?: DojoNodePosition): void; | ||
startup?(): void; | ||||
cin
|
r19 | |||
cin
|
r38 | addChild?(widget: any, index?: number): void; | ||
cin
|
r19 | } | ||
export type _WidgetCtor = new (attrs: any, srcNode?: string | Node) => _Widget; | ||||
cin
|
r7 | |||
cin
|
r22 | export class WidgetContext extends BuildContextBase<Node> { | ||
cin
|
r38 | readonly widgetClass: _WidgetCtor; | ||
cin
|
r7 | |||
cin
|
r19 | _instance: _Widget | undefined; | ||
cin
|
r7 | |||
cin
|
r19 | constructor(widgetClass: _WidgetCtor) { | ||
cin
|
r7 | super(); | ||
argumentNotNull(widgetClass, "widgetClass"); | ||||
this.widgetClass = widgetClass; | ||||
} | ||||
_addChild(child: any): void { | ||||
cin
|
r38 | const instance = this._getInstance(); | ||
cin
|
r7 | |||
cin
|
r38 | if (instance.addChild) { | ||
cin
|
r48 | if (child instanceof WidgetContext) { | ||
cin
|
r38 | // layout containers add custom logic to addChild methods | ||
instance.addChild(child.getWidgetInstance()); | ||||
cin
|
r48 | } else if (isWidget(child)) { | ||
cin
|
r38 | instance.addChild(child); | ||
cin
|
r48 | } 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); | ||||
} | ||||
cin
|
r38 | } 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); | ||||
} | ||||
cin
|
r7 | } | ||
cin
|
r48 | _create(attrs: any, children: any[]) { | ||
if (this.widgetClass.prototype instanceof ContentPane) { | ||||
// a special case for the ContentPane this is for | ||||
// the compatibility with this heavy widget, all | ||||
// regular containers could be easily manipulated | ||||
// through `containerNode` property or `addChild` method. | ||||
// render children to the DocumentFragment | ||||
const content = document.createDocumentFragment(); | ||||
children.forEach(child => content.appendChild(this.getChildDom(child))); | ||||
// set the content property to the parameters of the widget | ||||
const _attrs = { ...attrs, content }; | ||||
this._instance = new this.widgetClass(_attrs); | ||||
} else { | ||||
this._instance = new this.widgetClass(attrs); | ||||
cin
|
r7 | children.forEach(x => this._addChild(x)); | ||
cin
|
r48 | } | ||
cin
|
r7 | } | ||
cin
|
r38 | private _getInstance() { | ||
if (!this._instance) | ||||
throw new Error("The instance of the widget isn't created"); | ||||
return this._instance; | ||||
} | ||||
cin
|
r19 | _getDomNode() { | ||
cin
|
r7 | if (!this._instance) | ||
throw new Error("The instance of the widget isn't created"); | ||||
return this._instance.domNode; | ||||
} | ||||
cin
|
r38 | /** 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); | ||||
cin
|
r48 | // fix the dojo startup behavior when the widget is placed | ||
// directly to the document and doesn't have any enclosing widgets | ||||
const parentWidget = instance.domNode.parentNode ? | ||||
registry.getEnclosingWidget(instance.domNode.parentNode) : null | ||||
if (!parentWidget && isInPage(instance.domNode)) | ||||
this._startup(); | ||||
cin
|
r38 | } else { | ||
cin
|
r48 | // the widget doesn't have a placeAt method, strange but whatever | ||
cin
|
r38 | super.placeAt(refNode, position); | ||
} | ||||
} | ||||
cin
|
r48 | _startup() { | ||
const instance = this._getInstance(); | ||||
if (typeof instance.startup === "function") | ||||
instance.startup(); | ||||
} | ||||
cin
|
r38 | getWidgetInstance() { | ||
this.ensureCreated(); | ||||
return this._getInstance(); | ||||
} | ||||
cin
|
r7 | } | ||