add some JSDoc to the code

This commit is contained in:
lxsang
2020-06-10 11:15:01 +02:00
parent edbffeb2b8
commit 6365081f56
22 changed files with 1562 additions and 370 deletions

View File

@ -219,10 +219,10 @@ namespace OS {
*
*
* @export
* @param {(string | FormatedString)} m
* @param {(string | FormattedString)} m
* @param {Error} e
*/
export function osfail(m: string | FormatedString, e: Error): void {
export function osfail(m: string | FormattedString, e: Error): void {
announcer.ostrigger("fail", { m, e });
}
@ -230,10 +230,10 @@ namespace OS {
*
*
* @export
* @param {(string | FormatedString)} m
* @param {(string | FormattedString)} m
* @param {Error} e
*/
export function oserror(m: string | FormatedString, e: Error): void {
export function oserror(m: string | FormattedString, e: Error): void {
announcer.ostrigger("error", { m, e });
}
@ -241,9 +241,9 @@ namespace OS {
*
*
* @export
* @param {(string | FormatedString)} m
* @param {(string | FormattedString)} m
*/
export function osinfo(m: string | FormatedString): void {
export function osinfo(m: string | FormattedString): void {
announcer.ostrigger("info", { m, e: null });
}

View File

@ -302,10 +302,10 @@ namespace OS {
/**
*
*
* @returns {(string| FormatedString)}
* @returns {(string| FormattedString)}
* @memberof BaseApplication
*/
title(): string| FormatedString {
title(): string| FormattedString {
return (this.scheme as GUI.tag.WindowTag).apptitle;
}

View File

@ -393,14 +393,14 @@ namespace OS {
*
* @protected
* @param {string} t
* @param {(string | FormatedString)} m
* @param {(string | FormattedString)} m
* @param {Error} [e]
* @returns {void}
* @memberof BaseModel
*/
protected publish(
t: string,
m: string | FormatedString,
m: string | FormattedString,
e?: Error
): void {
const mt = this.meta();
@ -423,34 +423,34 @@ namespace OS {
/**
*
*
* @param {(string | FormatedString)} m
* @param {(string | FormattedString)} m
* @returns {void}
* @memberof BaseModel
*/
notify(m: string | FormatedString): void {
notify(m: string | FormattedString): void {
return this.publish("notification", m);
}
/**
*
*
* @param {(string | FormatedString)} m
* @param {(string | FormattedString)} m
* @returns {void}
* @memberof BaseModel
*/
warn(m: string | FormatedString): void {
warn(m: string | FormattedString): void {
return this.publish("warning", m);
}
/**
*
*
* @param {(string | FormatedString)} m
* @param {(string | FormattedString)} m
* @param {Error} [e]
* @returns
* @memberof BaseModel
*/
error(m: string | FormatedString, e?: Error) {
error(m: string | FormattedString, e?: Error) {
return this.publish("error", m, e ? e : this._api.throwe(m));
}

View File

@ -1,13 +1,4 @@
/*
* decaffeinate suggestions:
* DS101: Remove unnecessary use of Array.from
* DS102: Remove unnecessary code created because of implicit returns
* DS202: Simplify dynamic range loops
* DS205: Consider reworking code to avoid use of IIFEs
* DS208: Avoid top-level this
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
// Copyright 2017-2018 Xuan Sang LE <xsang.le AT gmail DOT com>
// Copyright 2017-2020 Xuan Sang LE <xsang.le AT gmail DOT com>
// AnTOS Web desktop is is licensed under the GNU General Public
// License v3.0, see the LICENCE file for more information
@ -40,7 +31,7 @@ interface String {
unescape(): string;
asUint8Array(): Uint8Array;
format(...args: any[]): string;
f(...args: any[]): OS.FormatedString;
f(...args: any[]): OS.FormattedString;
__(): string;
l(): string;
trimLeft(arg: string): string;
@ -71,9 +62,9 @@ interface GenericObject<T> {
*
*
* @param {...any[]} args
* @returns {(OS.FormatedString | string)}
* @returns {(OS.FormattedString | string)}
*/
declare function __(...args: any[]): OS.FormatedString | string;
declare function __(...args: any[]): OS.FormattedString | string;
/**
*
@ -111,13 +102,13 @@ namespace OS {
return range;
}
Ant.__ = function (...args: any[]): FormatedString | string {
Ant.__ = function (...args: any[]): FormattedString | string {
if (!(args.length > 0)) {
return "Undefined";
}
const d = args[0];
d.l();
return new FormatedString(
return new FormattedString(
d,
__range__(1, args.length - 1, true).map((i) => args[i])
);
@ -134,9 +125,9 @@ namespace OS {
*
*
* @export
* @class FormatedString
* @class FormattedString
*/
export class FormatedString {
export class FormattedString {
fs: string;
values: any[];
constructor(fs: string, args: any[]) {
@ -158,7 +149,7 @@ namespace OS {
*
*
* @returns {string}
* @memberof FormatedString
* @memberof FormattedString
*/
toString(): string {
return this.__();
@ -168,7 +159,7 @@ namespace OS {
*
*
* @returns {string}
* @memberof FormatedString
* @memberof FormattedString
*/
__(): string {
return this.fs
@ -186,7 +177,7 @@ namespace OS {
*
*
* @returns {number}
* @memberof FormatedString
* @memberof FormattedString
*/
hash(): number {
return this.__().hash();
@ -197,7 +188,7 @@ namespace OS {
*
* @param {(string | RegExp)} t
* @returns {RegExpMatchArray}
* @memberof FormatedString
* @memberof FormattedString
*/
match(t: string | RegExp): RegExpMatchArray {
return this.__().match(t);
@ -207,7 +198,7 @@ namespace OS {
*
*
* @returns {string}
* @memberof FormatedString
* @memberof FormattedString
*/
asBase64(): string {
return this.__().asBase64();
@ -217,7 +208,7 @@ namespace OS {
*
*
* @returns {string}
* @memberof FormatedString
* @memberof FormattedString
*/
unescape(): string {
return this.__().unescape();
@ -227,7 +218,7 @@ namespace OS {
*
*
* @returns {Uint8Array}
* @memberof FormatedString
* @memberof FormattedString
*/
asUint8Array(): Uint8Array {
return this.__().asUint8Array();
@ -237,7 +228,7 @@ namespace OS {
*
*
* @param {...any[]} args
* @memberof FormatedString
* @memberof FormattedString
*/
format(...args: any[]): void {
__range__(0, args.length - 1, true).map(
@ -444,8 +435,8 @@ namespace OS {
};
}
String.prototype.f = function (...args: any[]): FormatedString {
return new FormatedString(this, args);
String.prototype.f = function (...args: any[]): FormattedString {
return new FormattedString(this, args);
};
String.prototype.__ = function (): string {
@ -810,12 +801,16 @@ namespace OS {
}
/**
*
* Perform an REST GET request
*
* @export
* @param {string} p
* @param {string} [t=undefined]
* @returns {Promise<any>}
* @param {string} p the URI of the request
* @param {string} [t=undefined] the response data type:
* - jsonp: the response is an json object
* - script: the response is a javascript code
* - xm, html: the response is a XML/HTNL object
* - text: plain text
* @returns {Promise<any>} a Promise on the requested data
*/
export function get(p: string, t: string = undefined): Promise<any> {
return new Promise(function (resolve, reject) {
@ -1083,10 +1078,10 @@ namespace OS {
*
*
* @export
* @param {(string | FormatedString)} n
* @param {(string | FormattedString)} n
* @returns {Error}
*/
export function throwe(n: string | FormatedString): Error {
export function throwe(n: string | FormattedString): Error {
let err = undefined;
try {
throw new Error(n.__());

View File

@ -44,7 +44,7 @@ namespace OS {
* @interface BasicItemType
*/
export interface BasicItemType {
text: string | FormatedString;
text: string | FormattedString;
children?: BasicItemType[];
nodes?: BasicItemType[];
[propName: string]: any;

View File

@ -1,9 +1,4 @@
/*
* decaffeinate suggestions:
* DS102: Remove unnecessary code created because of implicit returns
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
// Copyright 2017-2018 Xuan Sang LE <xsang.le AT gmail DOT com>
// Copyright 2017-2020 Xuan Sang LE <xsang.le AT gmail DOT com>
// AnTOS Web desktop is is licensed under the GNU General Public
// License v3.0, see the LICENCE file for more information
@ -23,48 +18,172 @@
namespace OS {
export namespace API {
/**
* Interface for user login data
*
* @export
* @interface UserLoginType
*/
export interface UserLoginType {
/**
* The user credential
*
* @type {string}
* @memberof UserLoginType
*/
username: string;
/**
* The user password
*
* @type {string}
* @memberof UserLoginType
*/
password: string;
}
/**
* Interface for a command sent to
* server side package manage, it contains two field:
*
* @export
* @interface PackageCommandType
*/
export interface PackageCommandType {
/**
* Command name, should be: `init`, `cache`, `install`,
* `uninstall` or `list`
*
* @type {string}
* @memberof PackageCommandType
*/
command: string;
/**
* Parameter object of each command
*
* @type {GenericObject<any>}
* @memberof PackageCommandType
*/
args: GenericObject<any>;
}
/**
*
* Interface for basic request result returned
* from the server-side. A valid server-side response should
* be in the following format
* ```json
* {
* "error": boolean or string_err,
* "result": JSON result object
* }
* ```
*
* @export
* @interface RequestResult
*/
export interface RequestResult {
/**
* Indicate whether an the response is error
*
* @type {(boolean | string)}
* @memberof RequestResult
*/
error: boolean | string;
/**
* The response result, this value must be
* set when `error` is false
*
* @type {(string
* | boolean
* | GenericObject<any>
* | any[]
* | FileInfoType
* | FileInfoType[]
* | setting.UserSettingType)}
* @memberof RequestResult
*/
result:
| string
| boolean
| GenericObject<any>
| any[]
| FileInfoType
| FileInfoType[];
| FileInfoType[]
| setting.UserSettingType;
}
let loc: any = { hostname: "localhost", port: "80", protocol: "http" };
if (Ant.location) loc = Ant.location;
/**
* The host name of the server-side
*/
export var HOST: string =
loc.hostname + (loc.port ? `:${loc.port}` : "");
/**
* The base REST URI of the server-side API
*/
export var REST: string = `${loc.protocol}//${HOST}`;
/**
* The namespace `handle` contains some low level API to
* communicate with the server side API. It is the only
* API layer that communicate directly with the server.
* To make AntOS compatible with any server side API,
* all exported variable unctions defined in the `handle`
* namespace should be re-implemented
*/
export namespace handle {
// get file, require authentification
/**
* Base URI for reading content of VFS file
*/
export var get: string = `${REST}/VFS/get`;
// get shared file with publish
/**
* Base URI for VFS file sharing
*/
export var shared: string = `${REST}/VFS/shared`;
/**
* Send a request to the server-side API for a directory scanning
* operation
*
* @export
* @param {string} p a VFS file path e.g. home://test/
* @returns {Promise<RequestResult>} A promise on a [[RequestResult
* which contains an error or a list of FileInfoType
*/
export function scandir(p: string): Promise<RequestResult> {
const path = `${REST}/VFS/scandir`;
return API.post(path, { path: p });
}
/**
*
* Send a request to the server-side API for directory creation
*
* @export
* @param {string} p VFS path of the directory to be created
* @returns {Promise<RequestResult>} A promise on a RequestResult
* which contains an error or true on success
*/
export function mkdir(p: string): Promise<RequestResult> {
const path = `${API.REST}/VFS/mkdir`;
return API.post(path, { path: p });
}
/**
* Send a request to the server-side API for sharing/unsharing a VFS file,
* once shared a VFS file will be publicly visible by everyone
*
* @export
* @param {string} p VFS file path to be shared
* @param {boolean} pub flag: share (true) or unshare (false)
* @returns {Promise<RequestResult>} A promise on a RequestResult
* which contains an error or true on success
*/
export function sharefile(
p: string,
pub: boolean
@ -73,31 +192,88 @@ namespace OS {
return API.post(path, { path: p, publish: pub });
}
/**
* Get VFS file meta-data
*
* @export
* @param {string} p VFS file path
* @returns {Promise<RequestResult>} A promise on a [[RequestResult]]
* which contains an error or an object of FileInfoType
*/
export function fileinfo(p: string): Promise<RequestResult> {
const path = `${API.REST}/VFS/fileinfo`;
return API.post(path, { path: p });
}
/**
* Read a VFS file content. There are many ways a VFS file can be read:
* - Read as a raw text content
* - Read as a javascript file, in this case the content of the
* file will be executed
* - Read as JSON object
*
* @export
* @param {string} p path of the VFS file
* @param {string} t return data type:
* - jsonp: the response is an json object
* - script: the response is a javascript code
* - xm, html: the response is a XML/HTML object
* - text: plain text
*
* @returns {Promise<any>} A promise on a [[RequestResult]]
* which contains an error or an object of [[FileInfoType]]
*/
export function readfile(p: string, t: string): Promise<any> {
const path = `${API.REST}/VFS/get/`;
return API.get(path + p, t);
}
/**
* Move a file to another location on server-side
*
* @export
* @param {string} s VFS source file path
* @param {string} d VFS destination file path
* @returns {Promise<RequestResult>} A promise on a [[RequestResult]]
* which contains an error or a success response
*/
export function move(s: string, d: string): Promise<RequestResult> {
const path = `${API.REST}/VFS/move`;
return API.post(path, { src: s, dest: d });
}
/**
* Delete a VFS file on the server-side
*
* @export
* @param {string} p VFS file path
* @returns {Promise<RequestResult>} A promise on a [[RequestResult]]
* which contains an error or a success response
*/
export function remove(p: string): Promise<RequestResult> {
const path = `${API.REST}/VFS/delete`;
return API.post(path, { path: p });
}
/**
* Read the file as binary data
*
* @export
* @param {string} p VFS file to be read
* @returns {Promise<ArrayBuffer>} a Promise on an array buffer
*/
export function fileblob(p: string): Promise<ArrayBuffer> {
const path = `${API.REST}/VFS/get/`;
return API.blob(path + p);
}
/**
* Send a command to the serverside package manager
*
* @export
* @param {PackageCommandType} d a package command of type PackageCommandType
* @returns {Promise<RequestResult>} a promise on a [[RequestResult]]
*/
export function packages(
d: PackageCommandType
): Promise<RequestResult> {
@ -105,11 +281,26 @@ namespace OS {
return API.post(path, d);
}
/**
* Upload file to the server via VFS interface
*
* @export
* @param {string} d VFS destination directory path
* @returns {Promise<RequestResult>} a promise on a [[RequestResult]]
*/
export function upload(d: string): Promise<RequestResult> {
const path = `${API.REST}/VFS/upload`;
return API.upload(path, d);
}
/**
* Write Base 64 encoded data to a VFS file
*
* @export
* @param {string} p path to the VFS file
* @param {string} d file data encoded in Base 64
* @returns {Promise<RequestResult>} a promise on a [[RequestResult]]
*/
export function write(
p: string,
d: string
@ -117,6 +308,35 @@ namespace OS {
const path = `${API.REST}/VFS/write`;
return API.post(path, { path: p, data: d });
}
/**
* An apigateway allows client side to execute a custom server-side
* script and get back the result. This gateway is particularly
* useful in case of performing a task that is not provided by the core
* API
*
* @export
* @param {GenericObject<any>} d execution indication, provided only when ws is `false`
* otherwise, `d` should be written directly to the websocket stream as JSON object.
* Two possible formats of `d`:
* ```text
* execute an server-side script file:
*
* {
* path: [VFS path],
* parameters: [parameters of the server-side script]
* }
*
* or, execute directly a snippet of server-side script:
*
* { code: [server-side script code snippet as string] }
*
* ```
*
* @param {boolean} ws flag indicate whether to use websocket for the connection
* to the gateway API. In case of streaming data, the websocket is preferred
* @returns {Promise<any>} a promise on the result object (any)
*/
export function apigateway(
d: GenericObject<any>,
ws: boolean
@ -141,26 +361,98 @@ namespace OS {
}
}
/**
* Check if a user is logged in
*
* @export
* @returns {Promise<RequestResult>} a promise on a [[RequestResult]] that
* contains an error or a [[UserSettingType]] object
*/
export function auth(): Promise<RequestResult> {
const p = `${API.REST}/user/auth`;
return API.post(p, {});
}
/**
* Perform a login operation
*
* @export
* @param {UserLoginType} d user data [[UserLoginType]]
* @returns {Promise<RequestResult>} a promise on a [[RequestResult]] that
* contains an error or a [[UserSettingType]] object
*/
export function login(d: UserLoginType): Promise<RequestResult> {
const p = `${API.REST}/user/login`;
return API.post(p, d);
}
/**
* Perform a logout operation
*
* @export
* @returns {Promise<RequestResult>} a promise on a [[RequestResult]]
*/
export function logout(): Promise<RequestResult> {
const p = `${API.REST}/user/logout`;
return API.post(p, {});
}
/**
* Save the current user settings
*
* @export
* @returns {Promise<RequestResult>} a promise on a [[RequestResult]]
*/
export function setting(): Promise<RequestResult> {
const p = `${API.REST}/system/settings`;
return API.post(p, OS.setting);
}
/**
* This is the low level function of AntOS VDB API.
* It requests the server API to perform some simple
* SQL query.
*
* @export
* @param {string} cmd action to perform: save, delete, get, select
* @param {GenericObject<any>} d data object of the request based on each action:
* - save:
* ```
* { table: "table name", data: [record data object]}
* ```
* - get:
* ```
* { table: "table name", id: [record id]}
* ```
* - delete:
* ```
* { table: "table name", id: [record id]}
* or
* { table: "table name", cond: [conditional object]}
* ```
* - select:
* ```
* { table: "table name", cond: [conditional object]}
* ```
* @returns {Promise<RequestResult>} a promise of [[RequestResult]] on the
* query data
*
* A conditional object represents a SQL condition statement as an object,
* example: `pid = 10 AND cid = 2 ORDER BY date DESC`
* ```
* {
* exp: {
* "and": {
* pid: 10,
* cid: 2
* }
* },
* order: {
* date: "DESC"
* }
* }
* ```
*/
export function dbquery(
cmd: string,
d: GenericObject<any>

View File

@ -1,35 +1,69 @@
/*
* decaffeinate suggestions:
* DS101: Remove unnecessary use of Array.from
* DS102: Remove unnecessary code created because of implicit returns
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
namespace OS {
export namespace GUI {
/**
*
* Interface for an application dock item
*
* @export
* @interface AppDockItemType
*/
export interface AppDockItemType {
/**
* Reference to the application process represented
* by the dock item
*
* @type {application.BaseApplication}
* @memberof AppDockItemType
*/
app: application.BaseApplication;
/**
* Reference to the DOM element of
* the owner dock item
*
* @type {AFXTag}
* @memberof AppDockItemType
*/
domel?: AFXTag;
[propName: string]: any;
}
export namespace tag {
/**
*
* This class define the AntOS system application dock tag
*
* @export
* @class AppDockTag
* @extends {AFXTag}
*/
export class AppDockTag extends AFXTag {
/**
* variable holds the application select event
* callback handle
*
* @private
* @type {TagEventCallback<any>}
* @memberof AppDockTag
*/
private _onappselect: TagEventCallback<any>;
/**
* Items data of the dock
*
* @private
* @type {AppDockItemType[]}
* @memberof AppDockTag
*/
private _items: AppDockItemType[];
/**
* Reference to the currently select application
* process in the dock
*
* @private
* @type {application.BaseApplication}
* @memberof AppDockTag
*/
private _selectedApp: application.BaseApplication;
/**
@ -42,17 +76,17 @@ namespace OS {
}
/**
*
* Implementation of the abstract function: Update the current tag.
* It do nothing for this tag
*
* @protected
* @param {*} [d]
* @memberof AppDockTag
*/
protected reload(d?: any): void {
}
protected reload(d?: any): void {}
/**
*
* Init the tag before mounting
*
* @protected
* @memberof AppDockTag
@ -62,7 +96,8 @@ namespace OS {
}
/**
*
* The tag layout, it is empty on creation but elements will
* be added automatically to it in operation
*
* @protected
* @returns {TagLayoutType[]}
@ -73,16 +108,7 @@ namespace OS {
}
/**
*
*
* @protected
* @param {*} [d]
* @memberof AppDockTag
*/
protected refresh(d?: any): void {}
/**
*
* getter to get the dock items
*
* @readonly
* @type {AppDockItemType[]}
@ -93,7 +119,10 @@ namespace OS {
}
/**
*
* Setter to set the selected application in the dock
* this will trigger two event:
* - `focus`: on the selected application
* - `blur`: on all other applications on the dock
*
* @memberof AppDockTag
*/
@ -115,7 +144,8 @@ namespace OS {
}
/**
*
* getter to get the current selected application
* on the dock
*
* @type {BaseApplication}
* @memberof AppDockTag
@ -125,9 +155,12 @@ namespace OS {
}
/**
* When a new application process is created, this function
* will be called to add new application entry to the dock.
* The added application will becomes the current selected
* application
*
*
* @param {AppDockItemType} item
* @param {AppDockItemType} item an application dock item entry
* @memberof AppDockTag
*/
newapp(item: AppDockItemType): void {
@ -150,9 +183,11 @@ namespace OS {
}
/**
* Delete and application entry from the dock.
* This function will be called when an application
* is exit
*
*
* @param {BaseApplication} a
* @param {BaseApplication} a the application to be removed from the dock
* @memberof AppDockTag
*/
removeapp(a: application.BaseApplication): void {
@ -174,7 +209,7 @@ namespace OS {
}
/**
*
* Mount the current dock tag
*
* @protected
* @memberof AppDockTag
@ -184,7 +219,9 @@ namespace OS {
if (e.target === this) {
return;
}
const bt = $(e.target).closest("afx-button")[0] as any as ButtonTag;
const bt = ($(e.target).closest(
"afx-button"
)[0] as any) as ButtonTag;
const app = bt.data;
m.items = [
{ text: "__(Show)", dataid: "show" },

View File

@ -1,46 +1,113 @@
/*
* decaffeinate suggestions:
* DS102: Remove unnecessary code created because of implicit returns
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
namespace OS {
export namespace GUI {
export namespace tag {
/**
* This tag define a basic button and its behavior
*
* @export
* @class ButtonTag
* @extends {AFXTag}
*/
export class ButtonTag extends AFXTag {
private _selected: boolean;
/**
* Variable hold the button click callback handle
*
* @private
* @type {TagEventCallback<JQuery.MouseEventBase>}
* @memberof ButtonTag
*/
private _onbtclick: TagEventCallback<JQuery.MouseEventBase>;
/**
* Custom user data
*
* @type {GenericObject<any>}
* @memberof ButtonTag
*/
data: GenericObject<any>;
/**
*Creates an instance of ButtonTag.
* @memberof ButtonTag
*/
constructor() {
super();
}
set onbtclick(v: TagEventCallback<JQuery.MouseEventBase>)
{
/**
* Set the click callback handle for the target button
*
* @memberof ButtonTag
*/
set onbtclick(v: TagEventCallback<JQuery.MouseEventBase>) {
this._onbtclick = v;
}
/**
* Set the path to the button icon, the path should be
* a VFS file path
*
* @memberof ButtonTag
*/
set icon(v: string) {
$(this).attr("icon", v);
(this.refs.label as LabelTag).icon = v;
}
/**
* Set the icon class to the button, this property
* allows to style the button icon using CSS
*
* @memberof ButtonTag
*/
set iconclass(v: string) {
$(this).attr("iconclass", v);
(this.refs.label as LabelTag).iconclass = v;
}
set text(v: string | FormatedString) {
/**
* Set the text of the button
*
* @memberof ButtonTag
*/
set text(v: string | FormattedString) {
(this.refs.label as LabelTag).text = v;
}
get text(): string| FormatedString {
/**
* Get the current button test
*
* @type {(string| FormattedString)}
* @memberof ButtonTag
*/
get text(): string | FormattedString {
return (this.refs.label as LabelTag).text;
}
/**
* Enable or disable the button
*
* @memberof ButtonTag
*/
set enable(v: boolean) {
$(this.refs.button).prop("disabled", !v);
}
/**
* Get the `enable` property of the button
*
* @type {boolean}
* @memberof ButtonTag
*/
get enable(): boolean {
return !$(this.refs.button).prop("disabled");
}
/**
* set or remove the attribute `selected` of the button
*
* @memberof ButtonTag
*/
set selected(v: boolean) {
$(this.refs.button).removeClass();
this.attsw(v, "selected");
@ -48,18 +115,42 @@ namespace OS {
$(this.refs.button).addClass("selected");
}
}
/**
* check whether the attribute `selected` of the button is set
*
* @type {boolean}
* @memberof ButtonTag
*/
get selected(): boolean {
return this.hasattr("selected");
}
/**
* activate or deactivate the toggle mode of the button
*
* @memberof ButtonTag
*/
set toggle(v: boolean) {
this.attsw(v, "toggle");
}
/**
* Check whether the button is in toggle mode
*
* @type {boolean}
* @memberof ButtonTag
*/
get toggle(): boolean {
return this.hasattr("toggle");
}
/**
* Mount the tag
*
* @protected
* @memberof ButtonTag
*/
protected mount() {
$(this.refs.button).click((e) => {
const evt: TagEventType<JQuery.MouseEventBase> = {
@ -73,13 +164,42 @@ namespace OS {
}
});
}
/**
* Init the tag before mounting
*
* @protected
* @memberof ButtonTag
*/
protected init(): void {
this.enable = true;
this.toggle = false;
this._onbtclick = (e) => {};
}
/**
* Re-calibrate the button, do nothing in this tag
*
* @protected
* @memberof ButtonTag
*/
protected calibrate(): void {}
/**
* Update the current tag, do nothing in this tag
*
* @param {*} [d]
* @memberof ButtonTag
*/
reload(d?: any): void {}
/**
* Button layout definition
*
* @protected
* @returns {TagLayoutType[]}
* @memberof ButtonTag
*/
protected layout(): TagLayoutType[] {
return [
{
@ -90,6 +210,7 @@ namespace OS {
];
}
}
define("afx-button", ButtonTag);
}
}

View File

@ -1,25 +1,57 @@
/*
* decaffeinate suggestions:
* DS102: Remove unnecessary code created because of implicit returns
* DS202: Simplify dynamic range loops
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
namespace OS {
export namespace GUI {
export namespace tag {
/**
*
* Tag that define system calendar widget
*
* @export
* @class CalendarTag
* @extends {AFXTag}
*/
export class CalendarTag extends AFXTag {
/**
* The current selected day
*
* @private
* @type {number}
* @memberof CalendarTag
*/
private _day: number;
/**
* The current selected month
*
* @private
* @type {number}
* @memberof CalendarTag
*/
private _month: number;
/**
* The current selected year
*
* @private
* @type {number}
* @memberof CalendarTag
*/
private _year: number;
/**
* The current selected date object
*
* @private
* @type {Date}
* @memberof CalendarTag
*/
private _selectedDate: Date;
/**
* holder for date select event callback
*
* @private
* @type {TagEventCallback<Date>}
* @memberof CalendarTag
*/
private _ondateselect: TagEventCallback<Date>;
/**
@ -35,7 +67,7 @@ namespace OS {
}
/**
*
* Init the tag before mounting
*
* @protected
* @memberof CalendarTag
@ -46,17 +78,16 @@ namespace OS {
}
/**
*
* Update the current tag, doing nothing in this tag
*
* @protected
* @param {*} [d]
* @param {*} [d] any data object
* @memberof CalendarTag
*/
protected reload(d?: any): void {
}
protected reload(d?: any): void {}
/**
*
* Get the current selected date in the widget
*
* @readonly
* @type {Date}
@ -67,7 +98,7 @@ namespace OS {
}
/**
*
* Set the date select event callback handle for the widget
*
* @memberof CalendarTag
*/
@ -76,7 +107,7 @@ namespace OS {
}
/**
*
* Mount the current widget to the DOM tree
*
* @protected
* @memberof CalendarTag
@ -104,14 +135,16 @@ namespace OS {
}
/**
*
* This function triggers the date select event
*
* @private
* @param {TagEventType} e
* @param {TagEventType} e AFX tag event data [[TagEventType]]
* @returns {void}
* @memberof CalendarTag
*/
private dateselect(e: TagEventType<TagEventDataType<tag.GridCellPrototype>>): void {
private dateselect(
e: TagEventType<TagEventDataType<tag.GridCellPrototype>>
): void {
if (!e.data.item) {
return;
}
@ -121,7 +154,11 @@ namespace OS {
}
const evt = {
id: this.aid,
data: new Date(this._year, this._month, parseInt(value)),
data: new Date(
this._year,
this._month,
parseInt(value)
),
};
this._ondateselect(evt);
this._selectedDate = evt.data;
@ -129,7 +166,7 @@ namespace OS {
}
/**
*
* Calibrate the layout of the tag
*
* @protected
* @memberof CalendarTag
@ -142,7 +179,7 @@ namespace OS {
}
/**
*
* Display the previous month of the current month
*
* @private
* @memberof CalendarTag
@ -157,9 +194,8 @@ namespace OS {
this.calendar(new Date(this._year, this._month, 1));
}
/**
*
* Display the next month of the current month
*
* @private
* @returns
@ -176,7 +212,7 @@ namespace OS {
}
/**
*
* Visualize the calendar base on input date
*
* @private
* @param {Date} date
@ -265,11 +301,13 @@ namespace OS {
rows.push(row);
const grid = this.refs.grid as GridViewTag;
grid.rows = rows;
(this.refs.mlbl as LabelTag).text = `${months[this._month]} ${this._year}`;
(this.refs.mlbl as LabelTag).text = `${
months[this._month]
} ${this._year}`;
}
/**
*
* Layout definition of the widget
*
* @protected
* @returns {TagLayoutType[]}

View File

@ -1,38 +1,89 @@
/*
* decaffeinate suggestions:
* DS102: Remove unnecessary code created because of implicit returns
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
namespace OS {
export namespace GUI {
/**
*
* Color type used by AFX API
*
* @export
* @interface ColorType
*/
export interface ColorType {
/**
* Red chanel
*
* @type {number}
* @memberof ColorType
*/
r: number;
/**
* Green chanel
*
* @type {number}
* @memberof ColorType
*/
g: number;
/**
* Blue chanel
*
* @type {number}
* @memberof ColorType
*/
b: number;
/**
* Alpha chanel
*
* @type {number}
* @memberof ColorType
*/
a?: number;
/**
* color text in CSS format
*
* @type {string}
* @memberof ColorType
*/
text?: string;
/**
* Color in hex format
*
* @type {string}
* @memberof ColorType
*/
hex?: string;
}
export namespace tag {
/**
*
* Class definition of Color picker widget
*
* @export
* @class ColorPickerTag
* @extends {AFXTag}
*/
export class ColorPickerTag extends AFXTag {
/**
* The current selected color object
*
* @private
* @type {ColorType}
* @memberof ColorPickerTag
*/
private _selectedColor: ColorType;
/**
* Holder for the color select event callback
*
* @private
* @type {TagEventCallback<ColorType>}
* @memberof ColorPickerTag
*/
private _oncolorselect: TagEventCallback<ColorType>;
/**
*Creates an instance of ColorPickerTag.
* Creates an instance of ColorPickerTag.
* @memberof ColorPickerTag
*/
constructor() {
@ -41,7 +92,7 @@ namespace OS {
}
/**
*
* Init tag before mounting, do nothing
*
* @protected
* @memberof ColorPickerTag
@ -49,7 +100,7 @@ namespace OS {
protected init(): void {}
/**
*
* Reload tag, do nothing
*
* @protected
* @param {*} [d]
@ -58,7 +109,7 @@ namespace OS {
protected reload(d?: any): void {}
/**
*
* Get selected color value
*
* @readonly
* @type {ColorType}
@ -69,7 +120,7 @@ namespace OS {
}
/**
*
* Set the color select event handle
*
* @memberof ColorPickerTag
*/
@ -78,7 +129,7 @@ namespace OS {
}
/**
*
* Mount the widget to DOM tree
*
* @protected
* @memberof ColorPickerTag
@ -112,7 +163,7 @@ namespace OS {
}
/**
*
* Build the color palette
*
* @private
* @memberof ColorPickerTag
@ -237,7 +288,7 @@ namespace OS {
}
/**
*
* layout definition of the widget
*
* @protected
* @returns {TagLayoutType[]}

View File

@ -1,25 +1,74 @@
/*
* decaffeinate suggestions:
* DS102: Remove unnecessary code created because of implicit returns
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
namespace OS {
export namespace GUI {
export namespace tag {
/**
*
* Definition of system file view widget
*
* @export
* @class FileViewTag
* @extends {AFXTag}
*/
export class FileViewTag extends AFXTag {
/**
* Holder for file select event callback
*
* @private
* @type {TagEventCallback<API.FileInfoType>}
* @memberof FileViewTag
*/
private _onfileselect: TagEventCallback<API.FileInfoType>;
/**
* Holder for file open event callback
*
* @private
* @type {TagEventCallback<API.FileInfoType>}
* @memberof FileViewTag
*/
private _onfileopen: TagEventCallback<API.FileInfoType>;
/**
* Reference to the currently selected file meta-data
*
* @private
* @type {API.FileInfoType}
* @memberof FileViewTag
*/
private _selectedFile: API.FileInfoType;
/**
* Data holder of the current working directory
*
* @private
* @type {API.FileInfoType[]}
* @memberof FileViewTag
*/
private _data: API.FileInfoType[];
/**
* The path of the current working directory
*
* @private
* @type {string}
* @memberof FileViewTag
*/
private _path: string;
/**
* Header definition of the widget grid view
*
* @private
* @type {(GenericObject<string | number>[])}
* @memberof FileViewTag
*/
private _header: GenericObject<string | number>[];
/**
* Holder for the user-specified meta-data fetch function
*
* @private
* @memberof FileViewTag
*/
private _fetch: (p: string) => Promise<API.FileInfoType[]>;
/**
@ -31,7 +80,7 @@ namespace OS {
}
/**
*
* Init the widget before mounting
*
* @protected
* @memberof FileViewTag
@ -51,15 +100,18 @@ namespace OS {
}
/**
*
* Update the current widget, do nothing
*
* @protected
* @param {*} [d]
* @memberof FileViewTag
*/
protected reload(d?: any): void {}
/**
*
* set the function that allows to fetch file entries.
* This handle function should return a promise on
* an arry of [[API.FileInfoType]]
*
* @memberof FileViewTag
*/
@ -68,7 +120,9 @@ namespace OS {
}
/**
*
* set the callback handle for the file select event.
* The parameter of the callback should be an object
* of type [[TagEventType]]<T> with the data type `T` is [[API.FileInfoType]]
*
* @memberof FileViewTag
*/
@ -77,7 +131,9 @@ namespace OS {
}
/**
*
set the callback handle for the file open event.
* The parameter of the callback should be an object
* of type [[TagEventType]]<T> with the data type `T` is [[API.FileInfoType]]
*
* @memberof FileViewTag
*/
@ -86,7 +142,10 @@ namespace OS {
}
/**
*
* chang the view of the widget, there are three different views
* - `icon`
* - `list`
* - `tree`
*
* @memberof FileViewTag
*/
@ -96,7 +155,7 @@ namespace OS {
}
/**
*
* Get the current view setting of the widget
*
* @type {string}
* @memberof FileViewTag
@ -106,7 +165,10 @@ namespace OS {
}
/**
*
* Turn on/off the changing current working directory feature
* of the widget when a directory is double clicked. If enabled,
* the widget will use the configured [[fetch]] function to query
* the content of the selected directory
*
* @memberof FileViewTag
*/
@ -115,7 +177,8 @@ namespace OS {
}
/**
*
* check whether changing current working directory feature
* is enabled
*
* @type {boolean}
* @memberof FileViewTag
@ -125,7 +188,7 @@ namespace OS {
}
/**
*
* Enable or disable the status bar of the widget
*
* @memberof FileViewTag
*/
@ -139,7 +202,7 @@ namespace OS {
}
/**
*
* Check whether the status bar is enabled
*
* @type {boolean}
* @memberof FileViewTag
@ -149,7 +212,7 @@ namespace OS {
}
/**
*
* Allow the widget to show or hide hidden file
*
* @memberof FileViewTag
*/
@ -162,7 +225,8 @@ namespace OS {
}
/**
*
* Check whether the hidden file should be shown in
* the widget
*
* @type {boolean}
* @memberof FileViewTag
@ -172,7 +236,7 @@ namespace OS {
}
/**
*
* Get the current selected file
*
* @readonly
* @type {API.FileInfoType}
@ -183,7 +247,10 @@ namespace OS {
}
/**
*
* Set the path of the current working directory.
* When called the widget will refresh the current
* working directory using the configured [[fetch]]
* function
*
* @memberof FileViewTag
*/
@ -211,7 +278,7 @@ namespace OS {
}
/**
*
* Get the path of the current working directory
*
* @type {string}
* @memberof FileViewTag
@ -221,7 +288,7 @@ namespace OS {
}
/**
*
* Set the data of the current working directory
*
* @memberof FileViewTag
*/
@ -234,7 +301,7 @@ namespace OS {
}
/**
*
* Get the data of the current working directory
*
* @type {API.FileInfoType[]}
* @memberof FileViewTag
@ -244,21 +311,26 @@ namespace OS {
}
/**
*
* Set the file drag and drop event handle. This allows application
* to define custom behavior of the event
*
* @memberof FileViewTag
*/
set ondragndrop(v: TagEventCallback<DnDEventDataType<TreeViewTag| ListViewItemTag>>) {
set ondragndrop(
v: TagEventCallback<
DnDEventDataType<TreeViewTag | ListViewItemTag>
>
) {
(this.refs.treeview as TreeViewTag).ondragndrop = v;
(this.refs.listview as ListViewTag).ondragndrop = v;
}
/**
*
* sort file by it type
*
* @private
* @param {API.FileInfoType} a
* @param {API.FileInfoType} b
* @param {API.FileInfoType} a first file meta-data
* @param {API.FileInfoType} b second file meta-data
* @returns {(0|-1|1)}
* @memberof FileViewTag
*/
@ -276,7 +348,7 @@ namespace OS {
}
/**
*
* calibrate the widget layout
*
* @memberof FileViewTag
*/
@ -295,7 +367,8 @@ namespace OS {
}
/**
*
* Refresh the list view of the widget. This function
* is called when the view of the widget changed to `icon`
*
* @private
* @memberof FileViewTag
@ -318,7 +391,8 @@ namespace OS {
}
/**
*
* Refresh the grid view of the widget, this function is called
* when the view of the widget set to `list`
*
* @private
* @memberof FileViewTag
@ -348,7 +422,8 @@ namespace OS {
}
/**
*
* Refresh the Treeview of the widget, this function is called
* when the view of the widget set to `tree`
*
* @private
* @memberof FileViewTag
@ -359,17 +434,18 @@ namespace OS {
text: this.path,
path: this.path,
open: true,
nodes: this.getTreeData(this.data)
nodes: this.getTreeData(this.data),
};
(this.refs.treeview as TreeViewTag).data = tdata;
// (this.refs.treeview as TreeViewTag).expandAll();
// (this.refs.treeview as TreeViewTag).expandAll();
}
/**
*
* Create the tree data from the list of input
* file meta-data
*
* @private
* @param {API.FileInfoType[]} data
* @param {API.FileInfoType[]} data list of file meta-data
* @returns {TreeViewDataType[]}
* @memberof FileViewTag
*/
@ -395,7 +471,7 @@ namespace OS {
}
/**
*
* Refresh data of the current widget view
*
* @private
* @returns {void}
@ -417,7 +493,7 @@ namespace OS {
}
/**
*
* Switch between three view options
*
* @private
* @memberof FileViewTag
@ -445,10 +521,10 @@ namespace OS {
}
/**
*
* This function triggers the file select event
*
* @private
* @param {API.FileInfoType} e
* @param {API.FileInfoType} e selected file meta-data
* @memberof FileViewTag
*/
private fileselect(e: API.FileInfoType): void {
@ -470,10 +546,10 @@ namespace OS {
}
/**
*
* This function triggers the file open event
*
* @private
* @param {API.FileInfoType} e
* @param {API.FileInfoType} e selected file meta-data
* @memberof FileViewTag
*/
private filedbclick(e: API.FileInfoType): void {
@ -491,7 +567,7 @@ namespace OS {
}
/**
*
* Mount the widget in the DOM tree
*
* @protected
* @memberof FileViewTag
@ -529,27 +605,28 @@ namespace OS {
};
grid.onrowselect = (e) => {
this.fileselect(
$(e.data.item).children()[0].data as API.FileInfoType
$(e.data.item).children()[0]
.data as API.FileInfoType
);
};
tree.ontreeselect = (e) => {
this.fileselect(e.data.item.data as API.FileInfoType);
this.fileselect(e.data.item.data as API.FileInfoType);
};
// dblclick
list.onlistdbclick = (e) => {
this.filedbclick(e.data.item.data as API.FileInfoType);
this.filedbclick(e.data.item.data as API.FileInfoType);
};
grid.oncelldbclick = (e) => {
this.filedbclick(e.data.item.data as API.FileInfoType);
};
tree.ontreedbclick = (e) => {
this.filedbclick(e.data.item.data as API.FileInfoType);
this.filedbclick(e.data.item.data as API.FileInfoType);
};
this.switchView();
}
/**
*
* Layout definition of the widget
*
* @protected
* @returns {TagLayoutType[]}

View File

@ -1,21 +1,32 @@
/*
* decaffeinate suggestions:
* DS102: Remove unnecessary code created because of implicit returns
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
namespace OS {
export namespace GUI {
export namespace tag {
/**
*
* A float list is a list of items in which each
* item can be moved (drag and drop) freely
*
* @export
* @class FloatListTag
* @extends {ListViewTag}
*/
export class FloatListTag extends ListViewTag {
protected reload(d?: any): void {
}
/**
* Update the current tag, do nothing
*
* @protected
* @param {*} [d]
* @memberof FloatListTag
*/
protected reload(d?: any): void {}
/**
* Variable that hold the onready callback of
* the tag. This callback will be called after
* the tag is mounted
*
* @private
* @memberof FloatListTag
*/
private _onready: (e: FloatListTag) => void;
/**
@ -27,7 +38,9 @@ namespace OS {
}
/**
*
* set the onready callback function to the tag.
* This callback will be called after
* the tag is mounted
*
* @memberof FloatListTag
*/
@ -36,7 +49,12 @@ namespace OS {
}
/**
* Set the direction of the list item layout.
* Two directions are available:
* - `vertical`
* - `horizontal`
*
* This setter acts as a DOM attribute
*
* @memberof FloatListTag
*/
@ -46,7 +64,8 @@ namespace OS {
}
/**
*
* Get the currently set direction of list
* item layout
*
* @type {string}
* @memberof FloatListTag
@ -54,24 +73,24 @@ namespace OS {
get dir(): string {
return $(this).attr("dir");
}
// disable some uneccessary functions
/**
*
* Disable the dropdown option in this list
*
* @memberof FloatListTag
*/
set dropdown(v: boolean) {}
/**
*
* Disable the list buttons configuration in this
* list
*
* @memberof FloatListTag
*/
set buttons(v: GenericObject<any>[]) {}
/**
*
* Disable the `showlist` behavior in this list
*
* @protected
* @param {*} e
@ -80,7 +99,7 @@ namespace OS {
protected showlist(e: any) {}
/**
*
* Disable the `dropoff` behavior in this list
*
* @protected
* @param {*} e
@ -89,7 +108,8 @@ namespace OS {
protected dropoff(e: any) {}
/**
*
* Function called when the data of the list
* is changed
*
* @protected
* @memberof FloatListTag
@ -99,7 +119,7 @@ namespace OS {
}
/**
*
* Mount the list to the DOM tree
*
* @protected
* @returns {void}
@ -120,9 +140,9 @@ namespace OS {
}
/**
* Push an element to the list
*
*
* @param {GenericObject<any>} v
* @param {GenericObject<any>} v an element data
* @returns
* @memberof FloatListTag
*/
@ -133,10 +153,10 @@ namespace OS {
}
/**
*
* Enable drag and drop on the list
*
* @private
* @param {ListViewItemTag} el
* @param {ListViewItemTag} el the list item DOM element
* @memberof FloatListTag
*/
private enable_drag(el: ListViewItemTag): void {
@ -174,7 +194,7 @@ namespace OS {
}
/**
*
* Calibrate the view of the list
*
* @memberof FloatListTag
*/

View File

@ -1,24 +1,39 @@
/*
* decaffeinate suggestions:
* DS101: Remove unnecessary use of Array.from
* DS102: Remove unnecessary code created because of implicit returns
* DS205: Consider reworking code to avoid use of IIFEs
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
/**
* Extend the Array interface with some
* property needed by AFX API
*
* @interface Array
* @template T
*/
interface Array<T> {
domel: GenericObject<any>;
/**
* Reference to a DOM element created by AFX API,
* this property is used by some AFX tags to refer
* to its child element in it data object
*
* @type {GenericObject<any>}
* @memberof Array
*/
domel?: GenericObject<any>;
}
namespace OS {
export namespace GUI {
export namespace tag {
/**
*
* A grid Row is a simple element that
* contains a group of grid cell
*
* @export
* @class GridRowTag
* @extends {AFXTag}
*/
export class GridRowTag extends AFXTag {
/**
* Data holder for a collection of cell data
*
* @type {GenericObject<any>[]}
* @memberof GridRowTag
*/
data: GenericObject<any>[];
/**
@ -32,7 +47,7 @@ namespace OS {
}
/**
*
* Mount the tag, do nothing
*
* @protected
* @memberof GridRowTag
@ -40,7 +55,7 @@ namespace OS {
protected mount(): void {}
/**
*
* Init the tag before mounting: reset the data holder
*
* @protected
* @memberof GridRowTag
@ -50,7 +65,7 @@ namespace OS {
}
/**
*
* Empty layout
*
* @protected
* @returns {TagLayoutType[]}
@ -61,7 +76,7 @@ namespace OS {
}
/**
*
* This function does nothing in this tag
*
* @protected
* @memberof GridRowTag
@ -69,7 +84,7 @@ namespace OS {
protected calibrate(): void {}
/**
*
* This function does nothing in this tag
*
* @protected
* @param {*} [d]
@ -78,10 +93,15 @@ namespace OS {
protected reload(d?: any): void {}
}
/**
* Event data used by grid cell
*/
export type CellEventData = TagEventDataType<GridCellPrototype>;
/**
*
* Prototype of any grid cell, custom grid cell
* definition should extend and implement this
* abstract prototype
*
* @export
* @abstract
@ -89,8 +109,31 @@ namespace OS {
* @extends {AFXTag}
*/
export abstract class GridCellPrototype extends AFXTag {
/**
* Holder for cell selected event callback
*
* @private
* @type {TagEventCallback<CellEventData>}
* @memberof GridCellPrototype
*/
private _oncellselect: TagEventCallback<CellEventData>;
/**
* Holder for cell double click event callback
*
* @private
* @type {TagEventCallback<CellEventData>}
* @memberof GridCellPrototype
*/
private _oncelldbclick: TagEventCallback<CellEventData>;
/**
* Data holder of the current cell
*
* @private
* @type {GenericObject<any>}
* @memberof GridCellPrototype
*/
private _data: GenericObject<any>;
/**
@ -102,7 +145,7 @@ namespace OS {
}
/**
*
* Set the cell selected event callback
*
* @memberof GridCellPrototype
*/
@ -111,7 +154,7 @@ namespace OS {
}
/**
*
* Set the cell double click event callback
*
* @memberof GridCellPrototype
*/
@ -120,7 +163,8 @@ namespace OS {
}
/**
*
* Set the data of the cell, this will trigger
* the [[ondatachange]] function
*
* @memberof GridCellPrototype
*/
@ -135,7 +179,7 @@ namespace OS {
}
/**
*
* Get the current cell data holder
*
* @type {GenericObject<any>}
* @memberof GridCellPrototype
@ -145,7 +189,9 @@ namespace OS {
}
/**
*
* Set/unset the current cell as selected.
* This will trigger the [[cellselect]]
* event
*
* @memberof GridCellPrototype
*/
@ -159,7 +205,7 @@ namespace OS {
}
/**
*
* Check whether the current cell is selected
*
* @type {boolean}
* @memberof GridCellPrototype
@ -169,7 +215,8 @@ namespace OS {
}
/**
*
* Update the current cell. This will
* reset the cell data
*
* @protected
* @param {*} d
@ -180,7 +227,7 @@ namespace OS {
}
/**
*
* Mount the current cell to the grid
*
* @protected
* @memberof GridCellPrototype
@ -203,7 +250,8 @@ namespace OS {
}
/**
*
* This function triggers the cell select
* event
*
* @private
* @param {TagEventType<GridCellPrototype>} e
@ -223,7 +271,8 @@ namespace OS {
}
/**
*
* Abstract function called when the cell data changed.
* This should be implemented by subclasses
*
* @protected
* @abstract
@ -233,7 +282,8 @@ namespace OS {
}
/**
*
* Simple grid cell defines a grid cell with
* an [[LabelTag]] as it cell layout
*
* @export
* @class SimpleGridCellTag
@ -249,7 +299,7 @@ namespace OS {
}
/**
*
* Reset the label of the cell with its data
*
* @protected
* @memberof SimpleGridCellTag
@ -259,7 +309,7 @@ namespace OS {
}
/**
*
* This function do nothing in this tag
*
* @protected
* @memberof SimpleGridCellTag
@ -267,7 +317,7 @@ namespace OS {
protected init(): void {}
/**
*
* This function do nothing in this tag
*
* @protected
* @memberof SimpleGridCellTag
@ -275,7 +325,7 @@ namespace OS {
protected calibrate(): void {}
/**
*
* The layout of the cell with a simple [[LabelTag]]
*
* @returns
* @memberof SimpleGridCellTag
@ -291,24 +341,89 @@ namespace OS {
}
/**
*
* A Grid contains a header and a collection grid rows
* which has the same number of cells as the number of
* the header elements
*
* @export
* @class GridViewTag
* @extends {AFXTag}
*/
export class GridViewTag extends AFXTag {
/**
* Grid header definition
*
* @private
* @type {GenericObject<any>[]}
* @memberof GridViewTag
*/
private _header: GenericObject<any>[];
/**
* Grid rows data holder
*
* @private
* @type {GenericObject<any>[][]}
* @memberof GridViewTag
*/
private _rows: GenericObject<any>[][];
/**
* Reference to the current selected row DOM element
*
* @private
* @type {GridRowTag}
* @memberof GridViewTag
*/
private _selectedRow: GridRowTag;
/**
* A collection of selected grid rows DOM element
*
* @private
* @type {GridRowTag[]}
* @memberof GridViewTag
*/
private _selectedRows: GridRowTag[];
/**
* Reference to the current selected cell
*
* @private
* @type {GridCellPrototype}
* @memberof GridViewTag
*/
private _selectedCell: GridCellPrototype;
/**
* Cell select event callback holder
*
* @private
* @type {TagEventCallback<CellEventData>}
* @memberof GridViewTag
*/
private _oncellselect: TagEventCallback<CellEventData>;
/**
* Row select event callback holder
*
* @private
* @type {TagEventCallback<CellEventData>}
* @memberof GridViewTag
*/
private _onrowselect: TagEventCallback<CellEventData>;
/**
* Cell double click event callback holder
*
* @private
* @type {TagEventCallback<CellEventData>}
* @memberof GridViewTag
*/
private _oncelldbclick: TagEventCallback<CellEventData>;
/**
*Creates an instance of GridViewTag.
* Creates an instance of GridViewTag.
* @memberof GridViewTag
*/
constructor() {
@ -316,7 +431,8 @@ namespace OS {
}
/**
*
* Init the grid view before mounting.
* Reset all the holders to default values
*
* @protected
* @memberof GridViewTag
@ -335,7 +451,7 @@ namespace OS {
}
/**
*
* This function does nothing
*
* @protected
* @param {*} [d]
@ -344,7 +460,7 @@ namespace OS {
protected reload(d?: any): void {}
/**
*
* set the cell select event callback
*
* @memberof GridViewTag
*/
@ -353,7 +469,7 @@ namespace OS {
}
/**
*
* set the row select event callback
*
* @memberof GridViewTag
*/
@ -362,7 +478,7 @@ namespace OS {
}
/**
*
* set the cell double click event callback
*
* @memberof GridViewTag
*/
@ -371,7 +487,7 @@ namespace OS {
}
/**
*
* set the tag name of the header cells
*
* @memberof GridViewTag
*/
@ -380,7 +496,7 @@ namespace OS {
}
/**
*
* get the grid header tag name
*
* @type {string}
* @memberof GridViewTag
@ -390,7 +506,7 @@ namespace OS {
}
/**
*
* set the tag name of the grid cell
*
* @memberof GridViewTag
*/
@ -399,7 +515,7 @@ namespace OS {
}
/**
*
* get the tag name of the grid cell
*
* @type {string}
* @memberof GridViewTag
@ -409,7 +525,7 @@ namespace OS {
}
/**
*
* get the header data holder
*
* @type {GenericObject<any>[]}
* @memberof GridViewTag
@ -419,7 +535,7 @@ namespace OS {
}
/**
*
* the set the header data
*
* @memberof GridViewTag
*/
@ -443,7 +559,7 @@ namespace OS {
}
/**
*
* Get all the selected rows
*
* @readonly
* @type {GridRowTag[]}
@ -454,7 +570,7 @@ namespace OS {
}
/**
*
* Get the latest selected row
*
* @readonly
* @type {GridRowTag}
@ -465,7 +581,7 @@ namespace OS {
}
/**
*
* Get the current selected cell
*
* @readonly
* @type {GridCellPrototype}
@ -476,7 +592,7 @@ namespace OS {
}
/**
*
* set the rows data
*
* @memberof GridViewTag
*/
@ -487,7 +603,7 @@ namespace OS {
}
/**
*
* get the rows data
*
* @type {GenericObject<any>[][]}
* @memberof GridViewTag
@ -497,7 +613,7 @@ namespace OS {
}
/**
*
* activate deactivate multi-select
*
* @memberof GridViewTag
*/
@ -506,8 +622,7 @@ namespace OS {
}
/**
*
*
* check whether the `multiselect` option is activated
* @type {boolean}
* @memberof GridViewTag
*/
@ -516,9 +631,9 @@ namespace OS {
}
/**
* Delete a grid rows
*
*
* @param {GridRowTag} row
* @param {GridRowTag} row row DOM element
* @returns {void}
* @memberof GridViewTag
*/
@ -546,11 +661,12 @@ namespace OS {
}
/**
* Push a row to the grid
*
*
* @param {GenericObject<any>[]} row
* @param {boolean} flag
* @memberof GridViewTag
* @param {GenericObject<any>[]} row list of cell data
* @param {boolean} flag indicates where the row is add to beginning or end
* of the row
* @memberof GridViewTags
*/
push(row: GenericObject<any>[], flag: boolean): void {
const rowel = $("<afx-grid-row>").css(
@ -590,9 +706,9 @@ namespace OS {
}
/**
* Unshift a row to the grid
*
*
* @param {GenericObject<any>[]} row
* @param {GenericObject<any>[]} row list of cell data in the row
* @memberof GridViewTag
*/
unshift(row: GenericObject<any>[]): void {
@ -600,14 +716,15 @@ namespace OS {
}
/**
* This function triggers the cell select event
*
*
* @param {TagEventType<CellEventData>} e
* @param {boolean} flag
* @private
* @param {TagEventType<CellEventData>} e event contains cell event data
* @param {boolean} flag indicates whether the event is double clicked
* @returns {void}
* @memberof GridViewTag
*/
cellselect(
private cellselect(
e: TagEventType<CellEventData>,
flag: boolean
): void {
@ -629,13 +746,14 @@ namespace OS {
}
/**
*
* This function triggers the row selected event, a cell select
* event will also trigger this event
*
* @param {TagEventType<CellEventData>} e
* @returns {void}
* @memberof GridViewTag
*/
rowselect(e: TagEventType<CellEventData>): void {
private rowselect(e: TagEventType<CellEventData>): void {
if (!e.data.item) {
return;
}
@ -680,7 +798,7 @@ namespace OS {
}
/**
*
* Check whether the grid has header
*
* @private
* @returns {boolean}
@ -692,7 +810,7 @@ namespace OS {
}
/**
*
* Calibrate the grid
*
* @protected
* @memberof GridViewTag
@ -715,7 +833,9 @@ namespace OS {
}
/**
*
* Recalculate the size of each header cell, changing
* in header cell size will also resize the entire
* related column
*
* @private
* @returns {void}
@ -756,7 +876,7 @@ namespace OS {
}
/**
*
* Mount the grid view tag
*
* @protected
* @returns {void}
@ -776,7 +896,7 @@ namespace OS {
}
/**
*
* Layout definition of the grid view
*
* @protected
* @returns {TagLayoutType[]}

View File

@ -7,7 +7,7 @@ namespace OS {
export namespace GUI {
export namespace tag {
export class LabelTag extends AFXTag {
private _text: string | FormatedString;
private _text: string | FormattedString;
constructor() {
super();
}
@ -53,7 +53,7 @@ namespace OS {
}
}
set text(v: string | FormatedString) {
set text(v: string | FormattedString) {
this._text = v;
if (v && v !== "") {
$(this.refs.text).show();
@ -63,7 +63,7 @@ namespace OS {
}
}
get text(): string| FormatedString {
get text(): string| FormattedString {
return this._text;
}

View File

@ -1,16 +1,16 @@
/*
* decaffeinate suggestions:
* DS101: Remove unnecessary use of Array.from
* DS102: Remove unnecessary code created because of implicit returns
* DS205: Consider reworking code to avoid use of IIFEs
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
namespace OS {
export namespace GUI {
export namespace tag {
/**
* List item event data type
*/
export type ListItemEventData = TagEventDataType<ListViewItemTag>
/**
*
* A list item represent the individual view of an item in the [[ListView]].
* This class is an abstract prototype class, implementation of any
* list view item should extend it
*
*
* @export
* @abstract
@ -18,11 +18,59 @@ namespace OS {
* @extends {AFXTag}
*/
export abstract class ListViewItemTag extends AFXTag {
/**
* Data holder for the list item
*
* @private
* @type {GenericObject<any>}
* @memberof ListViewItemTag
*/
private _data: GenericObject<any>;
/**
* Holder for the item select event callback
*
* @private
* @type {TagEventCallback<ListItemEventData>}
* @memberof ListViewItemTag
*/
private _onselect: TagEventCallback<ListItemEventData>;
/**
* Context menu event callback handle
*
* @private
* @type {TagEventCallback<ListItemEventData>}
* @memberof ListViewItemTag
*/
private _onctxmenu: TagEventCallback<ListItemEventData>;
/**
* Click event callback holder
*
* @private
* @type {TagEventCallback<ListItemEventData>}
* @memberof ListViewItemTag
*/
private _onclick: TagEventCallback<ListItemEventData>;
/**
* Double click event callback handle
*
* @private
* @type {TagEventCallback<ListItemEventData>}
* @memberof ListViewItemTag
*/
private _ondbclick: TagEventCallback<ListItemEventData>;
/**
* Item close event callback holder
*
* @private
* @type {TagEventCallback<ListItemEventData>}
* @memberof ListViewItemTag
*/
private _onclose: TagEventCallback<ListItemEventData>;
/**

View File

@ -15,7 +15,7 @@ namespace OS {
* @extends {AFXTag}
*/
export class SystemPanelTag extends AFXTag {
private _osmenu: GenericObject<string | FormatedString>;
private _osmenu: GenericObject<string | FormattedString>;
private _view: boolean;
private _cb: (e: JQuery.MouseEventBase) => void;

View File

@ -81,13 +81,13 @@ namespace OS {
get resizable(): boolean {
return this.hasattr("resizable");
}
set apptitle(v: string| FormatedString) {
set apptitle(v: string| FormattedString) {
$(this).attr("apptitle", v.__());
if (v) {
(this.refs["txtTitle"] as LabelTag).text = v;
}
}
get apptitle(): string| FormatedString {
get apptitle(): string| FormattedString {
return $(this).attr("apptitle");
}

View File

@ -1,20 +1,95 @@
/*
* decaffeinate suggestions:
* DS101: Remove unnecessary use of Array.from
* DS102: Remove unnecessary code created because of implicit returns
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
/**
*
* Extend the HTMLElement interface with some utility function need
* by AFX API
*
* @interface HTMLElement
*/
interface HTMLElement {
/**
* Recursively update a tag and all its children
*
* @param {*} [d] data to send to all element in the DOM subtree
* @memberof HTMLElement
*/
update(d?: any): void;
/**
*
* AFX will automatically bind the context menu on an HTMLElement
* if this function is defined on that element. The function should
* define the content of the context menu and its action
*
* Once the context menu is bound to the element, all context menu handle
* defined on any child of this element will be ignored.
*
* @param {JQuery.MouseEventBase} e a mouse event
* @param {OS.GUI.tag.MenuTag} m The context menu element [[MenuTag]]
* @memberof HTMLElement
*/
contextmenuHandle(e: JQuery.MouseEventBase, m: OS.GUI.tag.MenuTag): void;
/**
* Mount the element and all the children on its DOM subtree. This action
* is performed in a top-down manner
*
* @memberof HTMLElement
*/
sync(): void;
/**
*
* This action allows to generated all the DOM nodes defined by all AFX tags
* in its hierarchy.
* It performs two operations, one top-down operation to generate all the
* necessary DOM nodes, another bottom-up operation to init all the AFX tag
* in the current element DOM hierarchy
*
* @param {OS.API.Announcer} o an AntOS observable object
* @memberof HTMLElement
*/
afxml(o: OS.API.Announcer): void;
/**
* Perform DOM generation ([[afxml]]) then mount ([[sync]]) all the
* elements.
*
* @param {OS.API.Announcer} o an AntOS observable object
* @param {boolean} [flag] indicates whether this is the top-most call of the operation
* @memberof HTMLElement
*/
uify(o: OS.API.Announcer, flag?: boolean): void;
/**
*
*
* @type {*}
* @memberof HTMLElement
*/
mozRequestFullScreen: any;
/**
*
*
* @type {*}
* @memberof HTMLElement
*/
webkitRequestFullscreen: any;
/**
*
*
* @type {*}
* @memberof HTMLElement
*/
msRequestFullscreen: any;
}
/**
*
*
* @interface Document
*/
interface Document {
mozCancelFullScreen: any;
webkitExitFullscreen: any;
@ -22,37 +97,205 @@ interface Document {
}
namespace OS {
export namespace GUI {
/**
* [[TagLayoutType]] interface using by AFX tags to defined
* its internal DOM hierarchy
*
* @export
* @interface TagLayoutType
*/
export interface TagLayoutType {
/**
* Element tag name
*
* @type {string}
* @memberof TagLayoutType
*/
el: string;
/**
* Children layout of the current element
*
* @type {TagLayoutType[]}
* @memberof TagLayoutType
*/
children?: TagLayoutType[];
/**
* Reference name of the element used by AFX Tag
*
* @type {string}
* @memberof TagLayoutType
*/
ref?: string;
/**
* CSS class of the element
*
* @type {string}
* @memberof TagLayoutType
*/
class?: string;
/**
* this is the `data-id` attribute of the element,
* can be query by the [[aid]] Tag API function.
* Not to be confused with the DOM `id` attribute
*
* @type {(string | number)}
* @memberof TagLayoutType
*/
id?: string | number;
tooltip?: string | FormatedString;
/**
* Tooltip text of the element
*
* @type {(string | FormattedString)}
* @memberof TagLayoutType
*/
tooltip?: string | FormattedString;
/**
* `data-width` of the element, not to be confused with
* the `width` attribute of the DOM element
*
* @type {number}
* @memberof TagLayoutType
*/
width?: number;
/**
** `data-height` of the element, not to be confused with
* the `height` attribute of the DOM element
*
* @type {number}
* @memberof TagLayoutType
*/
height?: number;
}
/**
* Data type for event issued by AFX tags
*
* @export
* @interface TagEventDataType
* @template T item template
*/
export interface TagEventDataType<T> {
item?: T,
[propName:string]: any;
/**
* Reference to the item involved in the event
*
* @type {T}
* @memberof TagEventDataType
*/
item?: T;
[propName: string]: any;
}
export interface TagEventType<T>{
/**
* Format of the event issued by AFX tags
*
* @export
* @interface TagEventType
* @template T data type
*/
export interface TagEventType<T> {
/**
* `data-id` of the tag that trigger the
* event
*
* @type {(number | string)}
* @memberof TagEventType
*/
id: number | string;
/**
* Data object of the event
*
* @type {T}
* @memberof TagEventType
*/
data: T;
}
/**
* Drag and Drop data type sent between mouse events
*
* @export
* @interface DnDEventDataType
* @template T
*/
export interface DnDEventDataType<T> {
/**
* Reference to the source DOM element
*
* @type {T}
* @memberof DnDEventDataType
*/
from: T;
/**
* Reference to the target DOM element
*
* @type {T}
* @memberof DnDEventDataType
*/
to: T;
}
/**
* Tag event callback type
*/
export type TagEventCallback<T> = (e: TagEventType<T>) => void;
/**
* Top most element z index value, start by 10
*/
export var zindex: number = 10;
/**
* Base abstract class for tag implementation, any AFX tag should be
* subclass of this class
*
* @export
* @abstract
* @class AFXTag
* @extends {HTMLElement}
*/
export abstract class AFXTag extends HTMLElement {
/**
* The announcer object of the tag
*
* @type {API.Announcer}
* @memberof AFXTag
*/
observable: API.Announcer;
/**
* Reference to some of the tag's children
* element. This reference object is built
* based on the `ref` property found in the
* tag layout [[TagLayoutType]]
*
* @protected
* @type {GenericObject<HTMLElement>}
* @memberof AFXTag
*/
protected refs: GenericObject<HTMLElement>;
/**
* boolean value indicated whether the tag
* is already mounted in the DOM tree
*
* @protected
* @type {boolean}
* @memberof AFXTag
*/
protected _mounted: boolean;
/**
*Creates an instance of AFXTag.
* @memberof AFXTag
*/
constructor() {
super();
@ -63,23 +306,51 @@ namespace OS {
this.refs = {};
}
/**
* This function verifies if a property name of the input object
* corresponds to a setter of the current tag. If this is the
* case, it sets the value of that property to the setter
*
* @param {GenericObject<any>} v input object
* @memberof AFXTag
*/
set(v: GenericObject<any>) {
for (let k in v) {
let descriptor = this.descriptor_of(k);
if (descriptor && descriptor.set)
{
if (descriptor && descriptor.set) {
this[k] = v[k];
}
}
}
/**
* Setter to set the tooltip text to the current tag.
* The text should be in the following format:
* ```text
* cr|cl|ct|cb: tooltip text
* ```
*
* @memberof AFXTag
*/
set tooltip(v: string) {
if (!v) {
return;
}
$(this).attr("tooltip", v);
}
private descriptor_of(k: string) {
/**
*
* This function looking for a property name of the tag
* in its prototype chain. The descriptor of the property
* will be returned if it exists
*
* @private
* @param {string} k the property name to be queried
* @returns {PropertyDescriptor} the property descriptor or undefined
* @memberof AFXTag
*/
private descriptor_of(k: string): PropertyDescriptor {
let desc: PropertyDescriptor;
let obj = this;
do {
@ -87,28 +358,55 @@ namespace OS {
} while (!desc && (obj = Object.getPrototypeOf(obj)));
return desc;
}
set aid(v: string| number) {
/**
* Setter to set the id of the tag in string or number
*
* @memberof AFXTag
*/
set aid(v: string | number) {
$(this).attr("data-id", v);
}
/**
* Getter to get the id of the current tag
*
* @type {(string | number)}
* @memberof AFXTag
*/
get aid(): string | number {
return $(this).attr("data-id");
}
/**
* Implementation from HTMLElement interface,
* this function mount the current tag hierarchy
*
* @returns {void}
* @memberof AFXTag
*/
sync(): void {
if(this._mounted)
{
if (this._mounted) {
return;
}
this._mounted = true;
this.mount();
super.sync();
}
/**
* Generate the DOM hierarchy of the current tag
*
* @param {API.Announcer} o observable object
* @memberof AFXTag
*/
afxml(o: API.Announcer): void {
if(o)
this.observable = o;
if(!this.aid)
this.aid = (Math.floor(Math.random() * 100000) + 1).toString();
const children = $(this).children();
if (o) this.observable = o;
if (!this.aid)
this.aid = (
Math.floor(Math.random() * 100000) + 1
).toString();
const children = $(this).children();
for (let obj of this.layout()) {
const dom = this.mkui(obj);
if (dom) {
@ -120,7 +418,7 @@ namespace OS {
$(v).detach().appendTo(this.refs.yield);
}
}
const attrs = {};
const attrs = {};
for (let i = 0; i < this.attributes.length; i++) {
const element = this.attributes[i];
let descriptor = this.descriptor_of(element.nodeName);
@ -136,26 +434,82 @@ namespace OS {
}
super.afxml(this.observable);
this.init();
for(let k in attrs)
{
for (let k in attrs) {
this[k] = attrs[k];
}
}
/**
* Update the current tag hierarchy
*
* @param {*} d any data object
* @memberof AFXTag
*/
update(d: any): void {
this.reload(d);
super.update(d);
}
/**
* Init the current tag, this function
* is called before the [[mount]] function
*
* @protected
* @abstract
* @memberof AFXTag
*/
protected abstract init(): void;
/**
* Mount only the current tag
*
* @protected
* @abstract
* @memberof AFXTag
*/
protected abstract mount(): void;
/**
* Layout definition of a tag
*
* @protected
* @abstract
* @returns {TagLayoutType[]} tag layout object
* @memberof AFXTag
*/
protected abstract layout(): TagLayoutType[];
/**
* Update only the current tag, this function is
* called by [[update]] before chaining the
* update process to its children
*
* @protected
* @abstract
* @param {*} [d]
* @memberof AFXTag
*/
protected abstract reload(d?: any): void;
// should be defined by subclasses
/**
* This function is used to re-render the current
* tag
*
* @protected
* @memberof AFXTag
*/
protected calibrate(): void {}
/**
* This function parses the input layout object
* and generates all the elements defined by
* the tag
*
* @private
* @param {TagLayoutType} tag tag layout object
* @returns {Element} the DOM element specified by the tag layout
* @memberof AFXTag
*/
private mkui(tag: TagLayoutType): Element {
if (!tag) {
return undefined;
@ -188,27 +542,63 @@ namespace OS {
return dom[0]; //.uify(@observable)
}
/**
* This function inserts or removes an attribute name
* to/from the target element based on the input `flag`.
*
* @protected
* @param {boolean} flag indicates whether the attribute name should be inserted o removed
* @param {string} v the attribute name
* @param {HTMLElement} [el] the target element
* @memberof AFXTag
*/
protected attsw(flag: boolean, v: string, el?: HTMLElement): void {
if (flag) this.atton(v, el);
else this.attoff(v, el);
}
/**
* Insert the attribute name to the target element
*
* @protected
* @param {string} v the attribute name
* @param {HTMLElement} [el] the target element
* @memberof AFXTag
*/
protected atton(v: string, el?: HTMLElement): void {
const element = el ? el : this;
$(element).attr(v, "");
}
/**
* Remove the attribute name from the target element
*
* @protected
* @param {string} v attribute name
* @param {HTMLElement} [el] the target element
* @memberof AFXTag
*/
protected attoff(v: string, el?: HTMLElement): void {
const element = el ? el : this;
element.removeAttribute(v);
}
/**
* Verify if the target element has an attribute name
*
* @protected
* @param {string} v attribute name
* @param {HTMLElement} [el] target element
* @returns {boolean}
* @memberof AFXTag
*/
protected hasattr(v: string, el?: HTMLElement): boolean {
const element = el ? el : this;
return element.hasAttribute(v);
}
}
HTMLElement.prototype.update = function (d):void {
HTMLElement.prototype.update = function (d): void {
$(this)
.children()
.each(function () {
@ -222,21 +612,39 @@ namespace OS {
return this.sync();
});
};
HTMLElement.prototype.afxml = function(o: API.Announcer): void {
HTMLElement.prototype.afxml = function (o: API.Announcer): void {
$(this)
.children()
.each(function () {
return this.afxml(o);
});
}
HTMLElement.prototype.uify = function(o: API.Announcer, toplevel?: boolean): void {
};
HTMLElement.prototype.uify = function (
o: API.Announcer,
toplevel?: boolean
): void {
this.afxml(o);
this.sync();
if(o && toplevel)
o.trigger("mounted", this.aid);
}
if (o && toplevel) o.trigger("mounted", this.aid);
};
/**
* All the AFX tags are defined in this namespace,
* these tags are are defined as custom DOM elements and will be
* stored in the `customElements` registry of the browser
*/
export namespace tag {
/**
* Define an AFX tag as a custom element and add it to the
* global `customElements` registry. If the tag is redefined, i.e.
* the tag already exist, its behavior will be updated with the
* new definition
*
* @export
* @template T all classes that extends [[AFXTag]]
* @param {string} name name of the tag
* @param {{ new (): T }} cls the class that defines the tag
* @returns {void}
*/
export function define<T extends AFXTag>(
name: string,
cls: { new (): T }
@ -245,18 +653,15 @@ namespace OS {
customElements.define(name, cls);
} catch (error) {
const proto = customElements.get(name);
if(cls)
{
if (cls) {
const props = Object.getOwnPropertyNames(cls.prototype);
// redefine the class
for(let prop of props)
{
for (let prop of props) {
proto.prototype[prop] = cls.prototype[prop];
}
return;
}
throw error;
}
}
}

View File

@ -58,11 +58,11 @@ namespace OS {
*
*
* @protected
* @param {(string | FormatedString)} m
* @param {(string | FormattedString)} m
* @returns {void}
* @memberof BaseExtension
*/
protected notify(m: string | FormatedString): void {
protected notify(m: string | FormattedString): void {
return this.app.notify(m);
}
@ -70,12 +70,12 @@ namespace OS {
*
*
* @protected
* @param {(string | FormatedString)} m
* @param {(string | FormattedString)} m
* @param {Error} e
* @returns {void}
* @memberof BaseExtension
*/
protected error(m: string | FormatedString, e: Error): void {
protected error(m: string | FormattedString, e: Error): void {
return this.app.error(m, e);
}

View File

@ -978,7 +978,7 @@ namespace OS {
* @class CMDMenu
*/
class CMDMenu {
text: string | FormatedString;
text: string | FormattedString;
private shortcut: string;
nodes: GenericObject<any>[];
parent: CMDMenu;
@ -990,11 +990,11 @@ namespace OS {
/**
*Creates an instance of CMDMenu.
* @param {(string | FormatedString)} text
* @param {(string | FormattedString)} text
* @param {string} [shortcut]
* @memberof CMDMenu
*/
constructor(text: string | FormatedString, shortcut?: string) {
constructor(text: string | FormattedString, shortcut?: string) {
this.text = text;
this.shortcut = shortcut;
this.nodes = [];