jsdk-offical
Version:
JSDK is the most comprehensive TypeScript framework, like JDK.
254 lines (219 loc) • 8.88 kB
text/typescript
/**
* @project JSDK
* @license MIT
* @website https://github.com/fengboyue/jsdk
*
* @version 2.0.0
* @author Frank.Feng
*/
/// <reference path="Base.ts"/>
module JS {
export namespace fx {
let J = Jsons;
export abstract class Widget implements IWidget {
public readonly id: string;
public widgetEl: JQuery<HTMLElement>;/** 组件DOM对象 */
protected _eventBus: EventBus;
protected _config: WidgetConfig<Widget> = null;//当前配置
protected _initialConfig: WidgetConfig<Widget> = null;//初始配置
constructor(cfg: WidgetConfig<Widget>) {
if (!cfg.id && cfg.renderTo) {
let wgt = $(cfg.renderTo);
if (wgt.length == 1) {
this.widgetEl = wgt;
let id = wgt.attr('id');
if (id) {
this.id = id
} else {
this.id = Random.uuid(4, 10).toString();
wgt.attr('id', this.id);
}
}
} else {
this.id = cfg.id || Random.uuid(4, 10).toString();
}
this._initConfig(cfg);
this._onBeforeInit();
this._initDom();
this._onAfterInit();
}
/**
* 在父类构造函数中的初始化之前,由子类重载实现
*/
protected _onBeforeInit() { }
/**
* 在父类构造函数中的初始化之后,由子类重载实现
*/
protected _onAfterInit() { }
/**
* 初始化DOM
*/
protected _initDom(): void {
let cfg = this._config;
this.widgetEl = $('#' + this.id);
if (this.widgetEl.length == 0) {
this.widgetEl = $('<div />', {
id: this.id,
width: cfg.width,
height: cfg.height,
title: cfg.tip,
style: cfg.style,
'klass-name': this.className
}).appendTo(cfg.appendTo || 'body');
} else {
let attrs = {};
if (cfg.tip) attrs['title'] = cfg.tip;
if (cfg.style) attrs['style'] = (this.widgetEl.attr('style') || '') + cfg.style;
if (!Check.isEmpty(attrs)) this.widgetEl.attr(attrs);
if (cfg.width) this.widgetEl.css('width', cfg.width);
}
this._eventBus = new EventBus(this);
//监听渲染事件
let listeners = cfg.listeners;
if (listeners && listeners.rendering) this.on('rendering', listeners.rendering);
this.render();
}
private _initConfig(cfg: WidgetConfig<Widget>) {
let defaultCfg = Class.newInstance<WidgetConfig<Widget>>(this.className + 'Config');
cfg.name = cfg.name || this.id;
this._config = J.union(defaultCfg, cfg);
this._initialConfig = J.clone(this._config);
}
public initialConfig<V>(key?: string): V {
return <V>J.clone(key ? this._initialConfig[key] : this._initialConfig);
}
protected _onBeforeRender() { }
protected _onAfterRender() { }
public render<T extends Widget>(): T {
this._onBeforeRender();
this._fire('rendering');
//渲染前注销所有事件监听
this.off();
this.widgetEl.off().empty();
//添加组件缺省样式
let cfg = this._config;
this.widgetEl.addClass(`jsfx-${(<Object>this).getClass().shortName.toLowerCase()} ${cfg.colorMode ? 'color-' + cfg.colorMode : ''} size-${cfg.sizeMode} ${cfg.cls || ''}`);
let is = this._render();
//渲染后重新注册事件监听
let lts = cfg.listeners || {};
J.forEach(<any>lts, function (handler: EventHandler<Widget>, type: string) {
if (handler) this.on(type, handler);
}, this);
this._onAfterRender();
if (is !== false) this._fire('rendered');
return <any>this;
}
/**
* 渲染DOM(不触发事件)
* 返回false表示异步渲染
*/
protected abstract _render(): void | false
/**
* 返回控件name属性
*/
public name() {
return this._config.name || '';
}
/**
* 是否包含指定模式
* @param key 模式键值
* @param type 模式类型
*/
protected _hasFaceMode(key: string, cfg?: WidgetConfig<Widget>): boolean {
cfg = cfg || this._config;
let t: any = cfg.faceMode;
if (!t) return false;
return t == key || t[key] === true || $.inArray(key, t) != -1;
}
/**
* 按指定模式类型渲染
* @param type 模式类型
* @param fn 渲染函数
*/
protected _eachMode(type: 'sizeMode' | 'colorMode' | 'faceMode', fn: (this: Widget, mode: string) => void, cfg?: WidgetConfig<Widget>) {
cfg = cfg || this._config;
let mode = cfg[type];
if (!mode) return;
let me = this;
if (Types.isArray(mode)) {
(<string[]>mode).forEach(m => {
fn.apply(this, [m])
});
} else {
fn.apply(me, [mode])
}
}
private _isD = false;
public destroy(): void {
this._fire('destroying');
this._destroy();
this._fire('destroyed');
}
protected _destroy(): void {
this.off();
this.widgetEl.remove();
this._eventBus.destroy();
this._isD = true;
}
public show() {
this._fire('showing');
this.widgetEl.css('display', '');
this._fire('shown');
return this
}
public hide() {
this._fire('hiding');
this.widgetEl.css('display', 'none');
this._fire('hidden');
return this
}
public isShown(): boolean {
return this.widgetEl.css('display') != 'none'
}
public on<H = EventHandler<this>>(types: string, fn: H, once?: boolean) {
this._eventBus.on(types, fn, once);
return this
}
public off(types?: string) {
this._eventBus.off(types);
return this;
}
protected _fire<E>(e: E, args?: Array<any>) {
return this._eventBus.fire(<any>e, args);
}
public static I18N: I18NResource|URLString = null;
private _i18nObj: I18N = null;
private _newI18N() {
let lc = this._config.locale,
n = new I18N(lc),
v:I18NResource|URLString = (<Object>this).getClass().getKlass<Widget>()['I18N'];
if(v) typeof v == 'string'?n.load(v):n.set(v);
let i18n = this._config.i18n;
if (i18n) {
if (Types.isString(i18n)) {
n.load(<string>i18n, lc);
} else {
n.set(J.union(n.get(), <JsonObject>i18n))
}
}
this._i18nObj = n
}
protected _i18n(): JsonObject
protected _i18n<T>(key: string): T
protected _i18n(key?: string) {
if (!this._i18nObj) this._newI18N();
return this._i18nObj.get(<any>key)
}
locale(): string
locale(locale: string): this
locale(lc?: string) {
if (arguments.length == 0) return this._config.locale;
// if (locale != this._config.locale) await this._newI18N();
this._config.locale = lc;
return this
}
}
}
}
import Widget = JS.fx.Widget;