forked from mystiq/hydrogen-web
copy Daniel's conversion of html.js to TypeScript from microui
This commit is contained in:
parent
cce8207870
commit
69672dd99c
10 changed files with 33 additions and 27 deletions
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {tag, text, classNames, setAttribute} from "./general/html.js";
|
import {tag, text, classNames, setAttribute} from "./general/html";
|
||||||
/**
|
/**
|
||||||
* @param {Object} vm view model with {avatarUrl, avatarColorNumber, avatarTitle, avatarLetter}
|
* @param {Object} vm view model with {avatarUrl, avatarColorNumber, avatarTitle, avatarLetter}
|
||||||
* @param {Number} size
|
* @param {Number} size
|
||||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {el} from "./html.js";
|
import {el} from "./html";
|
||||||
import {mountView} from "./utils";
|
import {mountView} from "./utils";
|
||||||
import {ListView} from "./ListView";
|
import {ListView} from "./ListView";
|
||||||
import {insertAt} from "./utils";
|
import {insertAt} from "./utils";
|
||||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {el} from "./html.js";
|
import {el} from "./html";
|
||||||
import {mountView, insertAt} from "./utils";
|
import {mountView, insertAt} from "./utils";
|
||||||
import {BaseObservableList as ObservableList} from "../../../../observable/list/BaseObservableList.js";
|
import {BaseObservableList as ObservableList} from "../../../../observable/list/BaseObservableList.js";
|
||||||
import {UIView, IMountArgs} from "./types";
|
import {UIView, IMountArgs} from "./types";
|
||||||
|
@ -79,7 +79,7 @@ export class ListView<T, V extends UIView> implements UIView {
|
||||||
if (this._className) {
|
if (this._className) {
|
||||||
attr.className = this._className;
|
attr.className = this._className;
|
||||||
}
|
}
|
||||||
this._root = el(this._tagName, attr);
|
this._root = el(this._tagName, attr) as HTMLElement;
|
||||||
this.loadList();
|
this.loadList();
|
||||||
if (this._onItemClick) {
|
if (this._onItemClick) {
|
||||||
this._root!.addEventListener("click", this);
|
this._root!.addEventListener("click", this);
|
||||||
|
|
|
@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {tag} from "../general/html.js";
|
import {tag} from "../general/html";
|
||||||
|
|
||||||
export class StaticView {
|
export class StaticView {
|
||||||
constructor(value, render = undefined) {
|
constructor(value, render = undefined) {
|
||||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { setAttribute, text, isChildren, classNames, TAG_NAMES, HTML_NS } from "./html.js";
|
import { setAttribute, text, isChildren, classNames, TAG_NAMES, HTML_NS } from "./html";
|
||||||
import {mountView} from "./utils";
|
import {mountView} from "./utils";
|
||||||
import {BaseUpdateView} from "./BaseUpdateView.js";
|
import {BaseUpdateView} from "./BaseUpdateView.js";
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2020 Bruno Windels <bruno@windels.cloud>
|
Copyright 2020 Bruno Windels <bruno@windels.cloud>
|
||||||
|
Copyright 2021 Daniel Fedorin <danila.fedorin@gmail.com>
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -16,12 +17,16 @@ limitations under the License.
|
||||||
|
|
||||||
// DOM helper functions
|
// DOM helper functions
|
||||||
|
|
||||||
export function isChildren(children) {
|
export type ClassNames<T> = { [className: string]: boolean | ((value?: T) => boolean) }
|
||||||
|
export type BasicAttributes<T> = { [attribute: string]: ClassNames<T> | boolean | string }
|
||||||
|
export type Child = string | Text | Element
|
||||||
|
|
||||||
|
export function isChildren(children: object | Child | Child[]): children is Child | Child[] {
|
||||||
// children should be an not-object (that's the attributes), or a domnode, or an array
|
// children should be an not-object (that's the attributes), or a domnode, or an array
|
||||||
return typeof children !== "object" || !!children.nodeType || Array.isArray(children);
|
return typeof children !== "object" || "nodeType" in children || Array.isArray(children);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function classNames(obj, value) {
|
export function classNames<T>(obj: ClassNames<T>, value?: T): string {
|
||||||
return Object.entries(obj).reduce((cn, [name, enabled]) => {
|
return Object.entries(obj).reduce((cn, [name, enabled]) => {
|
||||||
if (typeof enabled === "function") {
|
if (typeof enabled === "function") {
|
||||||
enabled = enabled(value);
|
enabled = enabled(value);
|
||||||
|
@ -34,7 +39,7 @@ export function classNames(obj, value) {
|
||||||
}, "");
|
}, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setAttribute(el, name, value) {
|
export function setAttribute(el: Element, name: string, value: string | boolean): void {
|
||||||
if (name === "className") {
|
if (name === "className") {
|
||||||
name = "class";
|
name = "class";
|
||||||
}
|
}
|
||||||
|
@ -48,22 +53,24 @@ export function setAttribute(el, name, value) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function el(elementName, attributes, children) {
|
export function el(elementName: string, attributes?: BasicAttributes<never> | Child | Child[], children?: Child | Child[]): Element {
|
||||||
return elNS(HTML_NS, elementName, attributes, children);
|
return elNS(HTML_NS, elementName, attributes, children);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function elNS(ns, elementName, attributes, children) {
|
export function elNS(ns: string, elementName: string, attributes?: BasicAttributes<never> | Child | Child[], children?: Child | Child[]): Element {
|
||||||
if (attributes && isChildren(attributes)) {
|
if (attributes && isChildren(attributes)) {
|
||||||
children = attributes;
|
children = attributes;
|
||||||
attributes = null;
|
attributes = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const e = document.createElementNS(ns, elementName);
|
const e = document.createElementNS(ns, elementName);
|
||||||
|
|
||||||
if (attributes) {
|
if (attributes) {
|
||||||
for (let [name, value] of Object.entries(attributes)) {
|
for (let [name, value] of Object.entries(attributes)) {
|
||||||
if (name === "className" && typeof value === "object" && value !== null) {
|
if (typeof value === "object") {
|
||||||
value = classNames(value);
|
// Only className should ever be an object; be careful
|
||||||
|
// here anyway and ignore object-valued non-className attributes.
|
||||||
|
value = (value !== null && name === "className") ? classNames(value) : false;
|
||||||
}
|
}
|
||||||
setAttribute(e, name, value);
|
setAttribute(e, name, value);
|
||||||
}
|
}
|
||||||
|
@ -74,7 +81,7 @@ export function elNS(ns, elementName, attributes, children) {
|
||||||
children = [children];
|
children = [children];
|
||||||
}
|
}
|
||||||
for (let c of children) {
|
for (let c of children) {
|
||||||
if (!c.nodeType) {
|
if (typeof c === "string") {
|
||||||
c = text(c);
|
c = text(c);
|
||||||
}
|
}
|
||||||
e.appendChild(c);
|
e.appendChild(c);
|
||||||
|
@ -83,12 +90,12 @@ export function elNS(ns, elementName, attributes, children) {
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function text(str) {
|
export function text(str: string): Text {
|
||||||
return document.createTextNode(str);
|
return document.createTextNode(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const HTML_NS = "http://www.w3.org/1999/xhtml";
|
export const HTML_NS: string = "http://www.w3.org/1999/xhtml";
|
||||||
export const SVG_NS = "http://www.w3.org/2000/svg";
|
export const SVG_NS: string = "http://www.w3.org/2000/svg";
|
||||||
|
|
||||||
export const TAG_NAMES = {
|
export const TAG_NAMES = {
|
||||||
[HTML_NS]: [
|
[HTML_NS]: [
|
||||||
|
@ -97,10 +104,9 @@ export const TAG_NAMES = {
|
||||||
"table", "thead", "tbody", "tr", "th", "td", "hr",
|
"table", "thead", "tbody", "tr", "th", "td", "hr",
|
||||||
"pre", "code", "button", "time", "input", "textarea", "label", "form", "progress", "output", "video"],
|
"pre", "code", "button", "time", "input", "textarea", "label", "form", "progress", "output", "video"],
|
||||||
[SVG_NS]: ["svg", "circle"]
|
[SVG_NS]: ["svg", "circle"]
|
||||||
};
|
} as const;
|
||||||
|
|
||||||
export const tag = {};
|
|
||||||
|
|
||||||
|
export const tag: { [tagName in typeof TAG_NAMES[string][number]]: (attributes?: BasicAttributes<never> | Child | Child[], children?: Child | Child[]) => Element } = {} as any;
|
||||||
|
|
||||||
for (const [ns, tags] of Object.entries(TAG_NAMES)) {
|
for (const [ns, tags] of Object.entries(TAG_NAMES)) {
|
||||||
for (const tagName of tags) {
|
for (const tagName of tags) {
|
|
@ -15,7 +15,7 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {UIView, IMountArgs} from "./types";
|
import {UIView, IMountArgs} from "./types";
|
||||||
import {tag} from "./html.js";
|
import {tag} from "./html";
|
||||||
|
|
||||||
export function mountView(view: UIView, mountArgs: IMountArgs): HTMLElement {
|
export function mountView(view: UIView, mountArgs: IMountArgs): HTMLElement {
|
||||||
let node;
|
let node;
|
||||||
|
@ -38,7 +38,7 @@ export function errorToDOM(error: Error): HTMLElement {
|
||||||
tag.h3(error.message),
|
tag.h3(error.message),
|
||||||
tag.p(`This occurred while running ${callee}.`),
|
tag.p(`This occurred while running ${callee}.`),
|
||||||
tag.pre(error.stack),
|
tag.pre(error.stack),
|
||||||
]);
|
]) as HTMLElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function insertAt(parentNode: HTMLElement, idx: number, childNode: HTMLElement): void {
|
export function insertAt(parentNode: HTMLElement, idx: number, childNode: HTMLElement): void {
|
||||||
|
|
|
@ -15,7 +15,7 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {TemplateView} from "../../general/TemplateView.js";
|
import {TemplateView} from "../../general/TemplateView.js";
|
||||||
import {classNames, tag} from "../../general/html.js";
|
import {classNames, tag} from "../../general/html";
|
||||||
import {AvatarView} from "../../AvatarView.js";
|
import {AvatarView} from "../../AvatarView.js";
|
||||||
|
|
||||||
export class RoomDetailsView extends TemplateView {
|
export class RoomDetailsView extends TemplateView {
|
||||||
|
|
|
@ -16,7 +16,7 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {renderStaticAvatar} from "../../../avatar.js";
|
import {renderStaticAvatar} from "../../../avatar.js";
|
||||||
import {tag} from "../../../general/html.js";
|
import {tag} from "../../../general/html";
|
||||||
import {mountView} from "../../../general/utils";
|
import {mountView} from "../../../general/utils";
|
||||||
import {TemplateView} from "../../../general/TemplateView.js";
|
import {TemplateView} from "../../../general/TemplateView.js";
|
||||||
import {Popup} from "../../../general/Popup.js";
|
import {Popup} from "../../../general/Popup.js";
|
||||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {tag, text} from "../../../general/html.js";
|
import {tag, text} from "../../../general/html";
|
||||||
import {BaseMessageView} from "./BaseMessageView.js";
|
import {BaseMessageView} from "./BaseMessageView.js";
|
||||||
|
|
||||||
export class TextMessageView extends BaseMessageView {
|
export class TextMessageView extends BaseMessageView {
|
||||||
|
|
Loading…
Reference in a new issue