jpf 5.0.62 → 5.0.64
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/controls/codeMirror/Editor/Editor.d.ts +4 -5
- package/dist/controls/codeMirror/Editor/Editor.js +8 -9
- package/dist/controls/codeMirror/Editor/Editor.js.map +1 -1
- package/dist/controls/custom/FileSelector/FileSelector.d.ts +3 -4
- package/dist/controls/custom/FileSelector/FileSelector.js +5 -6
- package/dist/controls/custom/FileSelector/FileSelector.js.map +1 -1
- package/dist/controls/custom/LabeledControl/LabeledControl.d.ts +5 -6
- package/dist/controls/custom/LabeledControl/LabeledControl.js +3 -4
- package/dist/controls/custom/LabeledControl/LabeledControl.js.map +1 -1
- package/dist/controls/custom/ListItem/ListItem.d.ts +8 -9
- package/dist/controls/custom/ListItem/ListItem.js +8 -9
- package/dist/controls/custom/ListItem/ListItem.js.map +1 -1
- package/dist/controls/html/Button/Button.d.ts +6 -7
- package/dist/controls/html/Button/Button.js +8 -9
- package/dist/controls/html/Button/Button.js.map +1 -1
- package/dist/controls/html/Div/Div.d.ts +4 -5
- package/dist/controls/html/Div/Div.js +2 -3
- package/dist/controls/html/Div/Div.js.map +1 -1
- package/dist/controls/html/Image/Image.d.ts +4 -5
- package/dist/controls/html/Image/Image.js +2 -3
- package/dist/controls/html/Image/Image.js.map +1 -1
- package/dist/controls/html/Input/Input.d.ts +4 -5
- package/dist/controls/html/Input/Input.js +23 -23
- package/dist/controls/html/Input/Input.js.map +1 -1
- package/dist/controls/html/Select/Select.d.ts +4 -5
- package/dist/controls/html/Select/Select.js +15 -16
- package/dist/controls/html/Select/Select.js.map +1 -1
- package/dist/controls/html/Span/Span.d.ts +3 -4
- package/dist/controls/html/Span/Span.js +2 -3
- package/dist/controls/html/Span/Span.js.map +1 -1
- package/dist/controls/jsonViewerAwesome/jsonFormatter/JsonFormatter.d.ts +4 -5
- package/dist/controls/jsonViewerAwesome/jsonFormatter/JsonFormatter.js +7 -8
- package/dist/controls/jsonViewerAwesome/jsonFormatter/JsonFormatter.js.map +1 -1
- package/dist/controls/kendo/Chart/Chart.d.ts +3 -4
- package/dist/controls/kendo/Chart/Chart.js +9 -10
- package/dist/controls/kendo/Chart/Chart.js.map +1 -1
- package/dist/controls/kendo/Editor/Editor.d.ts +3 -4
- package/dist/controls/kendo/Editor/Editor.js +13 -14
- package/dist/controls/kendo/Editor/Editor.js.map +1 -1
- package/dist/controls/kendo/Grid/Grid.d.ts +4 -5
- package/dist/controls/kendo/Grid/Grid.js +12 -13
- package/dist/controls/kendo/Grid/Grid.js.map +1 -1
- package/dist/controls/kendo/Menu/Menu.d.ts +3 -4
- package/dist/controls/kendo/Menu/Menu.js +9 -10
- package/dist/controls/kendo/Menu/Menu.js.map +1 -1
- package/dist/controls/kendo/Treeview/Treeview.d.ts +3 -4
- package/dist/controls/kendo/Treeview/Treeview.js +9 -10
- package/dist/controls/kendo/Treeview/Treeview.js.map +1 -1
- package/dist/controls/leaflet/LabelControl/LabelControl.d.ts +2 -3
- package/dist/controls/leaflet/LabelControl/LabelControl.js +1 -2
- package/dist/controls/leaflet/LabelControl/LabelControl.js.map +1 -1
- package/dist/controls/leaflet/Map/Map.d.ts +4 -5
- package/dist/controls/leaflet/Map/Map.js +9 -10
- package/dist/controls/leaflet/Map/Map.js.map +1 -1
- package/dist/controls/svg/Circle/Circle.d.ts +3 -4
- package/dist/controls/svg/Circle/Circle.js +1 -2
- package/dist/controls/svg/Circle/Circle.js.map +1 -1
- package/dist/controls/svg/Ellipse/Ellipse.d.ts +3 -4
- package/dist/controls/svg/Ellipse/Ellipse.js +1 -2
- package/dist/controls/svg/Ellipse/Ellipse.js.map +1 -1
- package/dist/controls/svg/ForeignObject/ForeignObject.d.ts +3 -4
- package/dist/controls/svg/ForeignObject/ForeignObject.js +1 -2
- package/dist/controls/svg/ForeignObject/ForeignObject.js.map +1 -1
- package/dist/controls/svg/Group/Group.d.ts +3 -4
- package/dist/controls/svg/Group/Group.js +1 -2
- package/dist/controls/svg/Group/Group.js.map +1 -1
- package/dist/controls/svg/Line/Line.d.ts +3 -4
- package/dist/controls/svg/Line/Line.js +1 -2
- package/dist/controls/svg/Line/Line.js.map +1 -1
- package/dist/controls/svg/Pattern/Pattern.d.ts +3 -4
- package/dist/controls/svg/Pattern/Pattern.js +1 -2
- package/dist/controls/svg/Pattern/Pattern.js.map +1 -1
- package/dist/controls/svg/Polygon/Polygon.d.ts +3 -4
- package/dist/controls/svg/Polygon/Polygon.js +3 -4
- package/dist/controls/svg/Polygon/Polygon.js.map +1 -1
- package/dist/controls/svg/Polyline/Polyline.d.ts +3 -4
- package/dist/controls/svg/Polyline/Polyline.js +1 -2
- package/dist/controls/svg/Polyline/Polyline.js.map +1 -1
- package/dist/controls/svg/Rectangle/Rectangle.d.ts +3 -4
- package/dist/controls/svg/Rectangle/Rectangle.js +1 -2
- package/dist/controls/svg/Rectangle/Rectangle.js.map +1 -1
- package/dist/controls/svg/Svg/Svg.d.ts +3 -4
- package/dist/controls/svg/Svg/Svg.js +1 -2
- package/dist/controls/svg/Svg/Svg.js.map +1 -1
- package/dist/controls/svg/Text/Text.d.ts +3 -4
- package/dist/controls/svg/Text/Text.js +1 -2
- package/dist/controls/svg/Text/Text.js.map +1 -1
- package/dist/controls/svg/Title/Title.d.ts +3 -4
- package/dist/controls/svg/Title/Title.js +1 -2
- package/dist/controls/svg/Title/Title.js.map +1 -1
- package/dist/controls/svg/svg.d.ts +1 -1
- package/dist/controls/svg/svg.js +5 -5
- package/dist/controls/svg/svg.js.map +1 -1
- package/dist/framework/attributes.d.ts +1 -1
- package/dist/framework/css.d.ts +1 -4
- package/dist/framework/element.d.ts +48 -15
- package/dist/framework/element.js +279 -29
- package/dist/framework/element.js.map +1 -1
- package/dist/framework/event.js.map +1 -1
- package/dist/framework/observable.d.ts +41 -0
- package/dist/framework/observable.js +46 -0
- package/dist/framework/observable.js.map +1 -0
- package/dist/framework/observablelmplementations.d.ts +1 -24
- package/dist/framework/observablelmplementations.js +0 -110
- package/dist/framework/observablelmplementations.js.map +1 -1
- package/dist/framework/properties.d.ts +1 -40
- package/dist/framework/properties.js +0 -265
- package/dist/framework/properties.js.map +1 -1
- package/dist/framework/style.d.ts +1 -328
- package/dist/index.d.ts +6 -10
- package/dist/index.js +7 -11
- package/dist/index.js.map +1 -1
- package/dist/utilities/object/object.d.ts +5 -0
- package/dist/utilities/object/object.js +47 -0
- package/dist/utilities/object/object.js.map +1 -0
- package/dist/utilities/value/value.d.ts +1 -0
- package/dist/utilities/value/value.js +7 -0
- package/dist/utilities/value/value.js.map +1 -0
- package/package.json +1 -1
- package/src/controls/codeMirror/Editor/Editor.ts +9 -11
- package/src/controls/custom/FileSelector/FileSelector.ts +5 -6
- package/src/controls/custom/LabeledControl/LabeledControl.ts +5 -6
- package/src/controls/custom/ListItem/ListItem.ts +13 -15
- package/src/controls/html/Button/Button.ts +13 -15
- package/src/controls/html/Div/Div.ts +4 -5
- package/src/controls/html/Image/Image.ts +4 -5
- package/src/controls/html/Input/Input.ts +21 -22
- package/src/controls/html/Select/Select.ts +16 -18
- package/src/controls/html/Span/Span.ts +3 -4
- package/src/controls/jsonViewerAwesome/jsonFormatter/JsonFormatter.ts +10 -12
- package/src/controls/kendo/Chart/Chart.ts +17 -19
- package/src/controls/kendo/Editor/Editor.ts +14 -16
- package/src/controls/kendo/Grid/Grid.ts +13 -15
- package/src/controls/kendo/Menu/Menu.ts +11 -13
- package/src/controls/kendo/Treeview/Treeview.ts +9 -11
- package/src/controls/leaflet/LabelControl/LabelControl.ts +4 -5
- package/src/controls/leaflet/Map/Map.ts +10 -12
- package/src/controls/svg/Circle/Circle.ts +3 -4
- package/src/controls/svg/Ellipse/Ellipse.ts +3 -4
- package/src/controls/svg/ForeignObject/ForeignObject.ts +3 -4
- package/src/controls/svg/Group/Group.ts +3 -4
- package/src/controls/svg/Line/Line.ts +3 -4
- package/src/controls/svg/Pattern/Pattern.ts +3 -4
- package/src/controls/svg/Polygon/Polygon.ts +4 -6
- package/src/controls/svg/Polyline/Polyline.ts +3 -4
- package/src/controls/svg/Rectangle/Rectangle.ts +3 -4
- package/src/controls/svg/Svg/Svg.ts +3 -4
- package/src/controls/svg/Text/Text.ts +3 -4
- package/src/controls/svg/Title/Title.ts +3 -4
- package/src/controls/svg/svg.ts +5 -6
- package/src/framework/attributes.ts +1 -47
- package/src/framework/css.ts +3 -5
- package/src/framework/element.ts +380 -44
- package/src/framework/event.ts +0 -2
- package/src/framework/observable.ts +100 -0
- package/src/framework/style.ts +1556 -1556
- package/src/index.ts +16 -11
- package/src/utilities/object/object.ts +56 -0
- package/src/utilities/value/value.ts +3 -0
- package/src/framework/observableInterfaces.ts +0 -39
- package/src/framework/observablelmplementations.ts +0 -135
- package/src/framework/properties.ts +0 -344
|
@@ -1,51 +1,5 @@
|
|
|
1
1
|
import { PreserveAspectRatio } from "./css";
|
|
2
|
-
import { ISubscribable } from "./
|
|
3
|
-
|
|
4
|
-
//export interface IAttributes {
|
|
5
|
-
// alt?: string,
|
|
6
|
-
// disabled?: string,
|
|
7
|
-
// href?: string,
|
|
8
|
-
// target?: string,
|
|
9
|
-
// id?: string,
|
|
10
|
-
// src?: string,
|
|
11
|
-
// title?: string,
|
|
12
|
-
// class?: string,
|
|
13
|
-
// tabindex?: number,
|
|
14
|
-
// draggable?: string,
|
|
15
|
-
// placeholder?: string,
|
|
16
|
-
// for?: string,
|
|
17
|
-
// type?: string,
|
|
18
|
-
// value?: string,
|
|
19
|
-
// view?: string,
|
|
20
|
-
// checked?: string;
|
|
21
|
-
// enctype?: string;
|
|
22
|
-
// name?: string;
|
|
23
|
-
// multiple?: boolean;
|
|
24
|
-
// ["aria-label"]?: string;
|
|
25
|
-
// cx?: number | string;
|
|
26
|
-
// cy?: number | string;
|
|
27
|
-
// r?: number | string;
|
|
28
|
-
// rx?: number | string;
|
|
29
|
-
// ry?: number | string;
|
|
30
|
-
// x?: number | string;
|
|
31
|
-
// x1?: number | string;
|
|
32
|
-
// x2?: number | string;
|
|
33
|
-
// y?: number | string;
|
|
34
|
-
// y1?: number | string;
|
|
35
|
-
// y2?: number | string;
|
|
36
|
-
// width?: number | string;
|
|
37
|
-
// height?: number | string;
|
|
38
|
-
// patternUnits?: string;
|
|
39
|
-
// patternTransform?: string;
|
|
40
|
-
// points?: string;
|
|
41
|
-
// viewBox?: string;
|
|
42
|
-
// dx?: number | string;
|
|
43
|
-
// dy?: number | string;
|
|
44
|
-
// rotate?: string;
|
|
45
|
-
// preserveAspectRatio?: PreserveAspectRatio;
|
|
46
|
-
// xmlns?: string;
|
|
47
|
-
// info?: string;
|
|
48
|
-
//}
|
|
2
|
+
import { ISubscribable } from "./observable";
|
|
49
3
|
|
|
50
4
|
export interface IAttributes {
|
|
51
5
|
alt?: string | ISubscribable<string>,
|
package/src/framework/css.ts
CHANGED
|
@@ -3,7 +3,7 @@ export type PatternUnits = "userSpaceOnUse" | "objectboudingBox";
|
|
|
3
3
|
export type DropEffect = "none" | "copy" | "link" | "move";
|
|
4
4
|
export type EffectAllowed = "none" | "copy" | "copyLink" | "copyMove" | "link" | "linkMove" | "move" | "all" | "uninitialized";
|
|
5
5
|
|
|
6
|
-
type
|
|
6
|
+
export type CssProperty = "alignContent" | "alignItems" | "alignSelf" | "alignmentAdjust" | "alignmentBaseline" | "animation" | "animationDelay" | "animationDirection" | "animationDuration" |
|
|
7
7
|
"animationFillMode" | "animationIterationCount" | "animationName" | "animationPlayState" | "animationTimingFunction" | "appearance" | "backfaceVisibility" | "background" |
|
|
8
8
|
"backgroundAttachment" | "backgroundBlendMode" | "backgroundClip" | "backgroundColor" | "backgroundComposite" | "backgroundImage" | "backgroundOrigin" | "backgroundPosition" |
|
|
9
9
|
"backgroundRepeat" | "backgroundSize" | "baselineShift" | "behavior" | "border" | "borderBottom" | "borderBottomColor" | "borderBottomLeftRadius" | "borderBottomRightRadius" |
|
|
@@ -17,9 +17,8 @@ type CssPropertyA = "alignContent" | "alignItems" | "alignSelf" | "alignmentAdju
|
|
|
17
17
|
"float" | "flowFrom" | "font" | "fontFamily" | "fontKerning" | "fontSize" | "fontSizeAdjust" | "fontStretch" | "fontStyle" | "fontSynthesis" | "fontVariant" | "fontVariantAlternates" |
|
|
18
18
|
"fontWeight" | "gridArea" | "gridAutoColumns" | "gridAutoFlow" | "gridAutoRows" | "gridColumn" | "gridColumnGap" | "gridColumnEnd" | "gridColumnStart" | "gridGap" | "gridRow" |
|
|
19
19
|
"gridRowEnd" | "gridRowGap" | "gridRowStart" | "gridRowPosition" | "gridRowSpan" | "gridTemplate" | "gridTemplateAreas" | "gridTemplateColumns" | "gridTemplateRows" | "height" |
|
|
20
|
-
"hyphenateLimitChars" | "hyphenateLimitLines" | "hyphenateLimitZone" | "hyphens" | "imeMode" | "justifyContent" | "justifyItems" | "justifySelf"
|
|
21
|
-
|
|
22
|
-
type CssPropertyL = "layoutGrid" | "layoutGridChar" | "layoutGridLine" | "layoutGridMode" | "layoutGridType" | "left" | "letterSpacing" | "lineBreak" | "lineClamp" | "lineHeight" |
|
|
20
|
+
"hyphenateLimitChars" | "hyphenateLimitLines" | "hyphenateLimitZone" | "hyphens" | "imeMode" | "justifyContent" | "justifyItems" | "justifySelf" |
|
|
21
|
+
"layoutGrid" | "layoutGridChar" | "layoutGridLine" | "layoutGridMode" | "layoutGridType" | "left" | "letterSpacing" | "lineBreak" | "lineClamp" | "lineHeight" |
|
|
23
22
|
"listStyle" | "listStyleImage" | "listStylePosition" | "listStyleType" | "margin" | "marginBottom" | "marginLeft" | "marginRight" | "marginTop" | "marqueeDirection" | "marqueeStyle" |
|
|
24
23
|
"mask" | "maskBorder" | "maskBorderRepeat" | "maskBorderSlice" | "maskBorderSource" | "maskBorderWidth" | "maskClip" | "maskOrigin" | "maxFontSize" | "maxHeight" | "maxWidth" |
|
|
25
24
|
"minHeight" | "minWidth" | "mixBlendMode" | "objectFit" | "objectPosition" | "opacity" | "order" | "orphans" | "outline" | "outlineColor" | "outlineStyle" | "outlineOffset" |
|
|
@@ -36,7 +35,6 @@ type CssPropertyL = "layoutGrid" | "layoutGridChar" | "layoutGridLine" | "layout
|
|
|
36
35
|
"userSelect" | "verticalAlign" | "visibility" | "voiceBalance" | "voiceDuration" | "voiceFamily" | "voicePitch" | "voiceRange" | "voiceRate" | "voiceStress" | "voiceVolume" |
|
|
37
36
|
"whiteSpace" | "whiteSpaceTreatment" | "widows" | "width" | "willChange" | "wordBreak" | "wordSpacing" | "wordWrap" | "wrapFlow" | "wrapMargin" | "wrapOption" | "writingMode" | "zIndex" | "zoom";
|
|
38
37
|
|
|
39
|
-
export type CssProperty = CssPropertyA | CssPropertyL;
|
|
40
38
|
/*
|
|
41
39
|
* Value of a CSS Property. Could be a single value or a list of fallbacks
|
|
42
40
|
* NOTE: array is for fallbacks
|
package/src/framework/element.ts
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import "tocca";
|
|
2
|
-
import { IDisposer, ISubscribable } from "./
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import { IDisposer, ISubscribable, observable } from "./observable";
|
|
3
|
+
import { IEventListener } from "./event";
|
|
4
|
+
import { IAttributes } from "./attributes";
|
|
5
|
+
import { IStyle } from "./style";
|
|
6
|
+
import { isNullOrUndefined } from "../utilities/value/value";
|
|
7
|
+
|
|
8
|
+
const svgNamespace = "http://www.w3.org/2000/svg";
|
|
9
|
+
|
|
10
|
+
// #region Element tagNames for HTML and SVG Elements
|
|
5
11
|
|
|
6
12
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
7
13
|
const htmlTags = {
|
|
@@ -33,26 +39,47 @@ const svgTags = {
|
|
|
33
39
|
}
|
|
34
40
|
|
|
35
41
|
type TagName = keyof typeof htmlTags | keyof typeof svgTags;
|
|
42
|
+
// #endregion
|
|
43
|
+
|
|
44
|
+
// #region Element Interfaces
|
|
45
|
+
|
|
46
|
+
//Element properties except the tagName
|
|
47
|
+
export interface IElementProperties {
|
|
48
|
+
attributes?: IAttributes;
|
|
49
|
+
classNames?: Array<string> | ISubscribable<Array<string>>;
|
|
50
|
+
style?: IStyle;
|
|
51
|
+
visible?: boolean | ISubscribable<boolean>;
|
|
52
|
+
disabled?: boolean | ISubscribable<boolean>;
|
|
53
|
+
innerHtml?: string | ISubscribable<string>;
|
|
54
|
+
textContent?: string | ISubscribable<string>;
|
|
55
|
+
addViewModelToDataObject?: boolean;
|
|
56
|
+
userSelectable?: boolean;
|
|
57
|
+
eventListeners?: Array<IEventListener>;
|
|
58
|
+
elementType?: string;
|
|
59
|
+
focused?: boolean | ISubscribable<boolean>;
|
|
60
|
+
}
|
|
36
61
|
|
|
37
|
-
|
|
62
|
+
//Options to create an Element
|
|
63
|
+
export interface IElementOptions<TElementProperties> {
|
|
64
|
+
tagName: TagName;
|
|
65
|
+
properties?: TElementProperties;
|
|
66
|
+
}
|
|
38
67
|
|
|
39
|
-
|
|
68
|
+
//public interface of an Element
|
|
40
69
|
export interface IElement {
|
|
41
70
|
render(): HTMLElement;
|
|
42
71
|
unmount(): void;
|
|
43
72
|
}
|
|
44
73
|
|
|
45
|
-
|
|
46
|
-
tagName: TagName;
|
|
47
|
-
properties?: TProperties;
|
|
48
|
-
}
|
|
74
|
+
// #endregion
|
|
49
75
|
|
|
50
|
-
|
|
51
|
-
|
|
76
|
+
// #region Element Class definition
|
|
77
|
+
export class Element<TElementProperties = IElementProperties> implements IElement {
|
|
78
|
+
constructor(options: IElementOptions<TElementProperties>, children?: Array<IElement> | ISubscribable<Array<IElement>>) {
|
|
52
79
|
this.tagName = options.tagName;
|
|
53
80
|
this.properties = options.properties;
|
|
54
81
|
this.optionsChildren = children;
|
|
55
|
-
this.children = unwrap(children);
|
|
82
|
+
this.children = observable.unwrap(children);
|
|
56
83
|
}
|
|
57
84
|
|
|
58
85
|
// #region Private members
|
|
@@ -62,33 +89,33 @@ export class Element<TProperties = IProperties> implements IElement {
|
|
|
62
89
|
|
|
63
90
|
|
|
64
91
|
private buildChildren() {
|
|
65
|
-
if (this.
|
|
92
|
+
if (this.htmlElement && this.children && this.children.length > 0) {
|
|
66
93
|
//Create a documentFragment to reduce browser repaints
|
|
67
94
|
const documentFragment = document.createDocumentFragment();
|
|
68
95
|
for (const child of this.children) {
|
|
69
|
-
this.
|
|
96
|
+
this.htmlElement.appendChild(child.render());
|
|
70
97
|
}
|
|
71
98
|
|
|
72
99
|
//Add the documentFragment to the dom
|
|
73
|
-
this.
|
|
100
|
+
this.htmlElement.appendChild(documentFragment);
|
|
74
101
|
}
|
|
75
102
|
}
|
|
76
103
|
// #endregion
|
|
77
104
|
|
|
78
105
|
// #region Protected members
|
|
79
|
-
protected
|
|
80
|
-
protected readonly properties:
|
|
106
|
+
protected htmlElement: HTMLElement;
|
|
107
|
+
protected readonly properties: TElementProperties;
|
|
81
108
|
protected readonly disposers = new Array<IDisposer>();
|
|
82
109
|
|
|
83
110
|
protected build(): void {
|
|
84
|
-
applyBindings(this.properties
|
|
111
|
+
applyBindings(this.properties, this.htmlElement, this.disposers);
|
|
85
112
|
|
|
86
113
|
if (this.children) {
|
|
87
114
|
this.buildChildren();
|
|
88
115
|
}
|
|
89
116
|
|
|
90
117
|
//Find out if the options.Children are observable.
|
|
91
|
-
if (isSubscribable(this.optionsChildren)) {
|
|
118
|
+
if (observable.isSubscribable(this.optionsChildren)) {
|
|
92
119
|
this.disposers.push(
|
|
93
120
|
this.optionsChildren.subscribe((children) => {
|
|
94
121
|
this.setChildren(...children);
|
|
@@ -98,26 +125,26 @@ export class Element<TProperties = IProperties> implements IElement {
|
|
|
98
125
|
}
|
|
99
126
|
|
|
100
127
|
protected remove(): void {
|
|
101
|
-
if (this.
|
|
102
|
-
if (this.
|
|
103
|
-
this.
|
|
128
|
+
if (this.htmlElement) {
|
|
129
|
+
if (this.htmlElement.remove) {
|
|
130
|
+
this.htmlElement.remove();
|
|
104
131
|
} else {
|
|
105
|
-
if (this.
|
|
106
|
-
this.
|
|
132
|
+
if (this.htmlElement.parentElement) {
|
|
133
|
+
this.htmlElement.parentElement.removeChild(this.htmlElement);
|
|
107
134
|
}
|
|
108
135
|
}
|
|
109
136
|
|
|
110
|
-
this.
|
|
137
|
+
this.htmlElement = null;
|
|
111
138
|
}
|
|
112
139
|
}
|
|
113
140
|
|
|
114
|
-
protected addChild(child: IElement): Element<
|
|
141
|
+
protected addChild(child: IElement): Element<TElementProperties> {
|
|
115
142
|
this.children.push(child);
|
|
116
143
|
this.buildChildren();
|
|
117
144
|
return this;
|
|
118
145
|
}
|
|
119
146
|
|
|
120
|
-
protected setChildren(...children: Array<IElement>): Element<
|
|
147
|
+
protected setChildren(...children: Array<IElement>): Element<TElementProperties> {
|
|
121
148
|
this.empty();
|
|
122
149
|
|
|
123
150
|
this.children = children;
|
|
@@ -129,10 +156,10 @@ export class Element<TProperties = IProperties> implements IElement {
|
|
|
129
156
|
protected empty(): void {
|
|
130
157
|
this.children = [];
|
|
131
158
|
|
|
132
|
-
if (this.
|
|
133
|
-
this.
|
|
134
|
-
while (this.
|
|
135
|
-
this.
|
|
159
|
+
if (this.htmlElement) {
|
|
160
|
+
this.htmlElement.innerHTML = "";
|
|
161
|
+
while (this.htmlElement.firstChild) {
|
|
162
|
+
this.htmlElement.removeChild(this.htmlElement.firstChild);
|
|
136
163
|
}
|
|
137
164
|
}
|
|
138
165
|
}
|
|
@@ -140,7 +167,7 @@ export class Element<TProperties = IProperties> implements IElement {
|
|
|
140
167
|
|
|
141
168
|
// #region Public members
|
|
142
169
|
render(): HTMLElement {
|
|
143
|
-
if (this.
|
|
170
|
+
if (this.htmlElement) {
|
|
144
171
|
//If the element has already been rendered we remove the element from the dom
|
|
145
172
|
this.remove();
|
|
146
173
|
}
|
|
@@ -150,17 +177,17 @@ export class Element<TProperties = IProperties> implements IElement {
|
|
|
150
177
|
//Create the html element.
|
|
151
178
|
if (svgTags.hasOwnProperty(this.tagName)) {
|
|
152
179
|
//Create a SVGElement
|
|
153
|
-
this.
|
|
180
|
+
this.htmlElement = document.createElementNS(svgNamespace, this.tagName) as unknown as HTMLElement;
|
|
154
181
|
} else {
|
|
155
182
|
//Create a HTMLElement
|
|
156
|
-
this.
|
|
183
|
+
this.htmlElement = document.createElement(this.tagName);
|
|
157
184
|
}
|
|
158
185
|
|
|
159
186
|
//Build the UiElement
|
|
160
187
|
this.build();
|
|
161
188
|
|
|
162
189
|
//Return the fully functional html element
|
|
163
|
-
return this.
|
|
190
|
+
return this.htmlElement;
|
|
164
191
|
}
|
|
165
192
|
|
|
166
193
|
throw "The build method of this UiElement has not been defined";
|
|
@@ -169,7 +196,7 @@ export class Element<TProperties = IProperties> implements IElement {
|
|
|
169
196
|
|
|
170
197
|
//This method is used to dispose subscriptions before removing the element from the DOM to prevent memory leaks
|
|
171
198
|
unmount(): void {
|
|
172
|
-
const properties = this.properties as
|
|
199
|
+
const properties = this.properties as IElementProperties;
|
|
173
200
|
console.log("Unmount element " + properties.elementType);
|
|
174
201
|
|
|
175
202
|
//If the element has childeren then we unmount the children
|
|
@@ -186,28 +213,337 @@ export class Element<TProperties = IProperties> implements IElement {
|
|
|
186
213
|
}
|
|
187
214
|
|
|
188
215
|
focus(options?: FocusOptions) {
|
|
189
|
-
if (this.
|
|
190
|
-
this.
|
|
216
|
+
if (this.htmlElement) {
|
|
217
|
+
this.htmlElement.focus(options);
|
|
191
218
|
}
|
|
192
219
|
}
|
|
193
220
|
// #endregion
|
|
194
221
|
}
|
|
195
222
|
|
|
196
|
-
|
|
223
|
+
// #endregion
|
|
224
|
+
|
|
225
|
+
// #region ElementProperties Class definition
|
|
226
|
+
export abstract class ElementProperties implements IElementProperties {
|
|
227
|
+
protected setProperties<TProperties>(object: object, properties?: TProperties) {
|
|
228
|
+
if (properties) {
|
|
229
|
+
Object.keys(properties).forEach((property) => {
|
|
230
|
+
object[property] = properties[property];
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
attributes?: IAttributes;
|
|
236
|
+
classNames?: Array<string> | ISubscribable<Array<string>>;
|
|
237
|
+
style?: IStyle;
|
|
238
|
+
visible?: boolean | ISubscribable<boolean>;
|
|
239
|
+
disabled?: boolean | ISubscribable<boolean>;
|
|
240
|
+
innerHtml?: string | ISubscribable<string>;
|
|
241
|
+
textContent?: string | ISubscribable<string>;
|
|
242
|
+
addViewModelToDataObject?: boolean;
|
|
243
|
+
userSelectable?: boolean;
|
|
244
|
+
eventListeners?: Array<IEventListener>;
|
|
245
|
+
elementType?: string;
|
|
246
|
+
focused?: boolean | ISubscribable<boolean>;
|
|
247
|
+
}
|
|
248
|
+
// #endregion
|
|
249
|
+
|
|
250
|
+
//#region Element helper functions
|
|
251
|
+
|
|
252
|
+
export function extendProperties<TTarget = IElementProperties, TOverwritingProperties = TTarget, TPreserveExistingProperties = TTarget>(target: TTarget, preserveExisting: TPreserveExistingProperties, overWriteExisting?: TOverwritingProperties): TTarget {
|
|
253
|
+
if (overWriteExisting || preserveExisting) {
|
|
254
|
+
target = target || {} as TTarget;
|
|
255
|
+
|
|
256
|
+
if (typeof preserveExisting === "object") {
|
|
257
|
+
Object.keys(preserveExisting).forEach((key) => {
|
|
258
|
+
//Check if the target object does not already have a property with the given key
|
|
259
|
+
if (!target.hasOwnProperty(key) || typeof target[key] === "undefined") {
|
|
260
|
+
target[key] = preserveExisting[key];
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
if (typeof overWriteExisting === "object") {
|
|
266
|
+
Object.keys(overWriteExisting).forEach((key) => {
|
|
267
|
+
target[key] = overWriteExisting[key];
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
return target;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
export function createElement<TProperties>(options: IElementOptions<TProperties>, children?: Array<IElement> | ISubscribable<Array<IElement>>) {
|
|
197
277
|
return new Element<TProperties>(options, children);
|
|
198
278
|
}
|
|
279
|
+
|
|
280
|
+
//#endregion
|
|
281
|
+
|
|
282
|
+
//#region Element Binding functions
|
|
283
|
+
export function applyBindings(properties: IElementProperties, element: HTMLElement, disposers: Array<IDisposer>) {
|
|
284
|
+
element.setAttribute("elementtype", properties.elementType || "Element");
|
|
285
|
+
|
|
286
|
+
if (properties.classNames) {
|
|
287
|
+
applyClassesToElement(observable.unwrap(properties.classNames), true, element);
|
|
288
|
+
if (observable.isSubscribable(properties.classNames)) {
|
|
289
|
+
const disposer = properties.classNames.subscribe((classNames) => {
|
|
290
|
+
applyClassesToElement(classNames, true, element);
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
if (disposers) {
|
|
294
|
+
disposers.push(disposer);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
if (properties.attributes) {
|
|
300
|
+
Object.keys(properties.attributes).forEach((key) => {
|
|
301
|
+
const value = properties.attributes[key];
|
|
302
|
+
applyAttributeToElement(key as keyof IAttributes, observable.unwrap(value), element);
|
|
303
|
+
|
|
304
|
+
if (observable.isSubscribable(value)) {
|
|
305
|
+
const disposer = value.subscribe((value: string) => {
|
|
306
|
+
applyAttributeToElement(key as keyof IAttributes, value, element);
|
|
307
|
+
});
|
|
308
|
+
if (disposers) {
|
|
309
|
+
disposers.push(disposer);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
if (properties.style) {
|
|
316
|
+
Object.keys(properties.style).forEach((key) => {
|
|
317
|
+
const style = properties.style[key];
|
|
318
|
+
|
|
319
|
+
element.style[key] = observable.unwrap(style);
|
|
320
|
+
if (observable.isSubscribable(style)) {
|
|
321
|
+
const disposer = style.subscribe((style) => {
|
|
322
|
+
element.style[key] = style;
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
if (disposers) {
|
|
326
|
+
disposers.push(disposer);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
if (!isNullOrUndefined(properties.innerHtml)) {
|
|
333
|
+
|
|
334
|
+
element.innerHTML = observable.unwrap(properties.innerHtml);
|
|
335
|
+
|
|
336
|
+
if (observable.isSubscribable(properties.innerHtml)) {
|
|
337
|
+
const disposer = properties.innerHtml.subscribe((innerHtml: string) => {
|
|
338
|
+
element.innerHTML = innerHtml;
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
if (disposers) {
|
|
342
|
+
disposers.push(disposer);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
if (!isNullOrUndefined(properties.textContent)) {
|
|
348
|
+
|
|
349
|
+
const textContent = observable.unwrap(properties.textContent);
|
|
350
|
+
|
|
351
|
+
if (element.hasChildNodes() && element.childNodes.length === 1 && element.childNodes[0].nodeType === 3) {
|
|
352
|
+
element.firstChild.nodeValue = textContent;
|
|
353
|
+
} else {
|
|
354
|
+
element.textContent = observable.unwrap(properties.textContent);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
if (observable.isSubscribable(properties.textContent)) {
|
|
358
|
+
const disposer = properties.textContent.subscribe((textContent) => {
|
|
359
|
+
if (element.hasChildNodes() && element.childNodes.length === 1 && element.childNodes[0].nodeType === 3) {
|
|
360
|
+
element.firstChild.nodeValue = textContent;
|
|
361
|
+
} else {
|
|
362
|
+
element.textContent = observable.unwrap(properties.textContent);
|
|
363
|
+
}
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
if (disposers) {
|
|
367
|
+
disposers.push(disposer);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
//Find out if the element is none selectable
|
|
373
|
+
if (properties.userSelectable === false) {
|
|
374
|
+
applyEventListenerToElement({
|
|
375
|
+
type: Event,
|
|
376
|
+
name: "selectstart",
|
|
377
|
+
handler: () => { return false; },
|
|
378
|
+
passive: true
|
|
379
|
+
},
|
|
380
|
+
element
|
|
381
|
+
);
|
|
382
|
+
element.style.userSelect = "none";
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
if (properties.addViewModelToDataObject) {
|
|
386
|
+
if (!element["data"]) {
|
|
387
|
+
element["data"] = {};
|
|
388
|
+
}
|
|
389
|
+
element["data"].viewModel = properties;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
if (properties.eventListeners) {
|
|
393
|
+
applyEventListenersToElement(properties.eventListeners, element);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
applyVisibilityToElement(observable.unwrap(properties.visible), element);
|
|
397
|
+
if (observable.isSubscribable(properties.visible)) {
|
|
398
|
+
const disposer = properties.visible.subscribe((visible) => {
|
|
399
|
+
applyVisibilityToElement(visible, element);
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
if (disposers) {
|
|
403
|
+
disposers.push(disposer);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
applyDisabledToElement(observable.unwrap(properties.disabled), element);
|
|
408
|
+
if (observable.isSubscribable(properties.disabled)) {
|
|
409
|
+
const disposer = properties.disabled.subscribe((disabled) => {
|
|
410
|
+
applyDisabledToElement(disabled, element);
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
if (disposers) {
|
|
414
|
+
disposers.push(disposer);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
applyFocusToElement(observable.unwrap(properties.focused), element);
|
|
419
|
+
if (observable.isSubscribable(properties.focused)) {
|
|
420
|
+
const disposer = properties.focused.subscribe((focused) => {
|
|
421
|
+
applyFocusToElement(focused, element);
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
if (disposers) {
|
|
425
|
+
disposers.push(disposer);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
function applyVisibilityToElement(visible: boolean, element: HTMLElement) {
|
|
431
|
+
if (visible === false) {
|
|
432
|
+
element.classList.add("hidden");
|
|
433
|
+
} else {
|
|
434
|
+
element.classList.remove("hidden");
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
function applyDisabledToElement(disabled: boolean, element: HTMLElement) {
|
|
439
|
+
if (disabled) {
|
|
440
|
+
element.setAttribute("disabled", "disabled");
|
|
441
|
+
} else {
|
|
442
|
+
element.removeAttribute("disabled");
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
function applyEventListenersToElement(eventListeners: Array<IEventListener>, element: HTMLElement) {
|
|
447
|
+
if (!element.addEventListener) {
|
|
448
|
+
throw new Error("Your browser does not support addEventListener");
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
if (eventListeners) {
|
|
452
|
+
eventListeners.forEach((eventListener) => {
|
|
453
|
+
applyEventListenerToElement(eventListener, element);
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
function applyEventListenerToElement(eventListener: IEventListener, element: HTMLElement) {
|
|
459
|
+
const type = eventListener.type;
|
|
460
|
+
const name = eventListener.name;
|
|
461
|
+
let handler = eventListener.handler;
|
|
462
|
+
const options: AddEventListenerOptions = {
|
|
463
|
+
passive: eventListener.passive || false,
|
|
464
|
+
once: eventListener.once || false
|
|
465
|
+
};
|
|
466
|
+
|
|
467
|
+
if (!type) {
|
|
468
|
+
throw new Error("type is mandatory");
|
|
469
|
+
}
|
|
470
|
+
if (!name) {
|
|
471
|
+
throw new Error("name is mandatory");
|
|
472
|
+
}
|
|
473
|
+
if (!handler) {
|
|
474
|
+
throw new Error("handler is mandatory");
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
if (name === "dragstart") {
|
|
478
|
+
element.setAttribute("draggable", "true");
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
if (eventListener.type === KeyboardEvent) {
|
|
482
|
+
handler = (event: KeyboardEvent) => {
|
|
483
|
+
if (eventListener.altKey && !event.altKey) {
|
|
484
|
+
return;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
if (eventListener.shiftKey && !event.shiftKey) {
|
|
488
|
+
return;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
if (eventListener.ctrlKey && !event.ctrlKey) {
|
|
492
|
+
return;
|
|
493
|
+
}
|
|
494
|
+
if (eventListener.key && eventListener.key !== event.key) {
|
|
495
|
+
return;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
handler(event);
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
|
|
503
|
+
//Add the event listener to the element
|
|
504
|
+
element.addEventListener(name, handler, options);
|
|
505
|
+
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
function applyClassesToElement(classNames: string[], replace: boolean, element: HTMLElement) {
|
|
509
|
+
//If all existing classes need to be replace we reset the classes object to an empty object
|
|
510
|
+
if (replace) {
|
|
511
|
+
element.className = "";
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
//Add all the classNames to the classes object
|
|
515
|
+
if (classNames) {
|
|
516
|
+
classNames.forEach((className) => {
|
|
517
|
+
element.classList.add(className);
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
function applyAttributeToElement(name: keyof IAttributes, value: string, element: HTMLElement) {
|
|
523
|
+
if (isNullOrUndefined(value)) {
|
|
524
|
+
element.removeAttribute(name);
|
|
525
|
+
} else {
|
|
526
|
+
element.setAttribute(name, value);
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
function applyFocusToElement(focused: boolean, element: HTMLElement) {
|
|
531
|
+
if (focused) {
|
|
532
|
+
element.focus();
|
|
533
|
+
}
|
|
534
|
+
}
|
|
199
535
|
//#endregion
|
|
200
536
|
|
|
201
|
-
//#region
|
|
202
|
-
//
|
|
537
|
+
//#region Element dictionary
|
|
538
|
+
//eslint-disable-next-line @typescript-eslint/no-unsafe-function-type, @typescript-eslint/no-explicit-any
|
|
203
539
|
const elementDictionary = new Map<Function, any>();
|
|
204
540
|
|
|
205
|
-
//
|
|
541
|
+
//eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
|
206
542
|
export function addElementToDictionary(properties: Function, element: Function) {
|
|
207
543
|
elementDictionary.set(properties, element);
|
|
208
544
|
}
|
|
209
545
|
|
|
210
|
-
export function getElement(properties:
|
|
546
|
+
export function getElement(properties: IElementProperties): IElement {
|
|
211
547
|
if (properties && properties.constructor) {
|
|
212
548
|
const element = elementDictionary.get(properties.constructor);
|
|
213
549
|
if (element.prototype) {
|
|
@@ -220,7 +556,7 @@ export function getElement(properties: Properties): Element {
|
|
|
220
556
|
return null;
|
|
221
557
|
}
|
|
222
558
|
|
|
223
|
-
export function render(properties:
|
|
559
|
+
export function render(properties: IElementProperties): HTMLElement {
|
|
224
560
|
const view = getElement(properties);
|
|
225
561
|
if (view && view.render) {
|
|
226
562
|
return view.render();
|
package/src/framework/event.ts
CHANGED
|
@@ -9,8 +9,6 @@ export type TouchEventType = "touchstart" | "touchend" | "touchmove" | "touchcan
|
|
|
9
9
|
export type MouseEventType = "contextmenu" | "dblclick" | "mousedown" | "mouseenter" | "mouseleave" | "mousemove" | "mouseout" | "mouseover" | "mouseup";
|
|
10
10
|
export type FocusEventType = "blur" | "focusout" | "focus" | "focusin";
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
12
|
export interface IEventListener extends AddEventListenerOptions, KeyboardEventInit {
|
|
15
13
|
type: EventType;
|
|
16
14
|
name: string;
|