From 0c0b9e3b673d00bb8b5e516b3c0974ff64a4fc76 Mon Sep 17 00:00:00 2001
From: rhenck <richard.henck@iqb.hu-berlin.de>
Date: Mon, 17 Oct 2022 16:37:43 +0200
Subject: [PATCH] Rework Elementfactory

The unit tests errored out because of circular dependencies via the
Elementfactory class. Therefore:
- No longer creates styling/position/player-Properties. This is done in
the Element parent class.
- Move element creation from Section to the ElementFactory class
instead.
---
 .../common/models/elements/button/button.ts   |  5 +-
 .../cloze-child-elements/drop-list-simple.ts  |  7 +-
 .../cloze-child-elements/text-field-simple.ts |  5 +-
 .../cloze-child-elements/toggle-button.ts     |  7 +-
 .../elements/compound-elements/cloze/cloze.ts |  5 +-
 .../compound-elements/likert/likert.ts        |  7 +-
 projects/common/models/elements/element.ts    | 68 ++++++++++++++++-
 .../common/models/elements/frame/frame.ts     |  5 +-
 .../models/elements/geometry/geometry.ts      |  3 +-
 .../elements/input-elements/checkbox.ts       |  7 +-
 .../elements/input-elements/drop-list.ts      |  7 +-
 .../elements/input-elements/dropdown.ts       |  9 +--
 .../radio-button-group-complex.ts             |  9 +--
 .../input-elements/radio-button-group.ts      |  9 +--
 .../models/elements/input-elements/slider.ts  |  7 +-
 .../elements/input-elements/spell-correct.ts  |  7 +-
 .../elements/input-elements/text-area.ts      |  7 +-
 .../elements/input-elements/text-field.ts     |  7 +-
 .../models/elements/media-elements/audio.ts   |  5 +-
 .../models/elements/media-elements/image.ts   |  7 +-
 .../models/elements/media-elements/video.ts   |  7 +-
 projects/common/models/elements/text/text.ts  |  5 +-
 projects/common/models/section.ts             |  2 +-
 projects/common/util/element.factory.ts       | 73 +------------------
 24 files changed, 128 insertions(+), 152 deletions(-)

diff --git a/projects/common/models/elements/button/button.ts b/projects/common/models/elements/button/button.ts
index b5bdcc645..adebce926 100644
--- a/projects/common/models/elements/button/button.ts
+++ b/projects/common/models/elements/button/button.ts
@@ -1,5 +1,4 @@
 import { Type } from '@angular/core';
-import { ElementFactory } from 'common/util/element.factory';
 import {
   BasicStyles, PositionProperties, UIElement
 } from 'common/models/elements/element';
@@ -24,9 +23,9 @@ export class ButtonElement extends UIElement {
     if (element.asLink) this.asLink = element.asLink;
     if (element.action) this.action = element.action;
     if (element.actionParam) this.actionParam = element.actionParam;
-    this.position = element.position ? ElementFactory.initPositionProps(element.position) : undefined;
+    this.position = element.position ? UIElement.initPositionProps(element.position) : undefined;
     this.styling = {
-      ...ElementFactory.initStylingProps<{ borderRadius: number; }>({ borderRadius: 0, ...element.styling })
+      ...UIElement.initStylingProps<{ borderRadius: number; }>({ borderRadius: 0, ...element.styling })
     };
   }
 
diff --git a/projects/common/models/elements/compound-elements/cloze/cloze-child-elements/drop-list-simple.ts b/projects/common/models/elements/compound-elements/cloze/cloze-child-elements/drop-list-simple.ts
index d20e07787..7b7022b7b 100644
--- a/projects/common/models/elements/compound-elements/cloze/cloze-child-elements/drop-list-simple.ts
+++ b/projects/common/models/elements/compound-elements/cloze/cloze-child-elements/drop-list-simple.ts
@@ -1,7 +1,6 @@
-import { ElementFactory } from 'common/util/element.factory';
 import {
-  BasicStyles, DragNDropValueObject, InputElement, UIElementValue, AnswerScheme,
-  AnswerSchemeValue
+  BasicStyles, DragNDropValueObject, InputElement, AnswerScheme,
+  AnswerSchemeValue, UIElement
 } from 'common/models/elements/element';
 import { Type } from '@angular/core';
 import { ElementComponent } from 'common/directives/element-component.directive';
@@ -30,7 +29,7 @@ export class DropListSimpleElement extends InputElement {
       this.highlightReceivingDropListColor = element.highlightReceivingDropListColor;
     }
     this.styling = {
-      ...ElementFactory.initStylingProps({
+      ...UIElement.initStylingProps({
         backgroundColor: '#f4f4f2',
         itemBackgroundColor: '#c9e0e0',
         ...element.styling
diff --git a/projects/common/models/elements/compound-elements/cloze/cloze-child-elements/text-field-simple.ts b/projects/common/models/elements/compound-elements/cloze/cloze-child-elements/text-field-simple.ts
index 98a4ac092..a2bb0d812 100644
--- a/projects/common/models/elements/compound-elements/cloze/cloze-child-elements/text-field-simple.ts
+++ b/projects/common/models/elements/compound-elements/cloze/cloze-child-elements/text-field-simple.ts
@@ -1,6 +1,5 @@
-import { ElementFactory } from 'common/util/element.factory';
 import {
-  BasicStyles, InputAssistancePreset, InputElement, AnswerScheme
+  BasicStyles, InputAssistancePreset, InputElement, AnswerScheme, UIElement
 } from 'common/models/elements/element';
 import { Type } from '@angular/core';
 import { ElementComponent } from 'common/directives/element-component.directive';
@@ -42,7 +41,7 @@ export class TextFieldSimpleElement extends InputElement {
     if (element.softwareKeyboardShowFrench) this.softwareKeyboardShowFrench = element.softwareKeyboardShowFrench;
     if (element.clearable) this.clearable = element.clearable;
     this.styling = {
-      ...ElementFactory.initStylingProps({ lineHeight: 135, backgroundColor: 'transparent', ...element.styling })
+      ...UIElement.initStylingProps({ lineHeight: 135, backgroundColor: 'transparent', ...element.styling })
     };
   }
 
diff --git a/projects/common/models/elements/compound-elements/cloze/cloze-child-elements/toggle-button.ts b/projects/common/models/elements/compound-elements/cloze/cloze-child-elements/toggle-button.ts
index 7b760a873..106a94634 100644
--- a/projects/common/models/elements/compound-elements/cloze/cloze-child-elements/toggle-button.ts
+++ b/projects/common/models/elements/compound-elements/cloze/cloze-child-elements/toggle-button.ts
@@ -1,6 +1,5 @@
-import { ElementFactory } from 'common/util/element.factory';
 import {
-  BasicStyles, InputElement, AnswerScheme, AnswerSchemeValue, TextLabel
+  BasicStyles, InputElement, AnswerScheme, AnswerSchemeValue, TextLabel, UIElement
 } from 'common/models/elements/element';
 import { Type } from '@angular/core';
 import { ElementComponent } from 'common/directives/element-component.directive';
@@ -27,7 +26,7 @@ export class ToggleButtonElement extends InputElement {
     if (element.verticalOrientation) this.verticalOrientation = element.verticalOrientation;
     if (element.dynamicWidth !== undefined) this.dynamicWidth = element.dynamicWidth;
     this.styling = {
-      ...ElementFactory.initStylingProps({
+      ...UIElement.initStylingProps({
         lineHeight: 135,
         selectionColor: '#c7f3d0',
         backgroundColor: 'transparent',
@@ -62,6 +61,6 @@ export class ToggleButtonElement extends InputElement {
   }
 
   getNewOptionLabel(optionText: string): TextLabel {
-    return ElementFactory.createOptionLabel(optionText) as TextLabel;
+    return UIElement.createOptionLabel(optionText) as TextLabel;
   }
 }
diff --git a/projects/common/models/elements/compound-elements/cloze/cloze.ts b/projects/common/models/elements/compound-elements/cloze/cloze.ts
index e55f6ebc2..fa9bf59ca 100644
--- a/projects/common/models/elements/compound-elements/cloze/cloze.ts
+++ b/projects/common/models/elements/compound-elements/cloze/cloze.ts
@@ -9,7 +9,6 @@ import {
 import { Type } from '@angular/core';
 import { ElementComponent } from 'common/directives/element-component.directive';
 import { ClozeComponent } from 'common/components/compound-elements/cloze/cloze.component';
-import { ElementFactory } from 'common/util/element.factory';
 import {
   TextFieldSimpleElement
 } from 'common/models/elements/compound-elements/cloze/cloze-child-elements/text-field-simple';
@@ -31,9 +30,9 @@ export class ClozeElement extends CompoundElement implements PositionedUIElement
     super({ height: 200, ...element });
     if (element.columnCount) this.columnCount = element.columnCount;
     this.document = ClozeElement.initDocument(element.document);
-    this.position = ElementFactory.initPositionProps(element.position);
+    this.position = UIElement.initPositionProps(element.position);
     this.styling = {
-      ...ElementFactory.initStylingProps({ lineHeight: 150, ...element.styling })
+      ...UIElement.initStylingProps({ lineHeight: 150, ...element.styling })
     };
   }
 
diff --git a/projects/common/models/elements/compound-elements/likert/likert.ts b/projects/common/models/elements/compound-elements/likert/likert.ts
index 4133417f5..e2d2ab63a 100644
--- a/projects/common/models/elements/compound-elements/likert/likert.ts
+++ b/projects/common/models/elements/compound-elements/likert/likert.ts
@@ -1,5 +1,4 @@
 import { Type } from '@angular/core';
-import { ElementFactory } from 'common/util/element.factory';
 import {
   BasicStyles, CompoundElement, UIElement,
   PositionedUIElement, PositionProperties, UIElementValue, TextImageLabel, OptionElement
@@ -28,9 +27,9 @@ export class LikertElement extends CompoundElement implements PositionedUIElemen
     this.rows = element.rows !== undefined ? element.rows?.map(row => new LikertRowElement(row)) : [];
     this.label = element.label !== undefined ? element.label : 'Optionentabelle Beschriftung';
     this.label2 = element.label2 !== undefined ? element.label2 : 'Optionentabelle Erste Spalte';
-    this.position = ElementFactory.initPositionProps(element.position);
+    this.position = UIElement.initPositionProps(element.position);
     this.styling = {
-      ...ElementFactory.initStylingProps({
+      ...UIElement.initStylingProps({
         backgroundColor: 'transparent',
         lineHeight: 135,
         lineColoring: true,
@@ -41,7 +40,7 @@ export class LikertElement extends CompoundElement implements PositionedUIElemen
   }
 
   getNewOptionLabel(optionText: string): TextImageLabel {
-    return ElementFactory.createOptionLabel(optionText, true) as TextImageLabel;
+    return UIElement.createOptionLabel(optionText, true) as TextImageLabel;
   }
 
   setProperty(property: string, value: UIElementValue): void {
diff --git a/projects/common/models/elements/element.ts b/projects/common/models/elements/element.ts
index 77a5e89d5..5806b0a34 100644
--- a/projects/common/models/elements/element.ts
+++ b/projects/common/models/elements/element.ts
@@ -2,7 +2,6 @@
 import { ElementComponent } from 'common/directives/element-component.directive';
 import { Type } from '@angular/core';
 import { ClozeDocument } from 'common/models/elements/compound-elements/cloze/cloze';
-import { ElementFactory } from 'common/util/element.factory';
 import { LikertRowElement } from 'common/models/elements/compound-elements/likert/likert-row';
 
 export type UIElementType = 'text' | 'button' | 'text-field' | 'text-field-simple' | 'text-area' | 'checkbox'
@@ -59,6 +58,46 @@ export abstract class UIElement {
   }
 
   abstract getElementComponent(): Type<ElementComponent>;
+
+  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;
@@ -91,7 +130,32 @@ export abstract class PlayerElement extends UIElement {
 
   protected constructor(element: Partial<PlayerElement>) {
     super(element);
-    this.player = ElementFactory.initPlayerProps(element.player);
+    this.player = {
+      autostart: element.autostart !== undefined ? element.autostart as boolean : false,
+      autostartDelay: element.autostartDelay !== undefined ? element.autostartDelay as number : 0,
+      loop: element.loop !== undefined ? element.loop as boolean : false,
+      startControl: element.startControl !== undefined ? element.startControl as boolean : true,
+      pauseControl: element.pauseControl !== undefined ? element.pauseControl as boolean : false,
+      progressBar: element.progressBar !== undefined ? element.progressBar as boolean : true,
+      interactiveProgressbar: element.interactiveProgressbar !== undefined ?
+        element.interactiveProgressbar as boolean :
+        false,
+      volumeControl: element.volumeControl !== undefined ? element.volumeControl as boolean : true,
+      defaultVolume: element.defaultVolume !== undefined ? element.defaultVolume as number : 0.8,
+      minVolume: element.minVolume !== undefined ? element.minVolume as number : 0,
+      muteControl: element.muteControl !== undefined ? element.muteControl as boolean : true,
+      interactiveMuteControl: element.interactiveMuteControl !== undefined ?
+        element.interactiveMuteControl as boolean :
+        false,
+      hintLabel: element.hintLabel !== undefined ? element.hintLabel as string : '',
+      hintLabelDelay: element.hintLabelDelay !== undefined ? element.hintLabelDelay as number : 0,
+      activeAfterID: element.activeAfterID !== undefined ? element.activeAfterID as string : '',
+      minRuns: element.minRuns !== undefined ? element.minRuns as number : 1,
+      maxRuns: element.maxRuns !== undefined ? element.maxRuns as number | null : null,
+      showRestRuns: element.showRestRuns !== undefined ? element.showRestRuns as boolean : false,
+      showRestTime: element.showRestTime !== undefined ? element.showRestTime as boolean : true,
+      playbackTime: element.playbackTime !== undefined ? element.playbackTime as number : 0
+    };
   }
 
   hasAnswerScheme(): boolean {
diff --git a/projects/common/models/elements/frame/frame.ts b/projects/common/models/elements/frame/frame.ts
index 50c83ebe5..f22a9a3f7 100644
--- a/projects/common/models/elements/frame/frame.ts
+++ b/projects/common/models/elements/frame/frame.ts
@@ -1,5 +1,4 @@
 import { Type } from '@angular/core';
-import { ElementFactory } from 'common/util/element.factory';
 import {
   BasicStyles, PositionedUIElement, PositionProperties, UIElement
 } from 'common/models/elements/element';
@@ -26,9 +25,9 @@ export class FrameElement extends UIElement implements PositionedUIElement {
     this.hasBorderBottom = element.hasBorderBottom !== undefined ? element.hasBorderBottom : true;
     this.hasBorderLeft = element.hasBorderLeft !== undefined ? element.hasBorderLeft : true;
     this.hasBorderRight = element.hasBorderRight !== undefined ? element.hasBorderRight : true;
-    this.position = ElementFactory.initPositionProps({ zIndex: -1, ...element.position });
+    this.position = UIElement.initPositionProps({ zIndex: -1, ...element.position });
     this.styling = {
-      ...ElementFactory.initStylingProps({
+      ...UIElement.initStylingProps({
         backgroundColor: 'transparent',
         borderWidth: 1,
         borderColor: 'black',
diff --git a/projects/common/models/elements/geometry/geometry.ts b/projects/common/models/elements/geometry/geometry.ts
index 598990b5c..acdfeb612 100644
--- a/projects/common/models/elements/geometry/geometry.ts
+++ b/projects/common/models/elements/geometry/geometry.ts
@@ -1,5 +1,4 @@
 import { Type } from '@angular/core';
-import { ElementFactory } from 'common/util/element.factory';
 import {
   PositionedUIElement, PositionProperties, UIElement
 } from 'common/models/elements/element';
@@ -22,7 +21,7 @@ export class GeometryElement extends UIElement implements PositionedUIElement {
     this.appDefinition = element.appDefinition !== undefined ? element.appDefinition : '';
     this.showResetIcon = element.showResetIcon !== undefined ? element.showResetIcon : true;
 
-    this.position = ElementFactory.initPositionProps({ ...element.position });
+    this.position = UIElement.initPositionProps({ ...element.position });
   }
 
   getElementComponent(): Type<ElementComponent> {
diff --git a/projects/common/models/elements/input-elements/checkbox.ts b/projects/common/models/elements/input-elements/checkbox.ts
index 5c7923c8a..3761d3c86 100644
--- a/projects/common/models/elements/input-elements/checkbox.ts
+++ b/projects/common/models/elements/input-elements/checkbox.ts
@@ -1,7 +1,6 @@
 import { Type } from '@angular/core';
-import { ElementFactory } from 'common/util/element.factory';
 import {
-  BasicStyles, InputElement, PositionedUIElement, PositionProperties, AnswerScheme, AnswerSchemeValue
+  BasicStyles, InputElement, PositionedUIElement, PositionProperties, AnswerScheme, AnswerSchemeValue, UIElement
 } from 'common/models/elements/element';
 import { ElementComponent } from 'common/directives/element-component.directive';
 import { CheckboxComponent } from 'common/components/input-elements/checkbox.component';
@@ -12,8 +11,8 @@ export class CheckboxElement extends InputElement implements PositionedUIElement
 
   constructor(element: Partial<CheckboxElement>) {
     super({ width: 215, ...element });
-    this.position = ElementFactory.initPositionProps(element.position);
-    this.styling = ElementFactory.initStylingProps(element.styling);
+    this.position = UIElement.initPositionProps(element.position);
+    this.styling = UIElement.initStylingProps(element.styling);
   }
 
   hasAnswerScheme(): boolean {
diff --git a/projects/common/models/elements/input-elements/drop-list.ts b/projects/common/models/elements/input-elements/drop-list.ts
index b13f3a681..3616dc45d 100644
--- a/projects/common/models/elements/input-elements/drop-list.ts
+++ b/projects/common/models/elements/input-elements/drop-list.ts
@@ -1,10 +1,9 @@
 import { Type } from '@angular/core';
-import { ElementFactory } from 'common/util/element.factory';
 import {
   InputElement, PositionedUIElement,
   DragNDropValueObject,
   BasicStyles, PositionProperties,
-  AnswerScheme, AnswerSchemeValue
+  AnswerScheme, AnswerSchemeValue, UIElement
 } from 'common/models/elements/element';
 import { ElementComponent } from 'common/directives/element-component.directive';
 import { DropListComponent } from 'common/components/input-elements/drop-list.component';
@@ -36,9 +35,9 @@ export class DropListElement extends InputElement implements PositionedUIElement
     if (element.highlightReceivingDropListColor) {
       this.highlightReceivingDropListColor = element.highlightReceivingDropListColor;
     }
-    this.position = ElementFactory.initPositionProps({ useMinHeight: true, ...element.position });
+    this.position = UIElement.initPositionProps({ useMinHeight: true, ...element.position });
     this.styling = {
-      ...ElementFactory.initStylingProps({
+      ...UIElement.initStylingProps({
         backgroundColor: '#f4f4f2',
         itemBackgroundColor: '#c9e0e0',
         ...element.styling
diff --git a/projects/common/models/elements/input-elements/dropdown.ts b/projects/common/models/elements/input-elements/dropdown.ts
index 8057cbb82..a9ee3d3ed 100644
--- a/projects/common/models/elements/input-elements/dropdown.ts
+++ b/projects/common/models/elements/input-elements/dropdown.ts
@@ -1,8 +1,7 @@
 import { Type } from '@angular/core';
-import { ElementFactory } from 'common/util/element.factory';
 import {
   BasicStyles, InputElement, TextLabel, PositionedUIElement, PositionProperties, OptionElement,
-  AnswerScheme, AnswerSchemeValue
+  AnswerScheme, AnswerSchemeValue, UIElement
 } from 'common/models/elements/element';
 import { ElementComponent } from 'common/directives/element-component.directive';
 import { DropdownComponent } from 'common/components/input-elements/dropdown.component';
@@ -17,9 +16,9 @@ export class DropdownElement extends InputElement implements PositionedUIElement
     super({ width: 240, height: 83, ...element });
     if (element.options) this.options = [...element.options];
     if (element.allowUnset) this.allowUnset = element.allowUnset;
-    this.position = ElementFactory.initPositionProps(element.position);
+    this.position = UIElement.initPositionProps(element.position);
     this.styling = {
-      ...ElementFactory.initStylingProps(element.styling)
+      ...UIElement.initStylingProps(element.styling)
     };
   }
 
@@ -49,6 +48,6 @@ export class DropdownElement extends InputElement implements PositionedUIElement
   }
 
   getNewOptionLabel(optionText: string): TextLabel {
-    return ElementFactory.createOptionLabel(optionText) as TextLabel;
+    return UIElement.createOptionLabel(optionText) as TextLabel;
   }
 }
diff --git a/projects/common/models/elements/input-elements/radio-button-group-complex.ts b/projects/common/models/elements/input-elements/radio-button-group-complex.ts
index 806902b5d..4cbba18d2 100644
--- a/projects/common/models/elements/input-elements/radio-button-group-complex.ts
+++ b/projects/common/models/elements/input-elements/radio-button-group-complex.ts
@@ -1,9 +1,8 @@
 import { Type } from '@angular/core';
-import { ElementFactory } from 'common/util/element.factory';
 import {
   BasicStyles, InputElement, OptionElement,
   PositionedUIElement, PositionProperties, TextImageLabel,
-  AnswerScheme, AnswerSchemeValue
+  AnswerScheme, AnswerSchemeValue, UIElement
 } from 'common/models/elements/element';
 import { ElementComponent } from 'common/directives/element-component.directive';
 import { RadioGroupImagesComponent } from 'common/components/input-elements/radio-group-images.component';
@@ -18,9 +17,9 @@ export class RadioButtonGroupComplexElement extends InputElement implements Posi
     super({ height: 100, ...element });
     if (element.options) this.options = [...element.options];
     this.itemsPerRow = element.itemsPerRow !== undefined ? element.itemsPerRow : null;
-    this.position = ElementFactory.initPositionProps({ marginBottom: 40, ...element.position });
+    this.position = UIElement.initPositionProps({ marginBottom: 40, ...element.position });
     this.styling = {
-      ...ElementFactory.initStylingProps({ backgroundColor: 'transparent', ...element.styling })
+      ...UIElement.initStylingProps({ backgroundColor: 'transparent', ...element.styling })
     };
   }
 
@@ -50,6 +49,6 @@ export class RadioButtonGroupComplexElement extends InputElement implements Posi
   }
 
   getNewOptionLabel(optionText: string): TextImageLabel {
-    return ElementFactory.createOptionLabel(optionText, true) as TextImageLabel;
+    return UIElement.createOptionLabel(optionText, true) as TextImageLabel;
   }
 }
diff --git a/projects/common/models/elements/input-elements/radio-button-group.ts b/projects/common/models/elements/input-elements/radio-button-group.ts
index 5e60f9171..61e4ec934 100644
--- a/projects/common/models/elements/input-elements/radio-button-group.ts
+++ b/projects/common/models/elements/input-elements/radio-button-group.ts
@@ -1,8 +1,7 @@
 import { Type } from '@angular/core';
-import { ElementFactory } from 'common/util/element.factory';
 import {
   BasicStyles, InputElement, TextLabel, PositionedUIElement, PositionProperties, OptionElement,
-  AnswerScheme, AnswerSchemeValue
+  AnswerScheme, AnswerSchemeValue, UIElement
 } from 'common/models/elements/element';
 import { ElementComponent } from 'common/directives/element-component.directive';
 import { RadioButtonGroupComponent } from 'common/components/input-elements/radio-button-group.component';
@@ -21,9 +20,9 @@ export class RadioButtonGroupElement extends InputElement implements PositionedU
     if (element.options) this.options = [...element.options];
     if (element.alignment) this.alignment = element.alignment;
     if (element.strikeOtherOptions) this.strikeOtherOptions = element.strikeOtherOptions;
-    this.position = ElementFactory.initPositionProps({ marginBottom: 30, ...element.position });
+    this.position = UIElement.initPositionProps({ marginBottom: 30, ...element.position });
     this.styling = {
-      ...ElementFactory.initStylingProps({
+      ...UIElement.initStylingProps({
         backgroundColor: 'transparent',
         lineHeight: 135,
         ...element.styling
@@ -57,6 +56,6 @@ export class RadioButtonGroupElement extends InputElement implements PositionedU
   }
 
   getNewOptionLabel(optionText: string): TextLabel {
-    return ElementFactory.createOptionLabel(optionText) as TextLabel;
+    return UIElement.createOptionLabel(optionText) as TextLabel;
   }
 }
diff --git a/projects/common/models/elements/input-elements/slider.ts b/projects/common/models/elements/input-elements/slider.ts
index cd4f4a958..df5e4fe53 100644
--- a/projects/common/models/elements/input-elements/slider.ts
+++ b/projects/common/models/elements/input-elements/slider.ts
@@ -1,7 +1,6 @@
 import { Type } from '@angular/core';
-import { ElementFactory } from 'common/util/element.factory';
 import {
-  BasicStyles, InputElement, PositionedUIElement, PositionProperties, AnswerScheme, AnswerSchemeValue
+  BasicStyles, InputElement, PositionedUIElement, PositionProperties, AnswerScheme, AnswerSchemeValue, UIElement
 } from 'common/models/elements/element';
 import { ElementComponent } from 'common/directives/element-component.directive';
 import { SliderComponent } from 'common/components/input-elements/slider.component';
@@ -24,9 +23,9 @@ export class SliderElement extends InputElement implements PositionedUIElement {
     if (element.showValues !== undefined) this.showValues = element.showValues;
     if (element.barStyle) this.barStyle = element.barStyle;
     if (element.thumbLabel) this.thumbLabel = element.thumbLabel;
-    this.position = ElementFactory.initPositionProps(element.position);
+    this.position = UIElement.initPositionProps(element.position);
     this.styling = {
-      ...ElementFactory.initStylingProps({
+      ...UIElement.initStylingProps({
         backgroundColor: 'transparent',
         lineHeight: 135,
         ...element.styling
diff --git a/projects/common/models/elements/input-elements/spell-correct.ts b/projects/common/models/elements/input-elements/spell-correct.ts
index 43b9e37f6..25db1a751 100644
--- a/projects/common/models/elements/input-elements/spell-correct.ts
+++ b/projects/common/models/elements/input-elements/spell-correct.ts
@@ -1,11 +1,10 @@
 import { Type } from '@angular/core';
-import { ElementFactory } from 'common/util/element.factory';
 import {
   BasicStyles,
   InputAssistancePreset,
   InputElement,
   PositionedUIElement,
-  PositionProperties, AnswerScheme
+  PositionProperties, AnswerScheme, UIElement
 } from 'common/models/elements/element';
 import { ElementComponent } from 'common/directives/element-component.directive';
 import { SpellCorrectComponent } from 'common/components/input-elements/spell-correct.component';
@@ -28,9 +27,9 @@ export class SpellCorrectElement extends InputElement implements PositionedUIEle
     }
     if (element.showSoftwareKeyboard) this.showSoftwareKeyboard = element.showSoftwareKeyboard;
     if (element.softwareKeyboardShowFrench) this.softwareKeyboardShowFrench = element.softwareKeyboardShowFrench;
-    this.position = ElementFactory.initPositionProps(element.position);
+    this.position = UIElement.initPositionProps(element.position);
     this.styling = {
-      ...ElementFactory.initStylingProps({ backgroundColor: 'transparent', ...element.styling })
+      ...UIElement.initStylingProps({ backgroundColor: 'transparent', ...element.styling })
     };
   }
 
diff --git a/projects/common/models/elements/input-elements/text-area.ts b/projects/common/models/elements/input-elements/text-area.ts
index 719d50869..8ecafab0a 100644
--- a/projects/common/models/elements/input-elements/text-area.ts
+++ b/projects/common/models/elements/input-elements/text-area.ts
@@ -1,11 +1,10 @@
 import { Type } from '@angular/core';
-import { ElementFactory } from 'common/util/element.factory';
 import {
   BasicStyles,
   InputAssistancePreset,
   InputElement,
   PositionedUIElement,
-  PositionProperties, AnswerScheme
+  PositionProperties, AnswerScheme, UIElement
 } from 'common/models/elements/element';
 import { ElementComponent } from 'common/directives/element-component.directive';
 import { TextAreaComponent } from 'common/components/input-elements/text-area.component';
@@ -36,9 +35,9 @@ export class TextAreaElement extends InputElement implements PositionedUIElement
     }
     if (element.showSoftwareKeyboard) this.showSoftwareKeyboard = element.showSoftwareKeyboard;
     if (element.softwareKeyboardShowFrench) this.softwareKeyboardShowFrench = element.softwareKeyboardShowFrench;
-    this.position = ElementFactory.initPositionProps(element.position);
+    this.position = UIElement.initPositionProps(element.position);
     this.styling = {
-      ...ElementFactory.initStylingProps({
+      ...UIElement.initStylingProps({
         backgroundColor: 'transparent',
         lineHeight: 135,
         ...element.styling
diff --git a/projects/common/models/elements/input-elements/text-field.ts b/projects/common/models/elements/input-elements/text-field.ts
index 5c0b90c3f..69639bb64 100644
--- a/projects/common/models/elements/input-elements/text-field.ts
+++ b/projects/common/models/elements/input-elements/text-field.ts
@@ -1,8 +1,7 @@
 import { Type } from '@angular/core';
-import { ElementFactory } from 'common/util/element.factory';
 import {
   BasicStyles, InputAssistancePreset, InputElement,
-  PositionedUIElement, PositionProperties, AnswerScheme
+  PositionedUIElement, PositionProperties, AnswerScheme, UIElement
 } from 'common/models/elements/element';
 import { ElementComponent } from 'common/directives/element-component.directive';
 import { TextFieldComponent } from 'common/components/input-elements/text-field.component';
@@ -43,9 +42,9 @@ export class TextFieldElement extends InputElement implements PositionedUIElemen
     if (element.showSoftwareKeyboard) this.showSoftwareKeyboard = element.showSoftwareKeyboard;
     if (element.softwareKeyboardShowFrench) this.softwareKeyboardShowFrench = element.softwareKeyboardShowFrench;
     if (element.clearable) this.clearable = element.clearable;
-    this.position = ElementFactory.initPositionProps(element.position);
+    this.position = UIElement.initPositionProps(element.position);
     this.styling = {
-      ...ElementFactory.initStylingProps({
+      ...UIElement.initStylingProps({
         backgroundColor: 'transparent',
         lineHeight: 135,
         ...element.styling
diff --git a/projects/common/models/elements/media-elements/audio.ts b/projects/common/models/elements/media-elements/audio.ts
index 6bd983cfd..21a9e10a0 100644
--- a/projects/common/models/elements/media-elements/audio.ts
+++ b/projects/common/models/elements/media-elements/audio.ts
@@ -1,6 +1,5 @@
 import { Type } from '@angular/core';
-import { ElementFactory } from 'common/util/element.factory';
-import { PlayerElement, PositionedUIElement, PositionProperties } from 'common/models/elements/element';
+import { PlayerElement, PositionedUIElement, PositionProperties, UIElement } from 'common/models/elements/element';
 import { ElementComponent } from 'common/directives/element-component.directive';
 import { AudioComponent } from 'common/components/media-elements/audio.component';
 
@@ -11,7 +10,7 @@ export class AudioElement extends PlayerElement implements PositionedUIElement {
   constructor(element: Partial<AudioElement>) {
     super({ width: 250, height: 90, ...element });
     if (element.src) this.src = element.src;
-    this.position = ElementFactory.initPositionProps(element.position);
+    this.position = UIElement.initPositionProps(element.position);
   }
 
   getElementComponent(): Type<ElementComponent> {
diff --git a/projects/common/models/elements/media-elements/image.ts b/projects/common/models/elements/media-elements/image.ts
index 8f7ec9c1c..716990871 100644
--- a/projects/common/models/elements/media-elements/image.ts
+++ b/projects/common/models/elements/media-elements/image.ts
@@ -1,6 +1,7 @@
 import { Type } from '@angular/core';
-import { ElementFactory } from 'common/util/element.factory';
-import { PositionedUIElement, PositionProperties, AnswerScheme, UIElement } from 'common/models/elements/element';
+import {
+  PositionedUIElement, PositionProperties, AnswerScheme, UIElement
+} from 'common/models/elements/element';
 import { ElementComponent } from 'common/directives/element-component.directive';
 import { ImageComponent } from 'common/components/media-elements/image.component';
 
@@ -21,7 +22,7 @@ export class ImageElement extends UIElement implements PositionedUIElement {
     if (element.magnifierSize) this.magnifierSize = element.magnifierSize;
     if (element.magnifierZoom) this.magnifierZoom = element.magnifierZoom;
     if (element.magnifierUsed) this.magnifierUsed = element.magnifierUsed;
-    this.position = ElementFactory.initPositionProps(element.position);
+    this.position = UIElement.initPositionProps(element.position);
   }
 
   getElementComponent(): Type<ElementComponent> {
diff --git a/projects/common/models/elements/media-elements/video.ts b/projects/common/models/elements/media-elements/video.ts
index ca2287a75..0396c790d 100644
--- a/projects/common/models/elements/media-elements/video.ts
+++ b/projects/common/models/elements/media-elements/video.ts
@@ -1,6 +1,7 @@
 import { Type } from '@angular/core';
-import { ElementFactory } from 'common/util/element.factory';
-import { PlayerElement, PositionedUIElement, PositionProperties } from 'common/models/elements/element';
+import {
+  PlayerElement, PositionedUIElement, PositionProperties, UIElement
+} from 'common/models/elements/element';
 import { ElementComponent } from 'common/directives/element-component.directive';
 import { VideoComponent } from 'common/components/media-elements/video.component';
 
@@ -13,7 +14,7 @@ export class VideoElement extends PlayerElement implements PositionedUIElement {
     super({ width: 280, height: 230, ...element });
     if (element.src) this.src = element.src;
     if (element.scale) this.scale = element.scale;
-    this.position = ElementFactory.initPositionProps(element.position);
+    this.position = UIElement.initPositionProps(element.position);
   }
 
   getElementComponent(): Type<ElementComponent> {
diff --git a/projects/common/models/elements/text/text.ts b/projects/common/models/elements/text/text.ts
index d7ab69b90..9a1bccf11 100644
--- a/projects/common/models/elements/text/text.ts
+++ b/projects/common/models/elements/text/text.ts
@@ -1,5 +1,4 @@
 import { Type } from '@angular/core';
-import { ElementFactory } from 'common/util/element.factory';
 import {
   BasicStyles, PositionedUIElement,
   PositionProperties, AnswerScheme, UIElement
@@ -27,9 +26,9 @@ export class TextElement extends UIElement implements PositionedUIElement {
     if (element.highlightableYellow) this.highlightableYellow = element.highlightableYellow;
     if (element.hasSelectionPopup !== undefined) this.hasSelectionPopup = element.hasSelectionPopup;
     if (element.columnCount) this.columnCount = element.columnCount;
-    this.position = ElementFactory.initPositionProps(element.position);
+    this.position = UIElement.initPositionProps(element.position);
     this.styling = {
-      ...ElementFactory.initStylingProps({
+      ...UIElement.initStylingProps({
         backgroundColor: 'transparent',
         lineHeight: element.styling?.lineHeight || 135,
         ...element.styling
diff --git a/projects/common/models/section.ts b/projects/common/models/section.ts
index 12825d386..a50f7f180 100644
--- a/projects/common/models/section.ts
+++ b/projects/common/models/section.ts
@@ -30,7 +30,7 @@ export class Section {
       section?.elements?.map(element => (
         ElementFactory.createElement({
           ...element,
-          position: ElementFactory.initPositionProps(element.position)
+          position: UIElement.initPositionProps(element.position)
         }) as PositionedUIElement)
       ) || [];
   }
diff --git a/projects/common/util/element.factory.ts b/projects/common/util/element.factory.ts
index ea4323e79..b28000709 100644
--- a/projects/common/util/element.factory.ts
+++ b/projects/common/util/element.factory.ts
@@ -1,6 +1,4 @@
-import {
-  BasicStyles, PlayerProperties, PositionProperties, UIElement
-} from 'common/models/elements/element';
+import { UIElement } from 'common/models/elements/element';
 import { Type } from '@angular/core';
 import { TextElement } from 'common/models/elements/text/text';
 import { ButtonElement } from 'common/models/elements/button/button';
@@ -56,73 +54,4 @@ export abstract class ElementFactory {
   static createElement(element: { type: string } & Partial<UIElement>): UIElement {
     return new ElementFactory.ELEMENT_CLASSES[element.type](element);
   }
-
-  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 initPlayerProps(defaults: Partial<PlayerProperties> = {}): PlayerProperties {
-    return {
-      autostart: defaults.autostart !== undefined ? defaults.autostart as boolean : false,
-      autostartDelay: defaults.autostartDelay !== undefined ? defaults.autostartDelay as number : 0,
-      loop: defaults.loop !== undefined ? defaults.loop as boolean : false,
-      startControl: defaults.startControl !== undefined ? defaults.startControl as boolean : true,
-      pauseControl: defaults.pauseControl !== undefined ? defaults.pauseControl as boolean : false,
-      progressBar: defaults.progressBar !== undefined ? defaults.progressBar as boolean : true,
-      interactiveProgressbar: defaults.interactiveProgressbar !== undefined ?
-        defaults.interactiveProgressbar as boolean :
-        false,
-      volumeControl: defaults.volumeControl !== undefined ? defaults.volumeControl as boolean : true,
-      defaultVolume: defaults.defaultVolume !== undefined ? defaults.defaultVolume as number : 0.8,
-      minVolume: defaults.minVolume !== undefined ? defaults.minVolume as number : 0,
-      muteControl: defaults.muteControl !== undefined ? defaults.muteControl as boolean : true,
-      interactiveMuteControl: defaults.interactiveMuteControl !== undefined ?
-        defaults.interactiveMuteControl as boolean :
-        false,
-      hintLabel: defaults.hintLabel !== undefined ? defaults.hintLabel as string : '',
-      hintLabelDelay: defaults.hintLabelDelay !== undefined ? defaults.hintLabelDelay as number : 0,
-      activeAfterID: defaults.activeAfterID !== undefined ? defaults.activeAfterID as string : '',
-      minRuns: defaults.minRuns !== undefined ? defaults.minRuns as number : 1,
-      maxRuns: defaults.maxRuns !== undefined ? defaults.maxRuns as number | null : null,
-      showRestRuns: defaults.showRestRuns !== undefined ? defaults.showRestRuns as boolean : false,
-      showRestTime: defaults.showRestTime !== undefined ? defaults.showRestTime as boolean : true,
-      playbackTime: defaults.playbackTime !== undefined ? defaults.playbackTime as number : 0
-    };
-  }
-
-  static createOptionLabel(optionText: string, addImg: boolean = false) {
-    return {
-      text: optionText,
-      imgSrc: addImg ? null : undefined,
-      imgPosition: addImg ? 'above' : undefined
-    };
-  }
 }
-- 
GitLab