Newer
Older
// eslint-disable-next-line max-classes-per-file
import { ElementComponent } from 'common/directives/element-component.directive';
import { Type } from '@angular/core';
import { ClozeDocument } from 'common/models/elements/compound-elements/cloze/cloze';
import { LikertRowElement } from 'common/models/elements/compound-elements/likert/likert-row';
export type UIElementType = 'text' | 'button' | 'text-field' | 'text-field-simple' | 'text-area' | 'checkbox'
| 'dropdown' | 'radio' | 'image' | 'audio' | 'video' | 'likert' | 'likert-row' | 'radio-group-images' | 'hotspot-image'
| 'drop-list' | 'drop-list-simple' | 'cloze' | 'spell-correct' | 'slider' | 'frame' | 'toggle-button' | 'geometry'
| 'math-field';
export type UIElementValue = string | number | boolean | undefined | UIElementType | InputElementValue |
TextLabel | TextLabel[] | ClozeDocument | LikertRowElement[] | Hotspot[] |
PositionProperties | PlayerProperties | BasicStyles;
export type InputAssistancePreset = null | 'french' | 'numbers' | 'numbersAndOperators' | 'numbersAndBasicOperators'
| 'comparisonOperators' | 'squareDashDot' | 'placeValue' | 'space' | 'comma' | 'custom';
type: UIElementType;
width: number = 180;
height: number = 60;
position?: PositionProperties;
styling?: BasicStyles & ExtendedStyles;
player?: PlayerProperties;
if (!element.type) throw Error('Element has no type!');
this.type = element.type;
if (element.width !== undefined) this.width = element.width;
if (element.height !== undefined) this.height = element.height;
}
setProperty(property: string, value: UIElementValue): void {
if (Array.isArray(this[property])) { // keep array reference intact
(this[property] as UIElementValue[])
.splice(0, (this[property] as UIElementValue[]).length, ...(value as UIElementValue[]));
} else {
this[property] = value;
}
}
setStyleProperty(property: string, value: UIElementValue): void {
(this.styling as BasicStyles & ExtendedStyles)[property] = value;
}
setPositionProperty(property: string, value: UIElementValue): void {
}
setPlayerProperty(property: string, value: UIElementValue): void {
hasAnswerScheme(): boolean {
return Boolean(this.getAnswerSchemeValues);
abstract getElementComponent(): Type<ElementComponent>;
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
static initPositionProps(defaults: Partial<PositionProperties> = {}): PositionProperties {
return {
fixedSize: defaults.fixedSize !== undefined ? defaults.fixedSize as boolean : false,
dynamicPositioning: defaults.dynamicPositioning !== undefined ? defaults.dynamicPositioning as boolean : true,
xPosition: defaults.xPosition !== undefined ? defaults.xPosition as number : 0,
yPosition: defaults.yPosition !== undefined ? defaults.yPosition as number : 0,
useMinHeight: defaults.useMinHeight !== undefined ? defaults.useMinHeight as boolean : false,
gridColumn: defaults.gridColumn !== undefined ? defaults.gridColumn as number : null,
gridColumnRange: defaults.gridColumnRange !== undefined ? defaults.gridColumnRange as number : 1,
gridRow: defaults.gridRow !== undefined ? defaults.gridRow as number : null,
gridRowRange: defaults.gridRowRange !== undefined ? defaults.gridRowRange as number : 1,
marginLeft: defaults.marginLeft !== undefined ? defaults.marginLeft as number : 0,
marginRight: defaults.marginRight !== undefined ? defaults.marginRight as number : 0,
marginTop: defaults.marginTop !== undefined ? defaults.marginTop as number : 0,
marginBottom: defaults.marginBottom !== undefined ? defaults.marginBottom as number : 0,
zIndex: defaults.zIndex !== undefined ? defaults.zIndex as number : 0
};
}
static initStylingProps<T>(defaults?: Partial<BasicStyles> & T): BasicStyles & T {
return {
...defaults as T,
fontColor: defaults?.fontColor !== undefined ? defaults.fontColor as string : '#000000',
font: defaults?.font !== undefined ? defaults.font as string : 'Roboto',
fontSize: defaults?.fontSize !== undefined ? defaults.fontSize as number : 20,
bold: defaults?.bold !== undefined ? defaults.bold as boolean : false,
italic: defaults?.italic !== undefined ? defaults.italic as boolean : false,
underline: defaults?.underline !== undefined ? defaults.underline as boolean : false,
backgroundColor: defaults?.backgroundColor !== undefined ? defaults.backgroundColor as string : '#d3d3d3'
};
}
static createOptionLabel(optionText: string, addImg: boolean = false) {
return {
text: optionText,
imgSrc: addImg ? null : undefined,
imgPosition: addImg ? 'above' : undefined
};
}
export type InputElementValue = string[] | string | number | boolean | TextLabel[] | null | Hotspot[] | boolean[];
export abstract class InputElement extends UIElement {
label: string = 'Beschriftung';
value: InputElementValue = null;
required: boolean = false;
requiredWarnMessage: string = 'Eingabe erforderlich';
readOnly: boolean = false;
protected constructor(element: Partial<InputElement>) {
super(element);
if (element.label !== undefined) this.label = element.label;
if (element.value !== undefined) this.value = element.value;
if (element.required) this.required = element.required;
if (element.requiredWarnMessage !== undefined) this.requiredWarnMessage = element.requiredWarnMessage;
if (element.readOnly) this.readOnly = element.readOnly;
abstract getAnswerScheme(options?: unknown): AnswerScheme;
static stripHTML(htmlString: string): string {
const parser = new DOMParser();
const htmlDocument = parser.parseFromString(htmlString, 'text/html');
return htmlDocument.documentElement.textContent || '';
}
export abstract class TextInputElement extends InputElement {
inputAssistancePreset: InputAssistancePreset = null;
inputAssistanceCustomKeys: string = '';
inputAssistancePosition: 'floating' | 'right' = 'floating';
restrictedToInputAssistanceChars: boolean = true;
hasArrowKeys: boolean = false;
showSoftwareKeyboard: boolean = false;
softwareKeyboardShowFrench: boolean = false;
protected constructor(element: Partial<TextInputElement>) {
super(element);
if (element.inputAssistancePreset) this.inputAssistancePreset = element.inputAssistancePreset;
if (element.inputAssistanceCustomKeys !== undefined) {
this.inputAssistanceCustomKeys = element.inputAssistanceCustomKeys;
}
if (element.inputAssistancePosition) this.inputAssistancePosition = element.inputAssistancePosition;
if (element.restrictedToInputAssistanceChars !== undefined) {
this.restrictedToInputAssistanceChars = element.restrictedToInputAssistanceChars;
}
if (element.hasArrowKeys) this.hasArrowKeys = element.hasArrowKeys;
if (element.showSoftwareKeyboard) this.showSoftwareKeyboard = element.showSoftwareKeyboard;
if (element.softwareKeyboardShowFrench) this.softwareKeyboardShowFrench = element.softwareKeyboardShowFrench;
}
}
export abstract class CompoundElement extends UIElement {
abstract getChildElements(): UIElement[];
}
export abstract class PlayerElement extends UIElement {
player: PlayerProperties;
protected constructor(element: Partial<PlayerElement>) {
super(element);
autostart: element.player?.autostart !== undefined ? element.player?.autostart as boolean : false,
autostartDelay: element.player?.autostartDelay !== undefined ? element.player?.autostartDelay as number : 0,
loop: element.player?.loop !== undefined ? element.player?.loop as boolean : false,
startControl: element.player?.startControl !== undefined ? element.player?.startControl as boolean : true,
pauseControl: element.player?.pauseControl !== undefined ? element.player?.pauseControl as boolean : false,
progressBar: element.player?.progressBar !== undefined ? element.player?.progressBar as boolean : true,
interactiveProgressbar: element.player?.interactiveProgressbar !== undefined ?
element.player?.interactiveProgressbar as boolean :
volumeControl: element.player?.volumeControl !== undefined ? element.player?.volumeControl as boolean : true,
defaultVolume: element.player?.defaultVolume !== undefined ? element.player?.defaultVolume as number : 0.8,
minVolume: element.player?.minVolume !== undefined ? element.player?.minVolume as number : 0,
muteControl: element.player?.muteControl !== undefined ? element.player?.muteControl as boolean : true,
interactiveMuteControl: element.player?.interactiveMuteControl !== undefined ?
element.player?.interactiveMuteControl as boolean :
hintLabel: element.player?.hintLabel !== undefined ? element.player?.hintLabel as string : '',
hintLabelDelay: element.player?.hintLabelDelay !== undefined ? element.player?.hintLabelDelay as number : 0,
activeAfterID: element.player?.activeAfterID !== undefined ? element.player?.activeAfterID as string : '',
minRuns: element.player?.minRuns !== undefined ? element.player?.minRuns as number : 1,
maxRuns: element.player?.maxRuns !== undefined ? element.player?.maxRuns as number | null : null,
showRestRuns: element.player?.showRestRuns !== undefined ? element.player?.showRestRuns as boolean : false,
showRestTime: element.player?.showRestTime !== undefined ? element.player?.showRestTime as boolean : true,
playbackTime: element.player?.playbackTime !== undefined ? element.player?.playbackTime as number : 0
hasAnswerScheme(): boolean {
return Boolean(this.getAnswerScheme);
getAnswerScheme(): AnswerScheme {
return {
id: this.id,
type: 'string',
format: 'playback',
multiple: false,
nullable: true,
values: [],
valuesComplete: true
};
}
export interface AnswerSchemeValue {
value: string;
label: string;
}
export interface AnswerScheme {
id: string;
type: string;
format?: string;
multiple?: boolean;
nullable?: boolean;
values?: AnswerSchemeValue[];
}
export interface PositionedUIElement extends UIElement {
position: PositionProperties;
}
export interface PositionProperties {
fixedSize: boolean;
dynamicPositioning: boolean;
xPosition: number;
yPosition: number;
useMinHeight: boolean;
gridColumn: number | null;
gridColumnRange: number;
gridRow: number | null;
gridRowRange: number;
marginLeft: number;
marginRight: number;
marginTop: number;
marginBottom: number;
zIndex: number;
}
export interface BasicStyles {
fontColor: string;
font: string;
fontSize: number;
bold: boolean;
italic: boolean;
underline: boolean;
backgroundColor: string;
}
export interface ExtendedStyles {
lineHeight?: number;
borderRadius?: number;
itemBackgroundColor?: string;
borderWidth?: number;
borderColor?: string;
borderStyle?: 'solid' | 'dotted' | 'dashed' | 'double' | 'groove' | 'ridge' | 'inset' | 'outset';
lineColoring?: boolean;
lineColoringColor?: string;
selectionColor?: string;
}
export interface PlayerElement {
player: PlayerProperties;
}
export interface PlayerProperties {
autostart: boolean;
autostartDelay: number;
loop: boolean;
startControl: boolean;
pauseControl: boolean;
progressBar: boolean;
interactiveProgressbar: boolean;
volumeControl: boolean;
defaultVolume: number;
minVolume: number;
muteControl: boolean;
interactiveMuteControl: boolean;
hintLabel: string;
hintLabelDelay: number;
activeAfterID: string;
minRuns: number;
maxRuns: number | null;
showRestRuns: boolean;
showRestTime: boolean;
playbackTime: number;
}
export interface Hotspot {
top: number;
left: number;
width: number;
height: number;
shape: 'ellipse' | 'rectangle' | 'triangle';
borderWidth: number;
borderColor: string;
backgroundColor: string;
rotation: number;
value: boolean;
readOnly: boolean
}
export interface ValueChangeElement {
id: string;
value: InputElementValue;
}
export interface ButtonEvent {
action: ButtonAction;
param: UnitNavParam | number | string;
export type ButtonAction = 'unitNav' | 'pageNav' | 'highlightText';
export type UnitNavParam = 'previous' | 'next' | 'first' | 'last' | 'end';
export interface OptionElement extends UIElement {
}
export interface TextLabel {
}
export interface TextImageLabel extends TextLabel {
imgPosition: 'above' | 'below' | 'left' | 'right';
export interface DragNDropValueObject extends TextImageLabel {
returnToOriginOnReplacement?: boolean;
originListID?: string;
originListIndex?: number;
}
export type Label = TextLabel | TextImageLabel | DragNDropValueObject;