From 874c1af3b3a6fbdc36605fcc832d04ecccde65ef Mon Sep 17 00:00:00 2001
From: rhenck <richard.henck@iqb.hu-berlin.de>
Date: Wed, 2 Mar 2022 12:01:07 +0100
Subject: [PATCH] Refactor unit definition and sanatizer

- Units and element are now built via the factory. This ensures only the
  wanted properties are present. All others are discarded.
- Since the sanatizer is supposed to check the unit defintion version
  it is used by player and editor and therefore put in common.
  This in turn makes it necessary to put the JSON resolver settings
  in the root-TSConfig file.
- Renamed a couple of properties to have clearer names.
---
 package.json                                  |   2 +-
 .../components/ui-elements/audio.component.ts |   2 +-
 .../ui-elements/button.component.ts           |  20 +-
 .../ui-elements/checkbox.component.ts         |  14 +-
 .../components/ui-elements/cloze.component.ts | 130 ++---
 .../ui-elements/drop-list-simple.component.ts |  41 +-
 .../ui-elements/drop-list.component.ts        |  61 +-
 .../ui-elements/dropdown.component.ts         |  20 +-
 .../components/ui-elements/frame.component.ts |  14 +-
 .../ui-elements/likert.component.ts           |  38 +-
 .../radio-button-group.component.ts           |  16 +-
 .../radio-group-images.component.ts           |  14 +-
 .../ui-elements/slider.component.ts           |  77 ++-
 .../ui-elements/spell-correct.component.ts    |  49 +-
 .../ui-elements/text-area.component.ts        |  16 +-
 .../text-field-simple.component.ts            |  14 +-
 .../ui-elements/text-field.component.ts       |  45 +-
 .../components/ui-elements/text.component.ts  |  48 +-
 .../ui-elements/toggle-button.component.ts    |  16 +-
 .../components/ui-elements/video.component.ts |   2 +-
 projects/common/interfaces/elements.ts        |  90 +--
 projects/common/services/message.service.ts   |  10 +-
 .../tiptap-editor-extensions/drop-list.ts     |   2 +-
 .../tiptap-editor-extensions/text-field.ts    |   2 +-
 .../tiptap-editor-extensions/toggle-button.ts |   2 +-
 projects/common/util/element.factory.ts       | 524 +++++++++---------
 .../common/util/unit-definition-sanitizer.ts  | 362 ++++++------
 projects/common/util/unit.factory.ts          |  41 +-
 .../page-view/canvas/canvas.component.ts      |   4 +-
 .../dynamic-canvas-overlay.component.ts       |  74 +--
 .../static-canvas-overlay.component.ts        |   6 +-
 .../canvas/section-dynamic.component.ts       |  92 +--
 .../element-properties-panel.component.html   |   8 +-
 .../element-model-properties.component.html   |   2 +-
 .../element-style-properties.component.ts     |   4 +-
 .../unit-view/unit-view.component.ts          |   2 +-
 .../editor/src/app/services/unit.service.ts   |  58 +-
 .../drop-list-component-extension.ts          |   2 +-
 .../text-field-component-extension.ts         |   2 +-
 .../toggle-button-component-extension.ts      |   2 +-
 projects/editor/src/app/util/cloze-parser.ts  |   6 +-
 projects/editor/tsconfig.app.json             |   4 +-
 projects/player/src/app/app.component.ts      |   5 +-
 .../element-media-player-group.component.ts   |  10 +-
 .../element-splitter.component.html           |   9 +-
 .../components/section/section.component.html |  26 +-
 .../unit-state-element-mapper.service.ts      |   4 +-
 tsconfig.json                                 |   2 +
 48 files changed, 1035 insertions(+), 959 deletions(-)

diff --git a/package.json b/package.json
index 82b9a6d59..8f9e2000f 100644
--- a/package.json
+++ b/package.json
@@ -3,7 +3,7 @@
   "config": {
     "player_version": "1.20.1",
     "editor_version": "1.26.1",
-    "unit_definition_version": "1.2.0"
+    "unit_definition_version": "2.0.0"
   },
   "scripts": {
     "ng": "ng",
diff --git a/projects/common/components/ui-elements/audio.component.ts b/projects/common/components/ui-elements/audio.component.ts
index c39789d5a..77db4b009 100644
--- a/projects/common/components/ui-elements/audio.component.ts
+++ b/projects/common/components/ui-elements/audio.component.ts
@@ -17,7 +17,7 @@ import { AudioElement } from '../../interfaces/elements';
                           [project]="project"
                           [id]="elementModel.id"
                           [savedPlaybackTime]="savedPlaybackTime"
-                          [playerProperties]="elementModel.playerProps"
+                          [playerProperties]="elementModel.player"
                           [active]="active"
                           [dependencyDissolved]="dependencyDissolved"
                           (onMediaValidStatusChanged)="onMediaValidStatusChanged.emit($event)"
diff --git a/projects/common/components/ui-elements/button.component.ts b/projects/common/components/ui-elements/button.component.ts
index 6102e11f3..e4d8bf31a 100644
--- a/projects/common/components/ui-elements/button.component.ts
+++ b/projects/common/components/ui-elements/button.component.ts
@@ -11,14 +11,14 @@ import { ButtonElement } from '../../interfaces/elements';
             type='button'
             [style.width.%]="100"
             [style.height.%]="100"
-            [style.background-color]="elementModel.styles.backgroundColor"
-            [style.color]="elementModel.styles.fontColor"
-            [style.font-family]="elementModel.styles.font"
-            [style.font-size.px]="elementModel.styles.fontSize"
-            [style.font-weight]="elementModel.styles.bold ? 'bold' : ''"
-            [style.font-style]="elementModel.styles.italic ? 'italic' : ''"
-            [style.text-decoration]="elementModel.styles.underline ? 'underline' : ''"
-            [style.border-radius.px]="elementModel.styles.borderRadius"
+            [style.background-color]="elementModel.styling.backgroundColor"
+            [style.color]="elementModel.styling.fontColor"
+            [style.font-family]="elementModel.styling.font"
+            [style.font-size.px]="elementModel.styling.fontSize"
+            [style.font-weight]="elementModel.styling.bold ? 'bold' : ''"
+            [style.font-style]="elementModel.styling.italic ? 'italic' : ''"
+            [style.text-decoration]="elementModel.styling.underline ? 'underline' : ''"
+            [style.border-radius.px]="elementModel.styling.borderRadius"
             (click)="elementModel.action && elementModel.actionParam !== null ?
                navigateTo.emit({
                   action: elementModel.action,
@@ -30,8 +30,8 @@ import { ButtonElement } from '../../interfaces/elements';
     <input
         *ngIf="elementModel.imageSrc" type="image"
         [src]="elementModel.imageSrc | safeResourceUrl"
-        [class]="elementModel.positionProps.dynamicPositioning &&
-                    !elementModel.positionProps.fixedSize ? 'dynamic-image' : 'static-image'"
+        [class]="elementModel.position.dynamicPositioning &&
+                    !elementModel.position.fixedSize ? 'dynamic-image' : 'static-image'"
         [alt]="'imageNotFound' | translate"
         (click)="elementModel.action && elementModel.actionParam !== null?
            navigateTo.emit({
diff --git a/projects/common/components/ui-elements/checkbox.component.ts b/projects/common/components/ui-elements/checkbox.component.ts
index 791bb2faa..f67cdb20c 100644
--- a/projects/common/components/ui-elements/checkbox.component.ts
+++ b/projects/common/components/ui-elements/checkbox.component.ts
@@ -8,16 +8,16 @@ import { CheckboxElement } from '../../interfaces/elements';
     <div class="mat-form-field"
          [style.width.%]="100"
          [style.height.%]="100"
-         [style.background-color]="elementModel.styles.backgroundColor">
+         [style.background-color]="elementModel.styling.backgroundColor">
       <mat-checkbox #checkbox class="example-margin"
                     [formControl]="elementFormControl"
                     [checked]="$any(elementModel.value)"
-                    [style.color]="elementModel.styles.fontColor"
-                    [style.font-family]="elementModel.styles.font"
-                    [style.font-size.px]="elementModel.styles.fontSize"
-                    [style.font-weight]="elementModel.styles.bold ? 'bold' : ''"
-                    [style.font-style]="elementModel.styles.italic ? 'italic' : ''"
-                    [style.text-decoration]="elementModel.styles.underline ? 'underline' : ''"
+                    [style.color]="elementModel.styling.fontColor"
+                    [style.font-family]="elementModel.styling.font"
+                    [style.font-size.px]="elementModel.styling.fontSize"
+                    [style.font-weight]="elementModel.styling.bold ? 'bold' : ''"
+                    [style.font-style]="elementModel.styling.italic ? 'italic' : ''"
+                    [style.text-decoration]="elementModel.styling.underline ? 'underline' : ''"
                     (click)="elementModel.readOnly ? $event.preventDefault() : null">
         <div [innerHTML]="elementModel.label"></div>
       </mat-checkbox>
diff --git a/projects/common/components/ui-elements/cloze.component.ts b/projects/common/components/ui-elements/cloze.component.ts
index 6133947e0..e1c0101dc 100644
--- a/projects/common/components/ui-elements/cloze.component.ts
+++ b/projects/common/components/ui-elements/cloze.component.ts
@@ -48,93 +48,93 @@ import { ClozeUtils } from '../../util/cloze';
 
     <ng-template #paragraphs let-part>
       <p *ngIf="part.type === 'paragraph'"
-         [style.line-height.%]="elementModel.styles.lineHeight"
-         [style.color]="elementModel.styles.fontColor"
-         [style.font-family]="elementModel.styles.font"
-         [style.font-size.px]="elementModel.styles.fontSize"
-         [style.font-weight]="elementModel.styles.bold ? 'bold' : ''"
-         [style.font-style]="elementModel.styles.italic ? 'italic' : ''"
-         [style.text-decoration]="elementModel.styles.underline ? 'underline' : ''"
+         [style.line-height.%]="elementModel.styling.lineHeight"
+         [style.color]="elementModel.styling.fontColor"
+         [style.font-family]="elementModel.styling.font"
+         [style.font-size.px]="elementModel.styling.fontSize"
+         [style.font-weight]="elementModel.styling.bold ? 'bold' : ''"
+         [style.font-style]="elementModel.styling.italic ? 'italic' : ''"
+         [style.text-decoration]="elementModel.styling.underline ? 'underline' : ''"
          [style.margin-bottom]="part.attrs?.margin + 'px'"
          [style.margin-left]="part.attrs?.hangingIndent ? '' :
-               ($any(part.attrs?.indentSize) * $any(part.attrs?.indent)) + 'px'"
+           ($any(part.attrs?.indentSize) * $any(part.attrs?.indent)) + 'px'"
          [style.text-align]="part.attrs?.textAlign"
          [style.text-indent]="part.attrs?.hangingIndent ?
-               ($any(part.attrs?.indentSize) * $any(part.attrs?.indent)) + 'px' : ''">
-        <ng-container [ngTemplateOutlet]="paragraphChildren"
-                      [ngTemplateOutletContext]="{ $implicit: part }"></ng-container>
+           ($any(part.attrs?.indentSize) * $any(part.attrs?.indent)) + 'px' : ''">
+          <ng-container [ngTemplateOutlet]="paragraphChildren"
+                        [ngTemplateOutletContext]="{ $implicit: part }"></ng-container>
       </p>
       <h1 *ngIf="part.type === 'heading' && part.attrs.level === 1"
           [style.display]="'inline'"
-          [style.line-height.%]="elementModel.styles.lineHeight"
-          [style.color]="elementModel.styles.fontColor"
-          [style.font-family]="elementModel.styles.font"
-          [style.font-size.px]="elementModel.styles.fontSize"
-          [style.font-weight]="elementModel.styles.bold ? 'bold' : ''"
-          [style.font-style]="elementModel.styles.italic ? 'italic' : ''"
-          [style.text-decoration]="elementModel.styles.underline ? 'underline' : ''">
-        <ng-container [ngTemplateOutlet]="paragraphChildren"
-                      [ngTemplateOutletContext]="{ $implicit: part }"></ng-container>
+          [style.line-height.%]="elementModel.styling.lineHeight"
+          [style.color]="elementModel.styling.fontColor"
+          [style.font-family]="elementModel.styling.font"
+          [style.font-size.px]="elementModel.styling.fontSize"
+          [style.font-weight]="elementModel.styling.bold ? 'bold' : ''"
+          [style.font-style]="elementModel.styling.italic ? 'italic' : ''"
+          [style.text-decoration]="elementModel.styling.underline ? 'underline' : ''">
+          <ng-container [ngTemplateOutlet]="paragraphChildren"
+                        [ngTemplateOutletContext]="{ $implicit: part }"></ng-container>
       </h1>
       <h2 *ngIf="part.type === 'heading' && part.attrs.level === 2"
           [style.display]="'inline'"
-          [style.line-height.%]="elementModel.styles.lineHeight"
-          [style.color]="elementModel.styles.fontColor"
-          [style.font-family]="elementModel.styles.font"
-          [style.font-size.px]="elementModel.styles.fontSize"
-          [style.font-weight]="elementModel.styles.bold ? 'bold' : ''"
-          [style.font-style]="elementModel.styles.italic ? 'italic' : ''"
-          [style.text-decoration]="elementModel.styles.underline ? 'underline' : ''">
-        <ng-container [ngTemplateOutlet]="paragraphChildren"
-                      [ngTemplateOutletContext]="{ $implicit: part }"></ng-container>
+          [style.line-height.%]="elementModel.styling.lineHeight"
+          [style.color]="elementModel.styling.fontColor"
+          [style.font-family]="elementModel.styling.font"
+          [style.font-size.px]="elementModel.styling.fontSize"
+          [style.font-weight]="elementModel.styling.bold ? 'bold' : ''"
+          [style.font-style]="elementModel.styling.italic ? 'italic' : ''"
+          [style.text-decoration]="elementModel.styling.underline ? 'underline' : ''">
+          <ng-container [ngTemplateOutlet]="paragraphChildren"
+                        [ngTemplateOutletContext]="{ $implicit: part }"></ng-container>
       </h2>
       <h3 *ngIf="part.type === 'heading' && part.attrs.level === 3"
           [style.display]="'inline'"
-          [style.line-height.%]="elementModel.styles.lineHeight"
-          [style.color]="elementModel.styles.fontColor"
-          [style.font-family]="elementModel.styles.font"
-          [style.font-size.px]="elementModel.styles.fontSize"
-          [style.font-weight]="elementModel.styles.bold ? 'bold' : ''"
-          [style.font-style]="elementModel.styles.italic ? 'italic' : ''"
-          [style.text-decoration]="elementModel.styles.underline ? 'underline' : ''">
-        <ng-container [ngTemplateOutlet]="paragraphChildren"
-                      [ngTemplateOutletContext]="{ $implicit: part }"></ng-container>
+          [style.line-height.%]="elementModel.styling.lineHeight"
+          [style.color]="elementModel.styling.fontColor"
+          [style.font-family]="elementModel.styling.font"
+          [style.font-size.px]="elementModel.styling.fontSize"
+          [style.font-weight]="elementModel.styling.bold ? 'bold' : ''"
+          [style.font-style]="elementModel.styling.italic ? 'italic' : ''"
+          [style.text-decoration]="elementModel.styling.underline ? 'underline' : ''">
+          <ng-container [ngTemplateOutlet]="paragraphChildren"
+                        [ngTemplateOutletContext]="{ $implicit: part }"></ng-container>
       </h3>
       <h4 *ngIf="part.type === 'heading' && part.attrs.level === 4"
           [style.display]="'inline'"
-          [style.line-height.%]="elementModel.styles.lineHeight"
-          [style.color]="elementModel.styles.fontColor"
-          [style.font-family]="elementModel.styles.font"
-          [style.font-size.px]="elementModel.styles.fontSize"
-          [style.font-weight]="elementModel.styles.bold ? 'bold' : ''"
-          [style.font-style]="elementModel.styles.italic ? 'italic' : ''"
-          [style.text-decoration]="elementModel.styles.underline ? 'underline' : ''">
-        <ng-container [ngTemplateOutlet]="paragraphChildren"
-                      [ngTemplateOutletContext]="{ $implicit: part }"></ng-container>
+          [style.line-height.%]="elementModel.styling.lineHeight"
+          [style.color]="elementModel.styling.fontColor"
+          [style.font-family]="elementModel.styling.font"
+          [style.font-size.px]="elementModel.styling.fontSize"
+          [style.font-weight]="elementModel.styling.bold ? 'bold' : ''"
+          [style.font-style]="elementModel.styling.italic ? 'italic' : ''"
+          [style.text-decoration]="elementModel.styling.underline ? 'underline' : ''">
+          <ng-container [ngTemplateOutlet]="paragraphChildren"
+                        [ngTemplateOutletContext]="{ $implicit: part }"></ng-container>
       </h4>
       <h5 *ngIf="part.type === 'heading' && part.attrs.level === 5"
           [style.display]="'inline'"
-          [style.line-height.%]="elementModel.styles.lineHeight"
-          [style.color]="elementModel.styles.fontColor"
-          [style.font-family]="elementModel.styles.font"
-          [style.font-size.px]="elementModel.styles.fontSize"
-          [style.font-weight]="elementModel.styles.bold ? 'bold' : ''"
-          [style.font-style]="elementModel.styles.italic ? 'italic' : ''"
-          [style.text-decoration]="elementModel.styles.underline ? 'underline' : ''">
-        <ng-container [ngTemplateOutlet]="paragraphChildren"
-                      [ngTemplateOutletContext]="{ $implicit: part }"></ng-container>
+          [style.line-height.%]="elementModel.styling.lineHeight"
+          [style.color]="elementModel.styling.fontColor"
+          [style.font-family]="elementModel.styling.font"
+          [style.font-size.px]="elementModel.styling.fontSize"
+          [style.font-weight]="elementModel.styling.bold ? 'bold' : ''"
+          [style.font-style]="elementModel.styling.italic ? 'italic' : ''"
+          [style.text-decoration]="elementModel.styling.underline ? 'underline' : ''">
+          <ng-container [ngTemplateOutlet]="paragraphChildren"
+                        [ngTemplateOutletContext]="{ $implicit: part }"></ng-container>
       </h5>
       <h6 *ngIf="part.type === 'heading' && part.attrs.level === 6"
           [style.display]="'inline'"
-          [style.line-height.%]="elementModel.styles.lineHeight"
-          [style.color]="elementModel.styles.fontColor"
-          [style.font-family]="elementModel.styles.font"
-          [style.font-size.px]="elementModel.styles.fontSize"
-          [style.font-weight]="elementModel.styles.bold ? 'bold' : ''"
-          [style.font-style]="elementModel.styles.italic ? 'italic' : ''"
-          [style.text-decoration]="elementModel.styles.underline ? 'underline' : ''">
-        <ng-container [ngTemplateOutlet]="paragraphChildren"
-                      [ngTemplateOutletContext]="{ $implicit: part }"></ng-container>
+          [style.line-height.%]="elementModel.styling.lineHeight"
+          [style.color]="elementModel.styling.fontColor"
+          [style.font-family]="elementModel.styling.font"
+          [style.font-size.px]="elementModel.styling.fontSize"
+          [style.font-weight]="elementModel.styling.bold ? 'bold' : ''"
+          [style.font-style]="elementModel.styling.italic ? 'italic' : ''"
+          [style.text-decoration]="elementModel.styling.underline ? 'underline' : ''">
+          <ng-container [ngTemplateOutlet]="paragraphChildren"
+                        [ngTemplateOutletContext]="{ $implicit: part }"></ng-container>
       </h6>
     </ng-template>
 
diff --git a/projects/common/components/ui-elements/drop-list-simple.component.ts b/projects/common/components/ui-elements/drop-list-simple.component.ts
index fb84d43ba..195351c1f 100644
--- a/projects/common/components/ui-elements/drop-list-simple.component.ts
+++ b/projects/common/components/ui-elements/drop-list-simple.component.ts
@@ -10,21 +10,21 @@ import { DragNDropValueObject, DropListSimpleElement } from '../../interfaces/el
   selector: 'aspect-drop-list-simple',
   template: `
     <div class="list-container">
-      <!-- Border width is a workaround to enable/disable the Material cdk-drop-list-receiving-->
-      <!-- class style.-->
+        <!-- Border width is a workaround to enable/disable the Material cdk-drop-list-receiving-->
+        <!-- class style.-->
       <div class="list"
            [style.height.px]="elementModel.height"
            [style.width.px]="elementModel.width"
            [class.dropList-highlight]="elementModel.highlightReceivingDropList"
            [style.border-color]="elementModel.highlightReceivingDropListColor"
            [style.border-width.px]="elementModel.highlightReceivingDropList ? 2 : 0"
-           [style.color]="elementModel.styles.fontColor"
-           [style.font-family]="elementModel.styles.font"
-           [style.font-size.px]="elementModel.styles.fontSize"
-           [style.font-weight]="elementModel.styles.bold ? 'bold' : ''"
-           [style.font-style]="elementModel.styles.italic ? 'italic' : ''"
-           [style.text-decoration]="elementModel.styles.underline ? 'underline' : ''"
-           [style.backgroundColor]="elementModel.styles.backgroundColor"
+           [style.color]="elementModel.styling.fontColor"
+           [style.font-family]="elementModel.styling.font"
+           [style.font-size.px]="elementModel.styling.fontSize"
+           [style.font-weight]="elementModel.styling.bold ? 'bold' : ''"
+           [style.font-style]="elementModel.styling.italic ? 'italic' : ''"
+           [style.text-decoration]="elementModel.styling.underline ? 'underline' : ''"
+           [style.backgroundColor]="elementModel.styling.backgroundColor"
            cdkDropList
            [id]="elementModel.id"
            [cdkDropListData]="this"
@@ -32,36 +32,37 @@ import { DragNDropValueObject, DropListSimpleElement } from '../../interfaces/el
            [cdkDropListEnterPredicate]="onlyOneItemPredicate"
            (cdkDropListDropped)="drop($event)">
         <ng-container *ngIf="!parentForm">
-          <ng-container *ngFor="let value of $any(elementModel.value)">
-            <ng-container [ngTemplateOutlet]="dropObject" [ngTemplateOutletContext]="{ $implicit: value }">
+            <ng-container *ngFor="let value of $any(elementModel.value)">
+                <ng-container [ngTemplateOutlet]="dropObject" [ngTemplateOutletContext]="{ $implicit: value }">
+                </ng-container>
             </ng-container>
-          </ng-container>
         </ng-container>
 
         <ng-container *ngIf="parentForm">
-          <ng-container *ngFor="let value of elementFormControl.value">
-            <ng-container [ngTemplateOutlet]="dropObject" [ngTemplateOutletContext]="{ $implicit: value }">
+            <ng-container *ngFor="let value of elementFormControl.value">
+                <ng-container [ngTemplateOutlet]="dropObject" [ngTemplateOutletContext]="{ $implicit: value }">
+                </ng-container>
             </ng-container>
-          </ng-container>
         </ng-container>
 
         <ng-template #dropObject let-value>
           <div class="item"
                [style.line-height.px]="elementModel.height - 4"
-               [style.background-color]="elementModel.styles.itemBackgroundColor"
+               [style.background-color]="elementModel.styling.itemBackgroundColor"
                cdkDrag (cdkDragStarted)=dragStart() (cdkDragEnded)="dragEnd()">
 
             <div *cdkDragPreview
-                 [style.font-size.px]="elementModel.styles.fontSize"
-                 [style.background-color]="elementModel.styles.itemBackgroundColor">
+                 [style.font-size.px]="elementModel.styling.fontSize"
+                 [style.background-color]="elementModel.styling.itemBackgroundColor">
               {{value.stringValue}}
             </div>
 
-            <div class="drag-placeholder" *cdkDragPlaceholder [style.min-height.px]="elementModel.styles.fontSize">
+            <div class="drag-placeholder" *cdkDragPlaceholder
+                 [style.min-height.px]="elementModel.styling.fontSize">
             </div>
             {{value.stringValue}}
           </div>
-         </ng-template>
+        </ng-template>
       </div>
       <mat-error *ngIf="elementFormControl.errors && elementFormControl.touched"
                  class="error-message">
diff --git a/projects/common/components/ui-elements/drop-list.component.ts b/projects/common/components/ui-elements/drop-list.component.ts
index 5df6e99c0..2f0bea40e 100644
--- a/projects/common/components/ui-elements/drop-list.component.ts
+++ b/projects/common/components/ui-elements/drop-list.component.ts
@@ -18,13 +18,13 @@ import { DragNDropValueObject, DropListElement } from '../../interfaces/elements
            [ngClass]="{ 'align-flex' : elementModel.orientation === 'flex' }"
            [class.dropList-highlight]="elementModel.highlightReceivingDropList"
            [style.outline-color]="elementModel.highlightReceivingDropListColor"
-           [style.color]="elementModel.styles.fontColor"
-           [style.font-family]="elementModel.styles.font"
-           [style.font-size.px]="elementModel.styles.fontSize"
-           [style.font-weight]="elementModel.styles.bold ? 'bold' : ''"
-           [style.font-style]="elementModel.styles.italic ? 'italic' : ''"
-           [style.text-decoration]="elementModel.styles.underline ? 'underline' : ''"
-           [style.backgroundColor]="elementModel.styles.backgroundColor"
+           [style.color]="elementModel.styling.fontColor"
+           [style.font-family]="elementModel.styling.font"
+           [style.font-size.px]="elementModel.styling.fontSize"
+           [style.font-weight]="elementModel.styling.bold ? 'bold' : ''"
+           [style.font-style]="elementModel.styling.italic ? 'italic' : ''"
+           [style.text-decoration]="elementModel.styling.underline ? 'underline' : ''"
+           [style.backgroundColor]="elementModel.styling.backgroundColor"
            [style.display]="elementModel.orientation === 'horizontal' ? 'flex' : ''"
            [style.flex-direction]="elementModel.orientation === 'horizontal' ? 'row' : ''"
            cdkDropList
@@ -48,31 +48,32 @@ import { DragNDropValueObject, DropListElement } from '../../interfaces/elements
             </ng-container>
           </ng-container>
         </ng-container>
-          <!--Leave template within the dom to ensure dragNdrop-->
-          <ng-template #dropObject let-value>
-            <div class="item text-item" *ngIf="!value.imgSrcValue" cdkDrag
-                 [ngClass]="{ 'vertical-orientation' : elementModel.orientation === 'vertical',
-                              'horizontal-orientation' : elementModel.orientation === 'horizontal'}"
-                 [style.background-color]="elementModel.itemBackgroundColor"
-                 (cdkDragStarted)=dragStart() (cdkDragEnded)="dragEnd()">
-              <div *cdkDragPreview
-                   [style.font-size.px]="elementModel.styles.fontSize"
-                   [style.background-color]="elementModel.styles.itemBackgroundColor">
+        <!--Leave template within the dom to ensure dragNdrop-->
+        <ng-template #dropObject let-value>
+          <div class="item text-item" *ngIf="!value.imgSrcValue" cdkDrag
+               [ngClass]="{ 'vertical-orientation' : elementModel.orientation === 'vertical',
+                      'horizontal-orientation' : elementModel.orientation === 'horizontal'}"
+               [style.background-color]="elementModel.itemBackgroundColor"
+               (cdkDragStarted)=dragStart() (cdkDragEnded)="dragEnd()">
+            <div *cdkDragPreview
+                 [style.font-size.px]="elementModel.styling.fontSize"
+                 [style.background-color]="elementModel.styling.itemBackgroundColor">
                 {{value.stringValue}}
-              </div>
-              <div class="drag-placeholder" *cdkDragPlaceholder [style.min-height.px]="elementModel.styles.fontSize">
-              </div>
-              {{value.stringValue}}
             </div>
-            <img *ngIf="value.imgSrcValue"
-                 [src]="value.imgSrcValue | safeResourceUrl" alt="Image Placeholder"
-                 [style.display]="elementModel.orientation === 'flex' ? '' : 'block'"
-                 class="item"
-                 [ngClass]="{ 'vertical-orientation' : elementModel.orientation === 'vertical',
-                              'horizontal-orientation' : elementModel.orientation === 'horizontal'}"
-                 cdkDrag (cdkDragStarted)=dragStart() (cdkDragEnded)="dragEnd()"
-                 [style.object-fit]="'scale-down'">
-          </ng-template>
+            <div class="drag-placeholder" *cdkDragPlaceholder
+                 [style.min-height.px]="elementModel.styling.fontSize">
+            </div>
+            {{value.stringValue}}
+          </div>
+          <img *ngIf="value.imgSrcValue"
+               [src]="value.imgSrcValue | safeResourceUrl" alt="Image Placeholder"
+               [style.display]="elementModel.orientation === 'flex' ? '' : 'block'"
+               class="item"
+               [ngClass]="{ 'vertical-orientation' : elementModel.orientation === 'vertical',
+                      'horizontal-orientation' : elementModel.orientation === 'horizontal'}"
+               cdkDrag (cdkDragStarted)=dragStart() (cdkDragEnded)="dragEnd()"
+               [style.object-fit]="'scale-down'">
+        </ng-template>
       </div>
       <mat-error *ngIf="elementFormControl.errors && elementFormControl.touched"
                  class="error-message">
diff --git a/projects/common/components/ui-elements/dropdown.component.ts b/projects/common/components/ui-elements/dropdown.component.ts
index 49db99cf1..e6118c65a 100644
--- a/projects/common/components/ui-elements/dropdown.component.ts
+++ b/projects/common/components/ui-elements/dropdown.component.ts
@@ -6,16 +6,16 @@ import { DropdownElement } from '../../interfaces/elements';
   selector: 'aspect-dropdown',
   template: `
     <mat-form-field
-        appearance="fill"
-        [style.width.%]="100"
-        [style.height.%]="100"
-        aspectInputBackgroundColor [backgroundColor]="elementModel.styles.backgroundColor">
-      <mat-label [style.color]="elementModel.styles.fontColor"
-                 [style.font-family]="elementModel.styles.font"
-                 [style.font-size.px]="elementModel.styles.fontSize"
-                 [style.font-weight]="elementModel.styles.bold ? 'bold' : ''"
-                 [style.font-style]="elementModel.styles.italic ? 'italic' : ''"
-                 [style.text-decoration]="elementModel.styles.underline ? 'underline' : ''">
+            appearance="fill"
+            [style.width.%]="100"
+            [style.height.%]="100"
+            aspectInputBackgroundColor [backgroundColor]="elementModel.styling.backgroundColor">
+      <mat-label [style.color]="elementModel.styling.fontColor"
+                 [style.font-family]="elementModel.styling.font"
+                 [style.font-size.px]="elementModel.styling.fontSize"
+                 [style.font-weight]="elementModel.styling.bold ? 'bold' : ''"
+                 [style.font-style]="elementModel.styling.italic ? 'italic' : ''"
+                 [style.text-decoration]="elementModel.styling.underline ? 'underline' : ''">
         {{$any(elementModel).label}}
       </mat-label>
       <mat-select [formControl]="elementFormControl" [value]="elementModel.value">
diff --git a/projects/common/components/ui-elements/frame.component.ts b/projects/common/components/ui-elements/frame.component.ts
index e3fc782a5..4cada7b07 100644
--- a/projects/common/components/ui-elements/frame.component.ts
+++ b/projects/common/components/ui-elements/frame.component.ts
@@ -5,13 +5,13 @@ import { FrameElement } from '../../interfaces/elements';
 @Component({
   selector: 'aspect-frame',
   template: `
-    <div [style.width]="'calc(100% - ' + (elementModel.styles.borderWidth * 2) + 'px)'"
-         [style.height]="'calc(100% - ' + (elementModel.styles.borderWidth * 2) + 'px)'"
-         [style.border-style]="elementModel.styles.borderStyle"
-         [style.border-width.px]="elementModel.styles.borderWidth"
-         [style.border-color]="elementModel.styles.borderColor"
-         [style.border-radius.px]="elementModel.styles.borderRadius"
-         [style.background-color]="elementModel.styles.backgroundColor">
+    <div [style.width]="'calc(100% - ' + (elementModel.styling.borderWidth * 2) + 'px)'"
+         [style.height]="'calc(100% - ' + (elementModel.styling.borderWidth * 2) + 'px)'"
+         [style.border-style]="elementModel.styling.borderStyle"
+         [style.border-width.px]="elementModel.styling.borderWidth"
+         [style.border-color]="elementModel.styling.borderColor"
+         [style.border-radius.px]="elementModel.styling.borderRadius"
+         [style.background-color]="elementModel.styling.backgroundColor">
     </div>
   `
 })
diff --git a/projects/common/components/ui-elements/likert.component.ts b/projects/common/components/ui-elements/likert.component.ts
index bb9fbfa88..d5aa2064f 100644
--- a/projects/common/components/ui-elements/likert.component.ts
+++ b/projects/common/components/ui-elements/likert.component.ts
@@ -17,15 +17,15 @@ import { LikertElement, LikertRowElement } from '../../interfaces/elements';
       <div class="mat-typography"
            [style.display]="'grid'"
            [style.grid-template-columns]="elementModel.firstColumnSizeRatio + 'fr ' +
-                                        '1fr '.repeat(elementModel.columns.length)"
-         [style.background-color]="elementModel.styles.backgroundColor"
-         [style.color]="elementModel.styles.fontColor"
-         [style.font-family]="elementModel.styles.font"
-         [style.font-size.px]="elementModel.styles.fontSize"
-         [style.line-height.%]="elementModel.styles.lineHeight"
-         [style.font-weight]="elementModel.styles.bold ? 'bold' : ''"
-         [style.font-style]="elementModel.styles.italic ? 'italic' : ''"
-         [style.text-decoration]="elementModel.styles.underline ? 'underline' : ''">
+                                    '1fr '.repeat(elementModel.columns.length)"
+           [style.background-color]="elementModel.styling.backgroundColor"
+           [style.color]="elementModel.styling.fontColor"
+           [style.font-family]="elementModel.styling.font"
+           [style.font-size.px]="elementModel.styling.fontSize"
+           [style.line-height.%]="elementModel.styling.lineHeight"
+           [style.font-weight]="elementModel.styling.bold ? 'bold' : ''"
+           [style.font-style]="elementModel.styling.italic ? 'italic' : ''"
+           [style.text-decoration]="elementModel.styling.underline ? 'underline' : ''">
         <div *ngFor="let column of elementModel.columns; let i = index"
              class="columns" fxLayout="column" fxLayoutAlign="end center"
              [style.grid-column-start]="2 + i"
@@ -43,16 +43,16 @@ import { LikertElement, LikertRowElement } from '../../interfaces/elements';
 
         <ng-container *ngFor="let row of elementModel.rows; let i = index">
           <aspect-likert-radio-button-group
-              [style.background-color]="elementModel.lineColoring && i % 2 === 0 ?
-                  elementModel.lineColoringColor : ''"
-              [style.grid-column-start]="1"
-              [style.grid-column-end]="elementModel.columns.length + 2"
-              [style.grid-row-start]="2 + i"
-              [style.grid-row-end]="3 + i"
-              [style.padding.px]="3"
-              [elementModel]="row"
-              [firstColumnSizeRatio]="elementModel.firstColumnSizeRatio"
-              [parentForm]="parentForm">
+            [style.background-color]="elementModel.lineColoring && i % 2 === 0 ?
+                                      elementModel.lineColoringColor : ''"
+            [style.grid-column-start]="1"
+            [style.grid-column-end]="elementModel.columns.length + 2"
+            [style.grid-row-start]="2 + i"
+            [style.grid-row-end]="3 + i"
+            [style.padding.px]="3"
+            [elementModel]="row"
+            [firstColumnSizeRatio]="elementModel.firstColumnSizeRatio"
+            [parentForm]="parentForm">
           </aspect-likert-radio-button-group>
         </ng-container>
       </div>
diff --git a/projects/common/components/ui-elements/radio-button-group.component.ts b/projects/common/components/ui-elements/radio-button-group.component.ts
index 09519cade..14a67a2ba 100644
--- a/projects/common/components/ui-elements/radio-button-group.component.ts
+++ b/projects/common/components/ui-elements/radio-button-group.component.ts
@@ -8,13 +8,13 @@ import { RadioButtonGroupElement } from '../../interfaces/elements';
     <div class="mat-form-field"
          [style.width.%]="100"
          [style.height.%]="100"
-         [style.background-color]="elementModel.styles.backgroundColor"
-         [style.color]="elementModel.styles.fontColor"
-         [style.font-family]="elementModel.styles.font"
-         [style.font-size.px]="elementModel.styles.fontSize"
-         [style.font-weight]="elementModel.styles.bold ? 'bold' : ''"
-         [style.font-style]="elementModel.styles.italic ? 'italic' : ''"
-         [style.text-decoration]="elementModel.styles.underline ? 'underline' : ''">
+         [style.background-color]="elementModel.styling.backgroundColor"
+         [style.color]="elementModel.styling.fontColor"
+         [style.font-family]="elementModel.styling.font"
+         [style.font-size.px]="elementModel.styling.fontSize"
+         [style.font-weight]="elementModel.styling.bold ? 'bold' : ''"
+         [style.font-style]="elementModel.styling.italic ? 'italic' : ''"
+         [style.text-decoration]="elementModel.styling.underline ? 'underline' : ''">
       <label id="radio-group-label"
              [innerHTML]="elementModel.label">
       </label>
@@ -29,7 +29,7 @@ import { RadioButtonGroupElement } from '../../interfaces/elements';
                                                   elementFormControl.value !== i }"
                           [value]="i"
                           [style.pointer-events]="elementModel.readOnly ? 'none' : 'unset'"
-                          [style.line-height.%]="elementModel.styles.lineHeight">
+                          [style.line-height.%]="elementModel.styling.lineHeight">
           {{option}}
         </mat-radio-button>
         <mat-error *ngIf="elementFormControl.errors && elementFormControl.touched"
diff --git a/projects/common/components/ui-elements/radio-group-images.component.ts b/projects/common/components/ui-elements/radio-group-images.component.ts
index 5f3739fb3..abf35cf16 100644
--- a/projects/common/components/ui-elements/radio-group-images.component.ts
+++ b/projects/common/components/ui-elements/radio-group-images.component.ts
@@ -9,13 +9,13 @@ import { RadioButtonGroupComplexElement } from '../../interfaces/elements';
          [style.height.%]="100"
          [style.display]="'grid !important'"
          [style.grid-template-columns]="'1fr '.repeat(elementModel.columns.length)"
-         [style.background-color]="elementModel.styles.backgroundColor"
-         [style.color]="elementModel.styles.fontColor"
-         [style.font-family]="elementModel.styles.font"
-         [style.font-size.px]="elementModel.styles.fontSize"
-         [style.font-weight]="elementModel.styles.bold ? 'bold' : ''"
-         [style.font-style]="elementModel.styles.italic ? 'italic' : ''"
-         [style.text-decoration]="elementModel.styles.underline ? 'underline' : ''">
+         [style.background-color]="elementModel.styling.backgroundColor"
+         [style.color]="elementModel.styling.fontColor"
+         [style.font-family]="elementModel.styling.font"
+         [style.font-size.px]="elementModel.styling.fontSize"
+         [style.font-weight]="elementModel.styling.bold ? 'bold' : ''"
+         [style.font-style]="elementModel.styling.italic ? 'italic' : ''"
+         [style.text-decoration]="elementModel.styling.underline ? 'underline' : ''">
       <label id="radio-group-label" class="label"
              [style.grid-column-start]="1"
              [style.grid-column-end]="2 + elementModel.columns.length"
diff --git a/projects/common/components/ui-elements/slider.component.ts b/projects/common/components/ui-elements/slider.component.ts
index b840d4b45..cd395eef7 100644
--- a/projects/common/components/ui-elements/slider.component.ts
+++ b/projects/common/components/ui-elements/slider.component.ts
@@ -11,16 +11,16 @@ import { SliderElement } from '../../interfaces/elements';
     <div fxLayout="column"
          [style.width.%]="100"
          [style.height.%]="100"
-         [style.background-color]="elementModel.styles.backgroundColor">
+         [style.background-color]="elementModel.styling.backgroundColor">
       <div *ngIf="elementModel.label"
-           [style.color]="elementModel.styles.fontColor"
-           [style.font-family]="elementModel.styles.font"
-           [style.font-size.px]="elementModel.styles.fontSize"
-           [style.line-height.%]="elementModel.styles.lineHeight"
-           [style.font-weight]="elementModel.styles.bold ? 'bold' : ''"
-           [style.font-style]="elementModel.styles.italic ? 'italic' : ''"
-           [style.text-decoration]="elementModel.styles.underline ? 'underline' : ''">
-        {{elementModel.label}}
+           [style.color]="elementModel.styling.fontColor"
+           [style.font-family]="elementModel.styling.font"
+           [style.font-size.px]="elementModel.styling.fontSize"
+           [style.line-height.%]="elementModel.styling.lineHeight"
+           [style.font-weight]="elementModel.styling.bold ? 'bold' : ''"
+           [style.font-style]="elementModel.styling.italic ? 'italic' : ''"
+           [style.text-decoration]="elementModel.styling.underline ? 'underline' : ''">
+          {{elementModel.label}}
       </div>
       <div #valueContainer
            [class.values]="elementModel.label && !elementModel.showValues">
@@ -29,36 +29,34 @@ import { SliderElement } from '../../interfaces/elements';
                class="value-container-min">
             <div *ngIf="elementModel.showValues"
                  class="value-container">
-              <div
-                  [style.color]="elementModel.styles.fontColor"
-                  [style.font-family]="elementModel.styles.font"
-                  [style.font-size.px]="elementModel.styles.fontSize"
-                  [style.line-height.%]="elementModel.styles.lineHeight"
-                  [style.font-weight]="elementModel.styles.bold ? 'bold' : ''"
-                  [style.font-style]="elementModel.styles.italic ? 'italic' : ''"
-                  [style.text-decoration]="elementModel.styles.underline ? 'underline' : ''">
-                {{elementModel.minValue | number:'':'de'}}
-              </div>
-              <div *ngIf="elementModel.barStyle" class="number-marker"></div>
+                <div [style.color]="elementModel.styling.fontColor"
+                     [style.font-family]="elementModel.styling.font"
+                     [style.font-size.px]="elementModel.styling.fontSize"
+                     [style.line-height.%]="elementModel.styling.lineHeight"
+                     [style.font-weight]="elementModel.styling.bold ? 'bold' : ''"
+                     [style.font-style]="elementModel.styling.italic ? 'italic' : ''"
+                     [style.text-decoration]="elementModel.styling.underline ? 'underline' : ''">
+                  {{elementModel.minValue | number:'':'de'}}
+                </div>
+                <div *ngIf="elementModel.barStyle" class="number-marker"></div>
             </div>
           </div>
           <div #valueMax
                [class.value-container-max]="elementModel.barStyle">
             <div *ngIf="elementModel.showValues"
                  class="value-container">
-              <div
-                  [style.color]="elementModel.styles.fontColor"
-                  [style.font-family]="elementModel.styles.font"
-                  [style.font-size.px]="elementModel.styles.fontSize"
-                  [style.line-height.%]="elementModel.styles.lineHeight"
-                  [style.font-weight]="elementModel.styles.bold ? 'bold' : ''"
-                  [style.font-style]="elementModel.styles.italic ? 'italic' : ''"
-                  [style.text-decoration]="elementModel.styles.underline ? 'underline' : ''">
-                {{elementModel.maxValue | number:'':'de'}}
-              </div>
-              <div *ngIf="elementModel.barStyle"
-                   class="number-marker">
-              </div>
+                <div [style.color]="elementModel.styling.fontColor"
+                     [style.font-family]="elementModel.styling.font"
+                     [style.font-size.px]="elementModel.styling.fontSize"
+                     [style.line-height.%]="elementModel.styling.lineHeight"
+                     [style.font-weight]="elementModel.styling.bold ? 'bold' : ''"
+                     [style.font-style]="elementModel.styling.italic ? 'italic' : ''"
+                     [style.text-decoration]="elementModel.styling.underline ? 'underline' : ''">
+                  {{elementModel.maxValue | number:'':'de'}}
+                </div>
+                <div *ngIf="elementModel.barStyle"
+                     class="number-marker">
+                </div>
             </div>
           </div>
         </div>
@@ -77,13 +75,12 @@ import { SliderElement } from '../../interfaces/elements';
            [style.margin-right.px]="elementModel.barStyle ? valueMax.offsetWidth/2 - 8 : valueMax.offsetWidth"
            [style.margin-left.px]="elementModel.barStyle ? valueMin.offsetWidth/2 - 8: valueMin.offsetWidth"
            [style.margin-top.px]="elementModel.barStyle ? -32 : -valueContainer.offsetHeight">
-        <mat-slider
-            [class]="elementModel.barStyle ? 'bar-style' : ''"
-            [thumbLabel]="elementModel.thumbLabel"
-            [formControl]="elementFormControl"
-            [style.width.%]="100"
-            [max]="elementModel.maxValue"
-            [min]="elementModel.minValue">
+        <mat-slider [class]="elementModel.barStyle ? 'bar-style' : ''"
+                    [thumbLabel]="elementModel.thumbLabel"
+                    [formControl]="elementFormControl"
+                    [style.width.%]="100"
+                    [max]="elementModel.maxValue"
+                    [min]="elementModel.minValue">
         </mat-slider>
         <mat-error *ngIf="elementFormControl.touched && elementFormControl.errors">
           {{elementModel.requiredWarnMessage}}
diff --git a/projects/common/components/ui-elements/spell-correct.component.ts b/projects/common/components/ui-elements/spell-correct.component.ts
index cb7c0f8bf..90b82cda2 100644
--- a/projects/common/components/ui-elements/spell-correct.component.ts
+++ b/projects/common/components/ui-elements/spell-correct.component.ts
@@ -8,9 +8,8 @@ import { SpellCorrectElement } from '../../interfaces/elements';
   template: `
     <div [style.width.%]="100"
          [style.height.%]="100">
-      <div fxFlex
-           fxLayout="column"
-           aspectInputBackgroundColor [backgroundColor]="elementModel.styles.backgroundColor"
+      <div fxFlex fxLayout="column"
+           aspectInputBackgroundColor [backgroundColor]="elementModel.styling.backgroundColor"
            [style.width.%]="100"
            [style.height.%]="100">
         <mat-form-field class="small-input">
@@ -18,12 +17,12 @@ import { SpellCorrectElement } from '../../interfaces/elements';
                  [style.text-align]="'center'"
                  autocomplete="off"
                  [readonly]="elementModel.readOnly"
-                 [style.color]="elementModel.styles.fontColor"
-                 [style.font-family]="elementModel.styles.font"
-                 [style.font-size.px]="elementModel.styles.fontSize"
-                 [style.font-weight]="elementModel.styles.bold ? 'bold' : ''"
-                 [style.font-style]="elementModel.styles.italic ? 'italic' : ''"
-                 [style.text-decoration]="elementModel.styles.underline ? 'underline' : ''"
+                 [style.color]="elementModel.styling.fontColor"
+                 [style.font-family]="elementModel.styling.font"
+                 [style.font-size.px]="elementModel.styling.fontSize"
+                 [style.font-weight]="elementModel.styling.bold ? 'bold' : ''"
+                 [style.font-style]="elementModel.styling.italic ? 'italic' : ''"
+                 [style.text-decoration]="elementModel.styling.underline ? 'underline' : ''"
                  [value]="elementModel.value"
                  [formControl]="elementFormControl">
         </mat-form-field>
@@ -31,25 +30,23 @@ import { SpellCorrectElement } from '../../interfaces/elements';
                 mat-button
                 type="button"
                 [disabled]="elementModel.readOnly"
-                [style.color]="elementModel.styles.fontColor"
-                [style.font-family]="elementModel.styles.font"
-                [style.font-size.px]="elementModel.styles.fontSize"
-                [style.font-weight]="elementModel.styles.bold ? 'bold' : '400'"
-                [style.font-style]="elementModel.styles.italic ? 'italic' : ''"
-                [style.text-decoration]="elementModel.styles.underline ? 'underline' : ''"
+                [style.color]="elementModel.styling.fontColor"
+                [style.font-family]="elementModel.styling.font"
+                [style.font-size.px]="elementModel.styling.fontSize"
+                [style.font-weight]="elementModel.styling.bold ? 'bold' : '400'"
+                [style.font-style]="elementModel.styling.italic ? 'italic' : ''"
+                [style.text-decoration]="elementModel.styling.underline ? 'underline' : ''"
                 [style.width.%]="100"
                 [style.margin-top]="'-20px'"
-                [style.text-decoration-line]=
-                    "(inputElement && inputElement.focused) ||
-                    (inputElement && !!inputElement.value) ||
-                    (elementFormControl && elementFormControl.value === '') ? 'line-through' : ''"
-                (click)="
-                elementFormControl.value === null ?
-                inputElement.focus() :
-                buttonElement.focus();
-                elementFormControl.value === null ?
-                (elementFormControl.setValue('')) :
-                elementFormControl.setValue(null)">{{elementModel.label}}
+                [style.text-decoration-line]="(inputElement && inputElement.focused) ||
+                                              (inputElement && !!inputElement.value) ||
+                                              (elementFormControl && elementFormControl.value === '') ? 'line-through' : ''"
+                (click)="elementFormControl.value === null ?
+                           inputElement.focus() :
+                           buttonElement.focus();
+                        elementFormControl.value === null ?
+                            (elementFormControl.setValue('')) :
+                            elementFormControl.setValue(null)">{{elementModel.label}}
         </button>
       </div>
     </div>
diff --git a/projects/common/components/ui-elements/text-area.component.ts b/projects/common/components/ui-elements/text-area.component.ts
index 53750e2c5..cf346635e 100644
--- a/projects/common/components/ui-elements/text-area.component.ts
+++ b/projects/common/components/ui-elements/text-area.component.ts
@@ -12,13 +12,13 @@ import { TextAreaElement } from '../../interfaces/elements';
         [style.width.%]="100"
         [style.height.%]="100"
         [style.min-height.%]="100"
-        aspectInputBackgroundColor [backgroundColor]="elementModel.styles.backgroundColor"
-        [style.color]="elementModel.styles.fontColor"
-        [style.font-family]="elementModel.styles.font"
-        [style.font-size.px]="elementModel.styles.fontSize"
-        [style.font-weight]="elementModel.styles.bold ? 'bold' : ''"
-        [style.font-style]="elementModel.styles.italic ? 'italic' : ''"
-        [style.text-decoration]="elementModel.styles.underline ? 'underline' : ''"
+        aspectInputBackgroundColor [backgroundColor]="elementModel.styling.backgroundColor"
+        [style.color]="elementModel.styling.fontColor"
+        [style.font-family]="elementModel.styling.font"
+        [style.font-size.px]="elementModel.styling.fontSize"
+        [style.font-weight]="elementModel.styling.bold ? 'bold' : ''"
+        [style.font-style]="elementModel.styling.italic ? 'italic' : ''"
+        [style.text-decoration]="elementModel.styling.underline ? 'underline' : ''"
         [appearance]="$any(elementModel.appearance)">
       <mat-label *ngIf="elementModel.label">{{elementModel.label}}</mat-label>
       <textarea matInput #input
@@ -27,7 +27,7 @@ import { TextAreaElement } from '../../interfaces/elements';
                 [value]="elementModel.value"
                 [readonly]="elementModel.readOnly"
                 [style.min-width.%]="100"
-                [style.line-height.%]="elementModel.styles.lineHeight"
+                [style.line-height.%]="elementModel.styling.lineHeight"
                 [style.resize]="elementModel.resizeEnabled ? 'both' : 'none'"
                 (focus)="elementModel.inputAssistancePreset !== 'none' ? onFocusChanged.emit(input) : null"
                 (blur)="elementModel.inputAssistancePreset !== 'none' ? onFocusChanged.emit(null): null">
diff --git a/projects/common/components/ui-elements/text-field-simple.component.ts b/projects/common/components/ui-elements/text-field-simple.component.ts
index f1b539910..621faa31d 100644
--- a/projects/common/components/ui-elements/text-field-simple.component.ts
+++ b/projects/common/components/ui-elements/text-field-simple.component.ts
@@ -8,13 +8,13 @@ import { TextFieldSimpleElement } from '../../interfaces/elements';
     <input type="text" form="parentForm"
            [style.width.px]="elementModel.width"
            [style.height.px]="elementModel.height"
-           [style.line-height.px]="elementModel.styles.fontSize"
-           [style.color]="elementModel.styles.fontColor"
-           [style.font-family]="elementModel.styles.font"
-           [style.font-size.px]="elementModel.styles.fontSize"
-           [style.font-weight]="elementModel.styles.bold ? 'bold' : ''"
-           [style.font-style]="elementModel.styles.italic ? 'italic' : ''"
-           [style.text-decoration]="elementModel.styles.underline ? 'underline' : ''"
+           [style.line-height.px]="elementModel.styling.fontSize"
+           [style.color]="elementModel.styling.fontColor"
+           [style.font-family]="elementModel.styling.font"
+           [style.font-size.px]="elementModel.styling.fontSize"
+           [style.font-weight]="elementModel.styling.bold ? 'bold' : ''"
+           [style.font-style]="elementModel.styling.italic ? 'italic' : ''"
+           [style.text-decoration]="elementModel.styling.underline ? 'underline' : ''"
            [readonly]="elementModel.readOnly"
            [formControl]="elementFormControl"
            [value]="elementModel.value">
diff --git a/projects/common/components/ui-elements/text-field.component.ts b/projects/common/components/ui-elements/text-field.component.ts
index 90885d18e..4743da198 100644
--- a/projects/common/components/ui-elements/text-field.component.ts
+++ b/projects/common/components/ui-elements/text-field.component.ts
@@ -8,17 +8,17 @@ import { TextFieldElement } from '../../interfaces/elements';
   selector: 'aspect-text-field',
   template: `
     <mat-form-field
-        *ngIf="elementModel.label !== ''"
-        [style.width.%]="100"
-        [style.height.%]="100"
-        [style.color]="elementModel.styles.fontColor"
-        [style.font-family]="elementModel.styles.font"
-        [style.font-size.px]="elementModel.styles.fontSize"
-        [style.font-weight]="elementModel.styles.bold ? 'bold' : ''"
-        [style.font-style]="elementModel.styles.italic ? 'italic' : ''"
-        [style.text-decoration]="elementModel.styles.underline ? 'underline' : ''"
-        aspectInputBackgroundColor [backgroundColor]="elementModel.styles.backgroundColor"
-        [appearance]="$any(elementModel.appearance)">
+            *ngIf="elementModel.label !== ''"
+            [style.width.%]="100"
+            [style.height.%]="100"
+            [style.color]="elementModel.styling.fontColor"
+            [style.font-family]="elementModel.styling.font"
+            [style.font-size.px]="elementModel.styling.fontSize"
+            [style.font-weight]="elementModel.styling.bold ? 'bold' : ''"
+            [style.font-style]="elementModel.styling.italic ? 'italic' : ''"
+            [style.text-decoration]="elementModel.styling.underline ? 'underline' : ''"
+            aspectInputBackgroundColor [backgroundColor]="elementModel.styling.backgroundColor"
+            [appearance]="$any(elementModel.appearance)">
       <mat-label>{{elementModel.label}}</mat-label>
       <input matInput type="text" #input autocomplete="off"
              [formControl]="elementFormControl"
@@ -37,18 +37,17 @@ import { TextFieldElement } from '../../interfaces/elements';
         {{elementFormControl.errors | errorTransform: elementModel}}
       </mat-error>
     </mat-form-field>
-    <mat-form-field
-        *ngIf="elementModel.label === ''" class="small-input"
-        [style.width.%]="100"
-        [style.height.%]="100"
-        [style.color]="elementModel.styles.fontColor"
-        [style.font-family]="elementModel.styles.font"
-        [style.font-size.px]="elementModel.styles.fontSize"
-        [style.font-weight]="elementModel.styles.bold ? 'bold' : ''"
-        [style.font-style]="elementModel.styles.italic ? 'italic' : ''"
-        [style.text-decoration]="elementModel.styles.underline ? 'underline' : ''"
-        aspectInputBackgroundColor [backgroundColor]="elementModel.styles.backgroundColor"
-        [appearance]="$any(elementModel.appearance)">
+    <mat-form-field *ngIf="elementModel.label === ''" class="small-input"
+                    [style.width.%]="100"
+                    [style.height.%]="100"
+                    [style.color]="elementModel.styling.fontColor"
+                    [style.font-family]="elementModel.styling.font"
+                    [style.font-size.px]="elementModel.styling.fontSize"
+                    [style.font-weight]="elementModel.styling.bold ? 'bold' : ''"
+                    [style.font-style]="elementModel.styling.italic ? 'italic' : ''"
+                    [style.text-decoration]="elementModel.styling.underline ? 'underline' : ''"
+                    aspectInputBackgroundColor [backgroundColor]="elementModel.styling.backgroundColor"
+                    [appearance]="$any(elementModel.appearance)">
       <input matInput type="text" #input autocomplete="off"
              [formControl]="elementFormControl"
              [value]="elementModel.value"
diff --git a/projects/common/components/ui-elements/text.component.ts b/projects/common/components/ui-elements/text.component.ts
index 6587db6fe..5c8ce8021 100644
--- a/projects/common/components/ui-elements/text.component.ts
+++ b/projects/common/components/ui-elements/text.component.ts
@@ -9,30 +9,30 @@ import { TextElement, ValueChangeElement } from '../../interfaces/elements';
   template: `
     <div [style.width.%]="100"
          [style.height.%]="100">
-      <aspect-marking-bar
-          *ngIf="elementModel.highlightableYellow ||
-              elementModel.highlightableTurquoise ||
-              elementModel.highlightableOrange"
-          [elementModel]="elementModel"
-          (selectionChanged)="onSelectionChanged($event)">
-      </aspect-marking-bar>
-      <div #textContainerRef class="text-container"
-           [class.orange-selection]="selectedColor === 'orange'"
-           [class.yellow-selection]="selectedColor === 'yellow'"
-           [class.turquoise-selection]="selectedColor === 'turquoise'"
-           [class.delete-selection]="selectedColor === 'delete'"
-           [style.background-color]="elementModel.styles.backgroundColor"
-           [style.color]="elementModel.styles.fontColor"
-           [style.font-family]="elementModel.styles.font"
-           [style.font-size.px]="elementModel.styles.fontSize"
-           [style.line-height.%]="elementModel.styles.lineHeight"
-           [style.font-weight]="elementModel.styles.bold ? 'bold' : ''"
-           [style.font-style]="elementModel.styles.italic ? 'italic' : ''"
-           [style.text-decoration]="elementModel.styles.underline ? 'underline' : ''"
-           [innerHTML]="savedText || elementModel.text | safeResourceHTML"
-           (touchstart)="emitStartSelection($event)"
-           (mousedown)="emitStartSelection($event)">
-      </div>
+        <aspect-marking-bar
+                *ngIf="elementModel.highlightableYellow ||
+            elementModel.highlightableTurquoise ||
+            elementModel.highlightableOrange"
+                [elementModel]="elementModel"
+                (selectionChanged)="onSelectionChanged($event)">
+        </aspect-marking-bar>
+        <div #textContainerRef class="text-container"
+             [class.orange-selection]="selectedColor === 'orange'"
+             [class.yellow-selection]="selectedColor === 'yellow'"
+             [class.turquoise-selection]="selectedColor === 'turquoise'"
+             [class.delete-selection]="selectedColor === 'delete'"
+             [style.background-color]="elementModel.styling.backgroundColor"
+             [style.color]="elementModel.styling.fontColor"
+             [style.font-family]="elementModel.styling.font"
+             [style.font-size.px]="elementModel.styling.fontSize"
+             [style.line-height.%]="elementModel.styling.lineHeight"
+             [style.font-weight]="elementModel.styling.bold ? 'bold' : ''"
+             [style.font-style]="elementModel.styling.italic ? 'italic' : ''"
+             [style.text-decoration]="elementModel.styling.underline ? 'underline' : ''"
+             [innerHTML]="savedText || elementModel.text | safeResourceHTML"
+             (touchstart)="emitStartSelection($event)"
+             (mousedown)="emitStartSelection($event)">
+        </div>
     </div>
   `,
   styles: [
diff --git a/projects/common/components/ui-elements/toggle-button.component.ts b/projects/common/components/ui-elements/toggle-button.component.ts
index 2f332c564..c81b1970e 100644
--- a/projects/common/components/ui-elements/toggle-button.component.ts
+++ b/projects/common/components/ui-elements/toggle-button.component.ts
@@ -16,17 +16,17 @@ import { ToggleButtonElement } from '../../interfaces/elements';
                            [ngClass]="{ 'strike' : elementModel.strikeOtherOptions &&
                                                    elementFormControl.value !== null &&
                                                    elementFormControl.value !== i }"
-                           [style.color]="elementModel.styles.fontColor"
-                           [style.font-size.px]="elementModel.styles.fontSize"
-                           [style.font-weight]="elementModel.styles.bold ? 'bold' : ''"
-                           [style.font-style]="elementModel.styles.italic ? 'italic' : ''"
-                           [style.text-decoration]="elementModel.styles.underline ? 'underline' : ''"
-                           [style.font-family]="elementModel.styles.font"
+                           [style.color]="elementModel.styling.fontColor"
+                           [style.font-size.px]="elementModel.styling.fontSize"
+                           [style.font-weight]="elementModel.styling.bold ? 'bold' : ''"
+                           [style.font-style]="elementModel.styling.italic ? 'italic' : ''"
+                           [style.text-decoration]="elementModel.styling.underline ? 'underline' : ''"
+                           [style.font-family]="elementModel.styling.font"
                            [style.background-color]="elementFormControl.value !== null &&
                                                    elementFormControl.value === i ?
                                                    elementModel.selectionColor :
-                                                   elementModel.styles.backgroundColor"
-                           [style.line-height.%]="elementModel.styles.lineHeight">
+                                                   elementModel.styling.backgroundColor"
+                           [style.line-height.%]="elementModel.styling.lineHeight">
                            <!--Background color does not show in editor-->
           {{option}}
         </mat-button-toggle>
diff --git a/projects/common/components/ui-elements/video.component.ts b/projects/common/components/ui-elements/video.component.ts
index a46faf9bb..e5813e49a 100644
--- a/projects/common/components/ui-elements/video.component.ts
+++ b/projects/common/components/ui-elements/video.component.ts
@@ -20,7 +20,7 @@ import { VideoElement } from '../../interfaces/elements';
                           [active]="active"
                           [id]="elementModel.id"
                           [savedPlaybackTime]="savedPlaybackTime"
-                          [playerProperties]="elementModel.playerProps"
+                          [playerProperties]="elementModel.player"
                           [dependencyDissolved]="dependencyDissolved"
                           (onMediaValidStatusChanged)="onMediaValidStatusChanged.emit($event)"
                           (elementValueChanged)="elementValueChanged.emit($event)">
diff --git a/projects/common/interfaces/elements.ts b/projects/common/interfaces/elements.ts
index f1c1e218c..c5260db34 100644
--- a/projects/common/interfaces/elements.ts
+++ b/projects/common/interfaces/elements.ts
@@ -4,7 +4,7 @@ import { LikertColumn } from './likert';
 export type InputElementValue = string[] | string | number | boolean | DragNDropValueObject[] | null;
 export type UIElementType = 'text' | 'button' | 'text-field' | 'text-area' | 'checkbox'
 | 'dropdown' | 'radio' | 'image' | 'audio' | 'video' | 'likert' | 'likert-row' | 'radio-group-images'
-| 'drop-list' | 'cloze' | 'spell-correct' | 'slider' | 'frame' | 'toggle-button';
+| 'drop-list' | 'cloze' | 'spell-correct' | 'slider' | 'frame' | 'toggle-button' | 'text-field-simple';
 export type InputAssistancePreset = 'none' | 'french' | 'numbers' | 'numbersAndOperators' | 'numbersAndBasicOperators'
 | 'comparisonOperators' | 'squareDashDot' | 'placeValue';
 export type DragNDropValueObject = {
@@ -14,7 +14,7 @@ export type DragNDropValueObject = {
 };
 export type UIElementValue = string | number | boolean | undefined | UIElementType | InputElementValue |
 LikertColumn[] | ClozeDocument |
-PositionProperties | ElementStyles | PlayerProperties | BasicStyles;
+PositionProperties | ElementStyling | PlayerProperties | BasicStyles;
 
 export interface UIElement {
   [index: string]: UIElementValue;
@@ -22,9 +22,9 @@ export interface UIElement {
   id: string;
   width: number;
   height: number;
-  positionProps?: PositionProperties;
-  styles: ElementStyles;
-  playerProps?: PlayerProperties;
+  position?: PositionProperties; // position
+  styling?: ElementStyling; // styling
+  player?: PlayerProperties; // player
 }
 
 export interface InputElement extends UIElement {
@@ -36,11 +36,11 @@ export interface InputElement extends UIElement {
 }
 
 export interface PositionedElement extends UIElement {
-  positionProps: PositionProperties;
+  position: PositionProperties;
 }
 
 export interface PlayerElement extends UIElement {
-  playerProps: PlayerProperties;
+  player: PlayerProperties;
 }
 
 export interface ValueChangeElement {
@@ -66,7 +66,7 @@ export interface PositionProperties {
   zIndex: number;
 }
 
-export interface ElementStyles {
+export interface ElementStyling {
   [index: string]: string | number | boolean | undefined;
   fontColor?: string;
   font?: string;
@@ -85,7 +85,7 @@ export interface ElementStyles {
   lineColoringColor?: string;
 }
 
-export interface BasicStyles extends ElementStyles {
+export interface BasicStyles extends ElementStyling {
   fontColor: string;
   font: string;
   fontSize: number;
@@ -125,23 +125,23 @@ export interface ButtonElement extends UIElement {
   imageSrc: string | null;
   action: null | 'unitNav' | 'pageNav'
   actionParam: null | 'previous' | 'next' | 'first' | 'last' | 'end' | number;
-  positionProps: PositionProperties;
-  styles: BasicStyles & {
+  position: PositionProperties;
+  styling: BasicStyles & {
     borderRadius: number;
   }
 }
 
 export interface CheckboxElement extends InputElement {
   type: 'checkbox';
-  positionProps: PositionProperties;
-  styles: BasicStyles;
+  position: PositionProperties;
+  styling: BasicStyles;
 }
 
 export interface ClozeElement extends UIElement {
   type: 'cloze';
   document: ClozeDocument;
-  positionProps: PositionProperties;
-  styles: BasicStyles & {
+  position: PositionProperties;
+  styling: BasicStyles & {
     lineHeight: number;
   }
 }
@@ -150,8 +150,8 @@ export interface DropdownElement extends InputElement {
   type: 'dropdown';
   options: string[];
   allowUnset: boolean;
-  positionProps: PositionProperties;
-  styles: BasicStyles
+  position: PositionProperties;
+  styling: BasicStyles
 }
 
 export interface DropListElement extends InputElement {
@@ -161,8 +161,8 @@ export interface DropListElement extends InputElement {
   orientation: 'vertical' | 'horizontal' | 'flex';
   highlightReceivingDropList: boolean;
   highlightReceivingDropListColor: string;
-  positionProps: PositionProperties;
-  styles: BasicStyles & {
+  position: PositionProperties;
+  styling: BasicStyles & {
     itemBackgroundColor: string;
   }
 }
@@ -172,15 +172,15 @@ export interface DropListSimpleElement extends InputElement {
   connectedTo: string[];
   highlightReceivingDropList: boolean;
   highlightReceivingDropListColor: string;
-  styles: BasicStyles & {
+  styling: BasicStyles & {
     itemBackgroundColor: string;
   }
 }
 
 export interface FrameElement extends UIElement {
   type: 'frame';
-  positionProps: PositionProperties;
-  styles: BasicStyles & {
+  position: PositionProperties;
+  styling: BasicStyles & {
     borderWidth: number;
     borderColor: string;
     borderStyle: 'solid' | 'dotted' | 'dashed' | 'double' | 'groove' | 'ridge' | 'inset' | 'outset';
@@ -196,7 +196,7 @@ export interface ImageElement extends UIElement {
   magnifierSize: number;
   magnifierZoom: number;
   magnifierUsed: boolean;
-  positionProps: PositionProperties;
+  position: PositionProperties;
 }
 
 export interface LikertElement extends UIElement {
@@ -205,8 +205,8 @@ export interface LikertElement extends UIElement {
   columns: LikertColumn[];
   firstColumnSizeRatio: number;
   readOnly: boolean;
-  positionProps: PositionProperties;
-  styles: BasicStyles & {
+  position: PositionProperties;
+  styling: BasicStyles & {
     lineHeight: number;
     lineColoring: boolean;
     lineColoringColor: string;
@@ -225,15 +225,15 @@ export interface RadioButtonGroupElement extends InputElement {
   options: string[];
   alignment: 'column' | 'row';
   strikeOtherOptions: boolean;
-  positionProps: PositionProperties;
-  styles: BasicStyles;
+  position: PositionProperties;
+  styling: BasicStyles;
 }
 
 export interface RadioButtonGroupComplexElement extends InputElement {
   type: 'radio-group-images' // TODO better name
   columns: LikertColumn[];
-  positionProps: PositionProperties;
-  styles: BasicStyles;
+  position: PositionProperties;
+  styling: BasicStyles;
 }
 
 export interface SliderElement extends InputElement {
@@ -243,14 +243,14 @@ export interface SliderElement extends InputElement {
   showValues: boolean;
   barStyle: boolean; // TODO besserer name
   thumbLabel: boolean;
-  positionProps: PositionProperties;
-  styles: BasicStyles;
+  position: PositionProperties;
+  styling: BasicStyles;
 }
 
 export interface SpellCorrectElement extends InputElement {
   type: 'spell-correct';
-  positionProps: PositionProperties;
-  styles: BasicStyles;
+  position: PositionProperties;
+  styling: BasicStyles;
 }
 
 export interface TextFieldElement extends InputElement {
@@ -265,8 +265,8 @@ export interface TextFieldElement extends InputElement {
   inputAssistancePreset: InputAssistancePreset;
   inputAssistancePosition: 'floating' | 'right';
   clearable: boolean;
-  positionProps: PositionProperties;
-  styles: BasicStyles;
+  position: PositionProperties;
+  styling: BasicStyles;
 }
 
 export interface TextAreaElement extends InputElement {
@@ -276,15 +276,15 @@ export interface TextAreaElement extends InputElement {
   rowCount: number;
   inputAssistancePreset: InputAssistancePreset;
   inputAssistancePosition: 'floating' | 'right';
-  positionProps: PositionProperties;
-  styles: BasicStyles & {
+  position: PositionProperties;
+  styling: BasicStyles & {
     lineHeight: number;
   };
 }
 
 export interface TextFieldSimpleElement extends InputElement {
   type: 'text-field';
-  styles: BasicStyles; // TODO okay? bg-color?
+  styling: BasicStyles; // TODO okay? bg-color?
 }
 
 export interface TextElement extends UIElement {
@@ -293,8 +293,8 @@ export interface TextElement extends UIElement {
   highlightableOrange: boolean;
   highlightableTurquoise: boolean;
   highlightableYellow: boolean;
-  positionProps: PositionProperties;
-  styles: BasicStyles & {
+  position: PositionProperties;
+  styling: BasicStyles & {
     lineHeight: number;
   }
 }
@@ -306,7 +306,7 @@ export interface ToggleButtonElement extends InputElement {
   selectionColor: string;
   verticalOrientation: boolean;
   dynamicWidth: boolean;
-  styles: BasicStyles & {
+  styling: BasicStyles & {
     lineHeight: number;
   };
 }
@@ -314,14 +314,14 @@ export interface ToggleButtonElement extends InputElement {
 export interface AudioElement extends UIElement {
   type: 'audio';
   src: string;
-  positionProps: PositionProperties;
-  playerProps: PlayerProperties;
+  position: PositionProperties;
+  player: PlayerProperties;
 }
 
 export interface VideoElement extends UIElement {
   type: 'video';
   src: string;
   scale: boolean; // TODO besserer name
-  positionProps: PositionProperties;
-  playerProps: PlayerProperties;
+  position: PositionProperties;
+  player: PlayerProperties;
 }
diff --git a/projects/common/services/message.service.ts b/projects/common/services/message.service.ts
index b2db68992..b8f1fcab9 100644
--- a/projects/common/services/message.service.ts
+++ b/projects/common/services/message.service.ts
@@ -5,7 +5,15 @@ import { MatSnackBar } from '@angular/material/snack-bar';
   providedIn: 'root'
 })
 export class MessageService {
-  constructor(private _snackBar: MatSnackBar) { }
+  private static instance: MessageService;
+
+  constructor(private _snackBar: MatSnackBar) {
+    MessageService.instance = this;
+  }
+
+  static getInstance(): MessageService {
+    return MessageService.instance;
+  }
 
   showWarning(text: string): void {
     this._snackBar.open(text, undefined, { duration: 2000, panelClass: 'snackbar-warning' });
diff --git a/projects/common/tiptap-editor-extensions/drop-list.ts b/projects/common/tiptap-editor-extensions/drop-list.ts
index c0fab8782..dc4c4b8bc 100644
--- a/projects/common/tiptap-editor-extensions/drop-list.ts
+++ b/projects/common/tiptap-editor-extensions/drop-list.ts
@@ -10,7 +10,7 @@ const DropListExtension =
     addAttributes() {
       return {
         model: {
-          default: ElementFactory.createElement('drop-list', { height: 25, width: 100 })
+          default: ElementFactory.createElement({ type: 'drop-list', height: 25, width: 100 })
         }
       };
     },
diff --git a/projects/common/tiptap-editor-extensions/text-field.ts b/projects/common/tiptap-editor-extensions/text-field.ts
index a6e41f9d7..599c04e35 100644
--- a/projects/common/tiptap-editor-extensions/text-field.ts
+++ b/projects/common/tiptap-editor-extensions/text-field.ts
@@ -10,7 +10,7 @@ const TextFieldExtension =
     addAttributes() {
       return {
         model: {
-          default: ElementFactory.createElement('text-field-simple')
+          default: ElementFactory.createElement({ type: 'text-field-simple' })
         }
       };
     },
diff --git a/projects/common/tiptap-editor-extensions/toggle-button.ts b/projects/common/tiptap-editor-extensions/toggle-button.ts
index 18b62121d..80144f537 100644
--- a/projects/common/tiptap-editor-extensions/toggle-button.ts
+++ b/projects/common/tiptap-editor-extensions/toggle-button.ts
@@ -10,7 +10,7 @@ const ToggleButtonExtension =
     addAttributes() {
       return {
         model: {
-          default: ElementFactory.createElement('toggle-button')
+          default: ElementFactory.createElement({ type: 'toggle-button' })
         }
       };
     },
diff --git a/projects/common/util/element.factory.ts b/projects/common/util/element.factory.ts
index 6c44380d8..e220dd501 100644
--- a/projects/common/util/element.factory.ts
+++ b/projects/common/util/element.factory.ts
@@ -24,139 +24,145 @@ import {
   ClozeElement,
   DropdownElement,
   DropListElement,
-  DropListSimpleElement,
+  DropListSimpleElement, ElementStyling,
   FrameElement,
   ImageElement,
-  InputElement, LikertElement, LikertRowElement, PlayerProperties, PositionProperties,
+  InputElement, InputElementValue, LikertElement, LikertRowElement, PlayerProperties, PositionProperties,
   RadioButtonGroupComplexElement,
   RadioButtonGroupElement, SliderElement, SpellCorrectElement,
   TextAreaElement,
   TextElement,
   TextFieldElement, TextFieldSimpleElement, ToggleButtonElement,
-  UIElement, UIElementType,
+  UIElement, UIElementType, UIElementValue,
   VideoElement
 } from '../interfaces/elements';
 
 export abstract class ElementFactory {
-  static createElement(elementType: string, defaults?: Record<string, any>): UIElement {
-    switch (elementType) {
+  static createElement(element: Partial<UIElement>): UIElement {
+    // console.log('createElement', element);
+    switch (element.type) {
       case 'text':
-        return ElementFactory.createTextElement(defaults);
+        return ElementFactory.createTextElement(element as Partial<TextElement>);
       case 'button':
-        return ElementFactory.createButtonElement(defaults);
+        return ElementFactory.createButtonElement(element as Partial<ButtonElement>);
       case 'text-field':
-        return ElementFactory.createTextFieldElement(defaults);
+        return ElementFactory.createTextFieldElement(element as Partial<TextFieldElement>);
       case 'text-field-simple':
-        return ElementFactory.createTextFieldSimpleElement(defaults);
+        return ElementFactory.createTextFieldSimpleElement(element as Partial<TextFieldSimpleElement>);
       case 'text-area':
-        return ElementFactory.createTextAreaElement(defaults);
+        return ElementFactory.createTextAreaElement(element as Partial<TextAreaElement>);
       case 'checkbox':
-        return ElementFactory.createCheckboxElement(defaults);
+        return ElementFactory.createCheckboxElement(element as Partial<CheckboxElement>);
       case 'dropdown':
-        return ElementFactory.createDropdownElement(defaults);
+        return ElementFactory.createDropdownElement(element as Partial<DropdownElement>);
       case 'radio':
-        return ElementFactory.createRadioButtonGroupElement(defaults);
+        return ElementFactory.createRadioButtonGroupElement(element as Partial<RadioButtonGroupElement>);
       case 'image':
-        return ElementFactory.createImageElement(defaults);
+        return ElementFactory.createImageElement(element as Partial<ImageElement>);
       case 'audio':
-        return ElementFactory.createAudioElement(defaults);
+        return ElementFactory.createAudioElement(element as Partial<AudioElement>);
       case 'video':
-        return ElementFactory.createVideoElement(defaults);
+        return ElementFactory.createVideoElement(element as Partial<VideoElement>);
       case 'likert':
-        return ElementFactory.createLikertElement(defaults);
+        return ElementFactory.createLikertElement(element as Partial<LikertElement>);
       case 'radio-group-images':
-        return ElementFactory.createRadioButtonGroupComplexElement(defaults);
+        return ElementFactory.createRadioButtonGroupComplexElement(element as Partial<RadioButtonGroupComplexElement>);
       case 'drop-list':
-        return ElementFactory.createDropListElement(defaults);
+        return ElementFactory.createDropListElement(element as Partial<DropListElement>);
       case 'cloze':
-        return ElementFactory.createClozeElement(defaults);
+        return ElementFactory.createClozeElement(element as Partial<ClozeElement>);
       case 'slider':
-        return ElementFactory.createSliderElement(defaults);
+        return ElementFactory.createSliderElement(element as Partial<SliderElement>);
       case 'spell-correct':
-        return ElementFactory.createSpellCorrectElement(defaults);
+        return ElementFactory.createSpellCorrectElement(element as Partial<SpellCorrectElement>);
       case 'frame':
-        return ElementFactory.createFrameElement(defaults);
+        return ElementFactory.createFrameElement(element as Partial<FrameElement>);
       case 'toggle-button':
-        return ElementFactory.createToggleButtonElement(defaults);
+        return ElementFactory.createToggleButtonElement(element as Partial<ToggleButtonElement>);
       default:
-        throw new Error(`ElementType ${elementType} not found!`);
+        throw new Error(`ElementType ${element.type} not found!`);
     }
   }
 
-  static initElement(elementType: string, defaults: Record<string, number>): UIElement {
+  static initElement(element: Partial<UIElement>): UIElement {
     return {
-      type: elementType as UIElementType,
-      id: defaults.id ? String(defaults.id) : 'id_placeholder',
-      width: defaults.width || 190,
-      height: defaults.height || 60,
-      styles: {}
+      type: element.type as UIElementType,
+      id: element.id ? String(element.id) : 'id_placeholder',
+      width: element.width || 190,
+      height: element.height || 60
     };
   }
 
-  static initInputElement(elementType: string, defaults: Record<string, any>): InputElement {
+  static initInputElement(element: Partial<UIElement>): InputElement {
     return {
-      ...ElementFactory.initElement(elementType, defaults),
-      label: defaults.label || 'Beispielbeschriftung',
-      value: defaults.value || null,
-      required: defaults.required || false,
-      requiredWarnMessage: defaults.requiredWarnMessage || 'Eingabe erforderlich',
-      readOnly: defaults.readOnly || false
+      ...ElementFactory.initElement(element),
+      label: element.label as string || 'Beispielbeschriftung',
+      value: element.value !== undefined ? element.value as InputElementValue : null,
+      required: element.required !== undefined ? element.required as boolean : false,
+      requiredWarnMessage: element.requiredWarnMessage !== undefined ?
+        element.requiredWarnMessage as string :
+        'Eingabe erforderlich',
+      readOnly: element.readOnly !== undefined ? element.readOnly as boolean : false
     };
   }
 
-  static initPositionProps(defaults: Record<string, any> = {}): PositionProperties {
+  static initPositionProps(defaults: Record<string, UIElementValue> = {}): PositionProperties {
     return {
-      fixedSize: defaults.fixedSize || false,
-      dynamicPositioning: defaults.dynamicPositioning || false,
-      xPosition: defaults.xPosition || 0,
-      yPosition: defaults.yPosition || 0,
-      useMinHeight: defaults.useMinHeight || false,
-      gridColumnStart: defaults.gridColumnStart || 1,
-      gridColumnEnd: defaults.gridColumnEnd || 2,
-      gridRowStart: defaults.gridRowStart || 1,
-      gridRowEnd: defaults.gridRowEnd || 2,
-      marginLeft: defaults.marginLeft || 0,
-      marginRight: defaults.marginRight || 0,
-      marginTop: defaults.marginTop || 0,
-      marginBottom: defaults.marginBottom || 0,
-      zIndex: defaults.zIndex || 0
+      fixedSize: defaults.fixedSize !== undefined ? defaults.fixedSize as boolean : false,
+      dynamicPositioning: defaults.dynamicPositioning !== undefined ? defaults.dynamicPositioning as boolean : false,
+      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,
+      gridColumnStart: defaults.gridColumnStart !== undefined ? defaults.gridColumnStart as number : 1,
+      gridColumnEnd: defaults.gridColumnEnd !== undefined ? defaults.gridColumnEnd as number : 2,
+      gridRowStart: defaults.gridRowStart !== undefined ? defaults.gridRowStart as number : 1,
+      gridRowEnd: defaults.gridRowEnd !== undefined ? defaults.gridRowEnd as number : 2,
+      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 initBasicStyles(defaults: Record<string, any>): BasicStyles {
+  static initBasicStyles(defaults: Record<string, UIElementValue> = {}): BasicStyles {
     return {
-      fontColor: defaults.fontColor || '#000000',
-      font: defaults.font || 'Roboto',
-      fontSize: defaults.fontSize || 20,
-      bold: defaults.bold || false,
-      italic: defaults.italic || false,
-      underline: defaults.underline || false,
-      backgroundColor: defaults.backgroundColor || '#d3d3d3'
+      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: Record<string, any> = {}): PlayerProperties {
+  static initPlayerProps(defaults: Record<string, UIElementValue> = {}): PlayerProperties {
     return {
-      autostart: defaults.autostart || false,
-      autostartDelay: defaults.autostartDelay || 0,
-      loop: defaults.loop || false,
-      startControl: defaults.startControl || true,
-      pauseControl: defaults.pauseControl || false,
-      progressBar: defaults.progressBar || true,
-      interactiveProgressbar: defaults.interactiveProgressbar || undefined,
-      volumeControl: defaults.volumeControl || true,
-      defaultVolume: defaults.defaultVolume || 0.8,
-      minVolume: defaults.minVolume || 0,
-      muteControl: defaults.muteControl || true,
-      interactiveMuteControl: defaults.interactiveMuteControl || undefined,
-      hintLabel: defaults.hintLabel || '',
-      hintLabelDelay: defaults.hintLabelDelay || 0,
-      activeAfterID: defaults.activeAfterID || '',
-      minRuns: defaults.minRuns || 1,
-      maxRuns: defaults.maxRuns || null,
-      showRestRuns: defaults.showRestRuns || false,
-      showRestTime: defaults.showRestTime || true,
-      playbackTime: defaults.playbackTime || 0
+      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, // TODO default?
+      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, // TODO default?
+      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
     };
   }
 
@@ -203,286 +209,302 @@ export abstract class ElementFactory {
     }
   }
 
-  private static createButtonElement(defaults: Record<string, any> = {}): ButtonElement {
+  private static createButtonElement(element: Partial<ButtonElement>): ButtonElement {
     return {
-      ...ElementFactory.initElement('button', defaults),
+      ...ElementFactory.initElement(element),
       type: 'button',
-      label: 'Knopf',
-      imageSrc: null,
-      action: null,
-      actionParam: null,
-      positionProps: ElementFactory.initPositionProps(defaults.positionProps),
-      styles: {
-        ...ElementFactory.initBasicStyles(defaults),
-        borderRadius: 0
+      label: element.label !== undefined ? element.label : 'Knopf',
+      imageSrc: element.imageSrc || null,
+      action: element.action || null,
+      actionParam: element.actionParam || null,
+      position: ElementFactory.initPositionProps(element.positionProps as Record<string, UIElementValue>),
+      styling: {
+        ...ElementFactory.initBasicStyles(element.styling),
+        borderRadius: element.borderRadius !== undefined ? element.borderRadius as number : 0
       }
     };
   }
 
-  private static createCheckboxElement(defaults: Record<string, any> = {}): CheckboxElement {
+  private static createCheckboxElement(element: Partial<CheckboxElement>): CheckboxElement {
     return {
-      ...ElementFactory.initInputElement('checkbox', { width: 215, ...defaults }),
+      ...ElementFactory.initInputElement({ width: 215, ...element }),
       type: 'checkbox',
-      value: false,
-      positionProps: ElementFactory.initPositionProps(defaults),
-      styles: ElementFactory.initBasicStyles(defaults)
+      value: element.value !== undefined ? element.value : false,
+      position: ElementFactory.initPositionProps(element.position),
+      styling: ElementFactory.initBasicStyles(element.styling)
     };
   }
 
-  private static createClozeElement(defaults: Record<string, any> = {}): ClozeElement {
+  private static createClozeElement(element: Partial<ClozeElement>): ClozeElement {
     return {
-      ...ElementFactory.initElement('cloze', { width: 450, height: 200, ...defaults }),
+      ...ElementFactory.initElement({ width: 450, height: 200, ...element }),
       type: 'cloze',
-      document: { type: 'doc', content: [] },
-      positionProps: ElementFactory.initPositionProps(defaults),
-      styles: {
-        ...ElementFactory.initBasicStyles(defaults),
-        lineHeight: 135
+      document: element.document !== undefined ? element.document : { type: 'doc', content: [] },
+      position: ElementFactory.initPositionProps(element.position),
+      styling: {
+        ...ElementFactory.initBasicStyles(element.styling),
+        lineHeight: element.lineHeight !== undefined ? element.lineHeight as number : 135
       }
     };
   }
 
-  private static createDropdownElement(defaults: Record<string, any> = {}): DropdownElement {
+  private static createDropdownElement(element: Partial<DropdownElement>): DropdownElement {
     return {
-      ...ElementFactory.initInputElement('dropdown', { width: 240, height: 83, ...defaults }),
+      ...ElementFactory.initInputElement({ width: 240, height: 83, ...element }),
       type: 'dropdown',
-      options: [],
-      allowUnset: false,
-      positionProps: ElementFactory.initPositionProps(defaults),
-      styles: ElementFactory.initBasicStyles(defaults)
+      options: element.options !== undefined ? element.options : [],
+      allowUnset: element.allowUnset !== undefined ? element.allowUnset : false,
+      position: ElementFactory.initPositionProps(element),
+      styling: ElementFactory.initBasicStyles(element.styling)
     };
   }
 
-  private static createDropListElement(defaults: Record<string, any> = {}): DropListElement {
+  private static createDropListElement(element: Partial<DropListElement>): DropListElement {
     return {
-      ...ElementFactory.initInputElement('drop-list', { height: 100, ...defaults }),
+      ...ElementFactory.initInputElement({ height: 100, ...element }),
       type: 'drop-list',
-      value: [],
-      onlyOneItem: false,
-      connectedTo: [],
-      orientation: 'vertical',
-      highlightReceivingDropList: false,
-      highlightReceivingDropListColor: '#006064',
-      positionProps: ElementFactory.initPositionProps({ useMinHeight: true, ...defaults }),
-      styles: {
-        ...ElementFactory.initBasicStyles({ backgroundColor: '#f4f4f2', ...defaults }),
-        itemBackgroundColor: '#c9e0e0'
+      value: element.value !== undefined ? element.value : [],
+      onlyOneItem: element.onlyOneItem !== undefined ? element.onlyOneItem : false,
+      connectedTo: element.connectedTo !== undefined ? element.connectedTo : [],
+      orientation: element.orientation !== undefined ? element.orientation : 'vertical',
+      highlightReceivingDropList: element.highlightReceivingDropList !== undefined ?
+        element.highlightReceivingDropList :
+        false,
+      highlightReceivingDropListColor: element.highlightReceivingDropListColor !== undefined ?
+        element.highlightReceivingDropListColor : '#006064',
+      position: ElementFactory.initPositionProps({ useMinHeight: true, ...element }),
+      styling: {
+        ...ElementFactory.initBasicStyles({ backgroundColor: '#f4f4f2', ...element.styling }),
+        itemBackgroundColor: element.itemBackgroundColor !== undefined ?
+          element.itemBackgroundColor as string : '#c9e0e0'
       }
     };
   }
 
-  private static createDropListSimpleElement(defaults: Record<string, any> = {}): DropListSimpleElement {
+  private static createDropListSimpleElement(element: Partial<DropListSimpleElement>): DropListSimpleElement {
     return {
-      ...ElementFactory.initInputElement('drop-list-simple', { height: 100, ...defaults }),
+      ...ElementFactory.initInputElement({ height: 100, ...element }),
       type: 'drop-list',
-      value: [],
-      connectedTo: [],
-      highlightReceivingDropList: false,
-      highlightReceivingDropListColor: '#add8e6',
-      styles: {
-        ...ElementFactory.initBasicStyles({ backgroundColor: '#eeeeec', ...defaults }),
-        itemBackgroundColor: '#add8e6'
+      value: element.value !== undefined ? element.value : [],
+      connectedTo: element.connectedTo !== undefined ? element.connectedTo : [],
+      highlightReceivingDropList: element.highlightReceivingDropList !== undefined ?
+        element.highlightReceivingDropList : false,
+      highlightReceivingDropListColor: element.highlightReceivingDropListColor !== undefined ?
+        element.highlightReceivingDropListColor : '#add8e6',
+      styling: {
+        ...ElementFactory.initBasicStyles({ backgroundColor: '#eeeeec', ...element.styling }),
+        itemBackgroundColor: element.itemBackgroundColor !== undefined ?
+          element.itemBackgroundColor as string : '#add8e6'
       }
     };
   }
 
-  private static createFrameElement(defaults: Record<string, any> = {}): FrameElement {
+  private static createFrameElement(element: Partial<FrameElement>): FrameElement {
     return {
-      ...ElementFactory.initElement('frame', {}),
+      ...ElementFactory.initElement({}),
       type: 'frame',
-      positionProps: ElementFactory.initPositionProps({ zIndex: -1, ...defaults }),
-      styles: {
-        ...ElementFactory.initBasicStyles({ backgroundColor: 'transparent', ...defaults }),
-        borderWidth: 1,
-        borderColor: 'black',
-        borderStyle: 'solid',
-        borderRadius: 0
+      position: ElementFactory.initPositionProps({ zIndex: -1, ...element }),
+      styling: {
+        ...ElementFactory.initBasicStyles({ backgroundColor: 'transparent', ...element.styling }) as BasicStyles,
+        borderWidth: element.borderWidth !== undefined ? element.borderWidth as number : 1,
+        borderColor: element.borderColor !== undefined ? element.borderColor as string : 'black',
+        borderStyle: element.borderStyle !== undefined ?
+          element.borderStyle as 'solid' | 'dotted' | 'dashed' | 'double' | 'groove' |
+          'ridge' | 'inset' | 'outset' :
+          'solid',
+        borderRadius: element.borderRadius !== undefined ? element.borderRadius as number : 0
       }
     };
   }
 
-  private static createImageElement(defaults: Record<string, any> = {}): ImageElement {
+  private static createImageElement(element: Partial<ImageElement>): ImageElement {
     return {
-      ...ElementFactory.initElement('image', { height: 100, ...defaults }),
+      ...ElementFactory.initElement({ height: 100, ...element }),
       type: 'image',
-      src: defaults.src || '', // TODO eigentlich undefined
-      scale: false,
-      magnifier: false,
-      magnifierSize: 100,
-      magnifierZoom: 1.5,
-      magnifierUsed: false,
-      positionProps: ElementFactory.initPositionProps({})
+      src: element.src || '', // TODO eigentlich undefined
+      scale: element.scale !== undefined ? element.scale : false,
+      magnifier: element.magnifier !== undefined ? element.magnifier : false,
+      magnifierSize: element.magnifierSize !== undefined ? element.magnifierSize : 100,
+      magnifierZoom: element.magnifierZoom !== undefined ? element.magnifierZoom : 1.5,
+      magnifierUsed: element.magnifierUsed !== undefined ? element.magnifierUsed : false,
+      position: ElementFactory.initPositionProps({})
     };
   }
 
-  private static createLikertElement(defaults: Record<string, any> = {}): LikertElement {
+  private static createLikertElement(element: Partial<LikertElement>): LikertElement {
     return {
-      ...ElementFactory.initElement('likert', { width: 250, height: 200, ...defaults }),
+      ...ElementFactory.initElement({ width: 250, height: 200, ...element }),
       type: 'likert',
-      rows: [],
-      columns: [],
-      firstColumnSizeRatio: 5,
-      readOnly: false,
-      positionProps: ElementFactory.initPositionProps({ marginBottom: 30, ...defaults }),
-      styles: {
-        ...ElementFactory.initBasicStyles({ backgroundColor: 'transparent', ...defaults }),
-        lineHeight: 135,
-        lineColoring: true,
-        lineColoringColor: '#c9e0e0'
+      rows: element.rows !== undefined ? element.rows : [],
+      columns: element.columns !== undefined ? element.columns : [],
+      firstColumnSizeRatio: element.firstColumnSizeRatio !== undefined ? element.firstColumnSizeRatio : 5,
+      readOnly: element.readOnly !== undefined ? element.readOnly : false,
+      position: ElementFactory.initPositionProps({ marginBottom: 30, ...element }),
+      styling: {
+        ...ElementFactory.initBasicStyles({ backgroundColor: 'transparent', ...element }),
+        lineHeight: element.lineHeight !== undefined ? element.lineHeight as number : 135,
+        lineColoring: element.lineColoring !== undefined ? element.lineColoring as boolean : true,
+        lineColoringColor: element.lineColoringColor !== undefined ? element.lineColoringColor as string : '#c9e0e0'
       }
     };
   }
 
-  static createLikertRowElement(defaults: Record<string, any>): LikertRowElement {
+  static createLikertRowElement(element: Partial<LikertRowElement>): LikertRowElement {
     return {
-      ...ElementFactory.initInputElement('likert_row', defaults),
+      ...ElementFactory.initInputElement(element),
       type: 'likert-row',
-      text: defaults.text || '',
-      columnCount: defaults.columnCount || 0,
-      firstColumnSizeRatio: defaults.firstColumnSizeRatio || 5
+      text: element.text !== undefined ? element.text : '',
+      columnCount: element.columnCount !== undefined ? element.columnCount : 0,
+      firstColumnSizeRatio: element.firstColumnSizeRatio !== undefined ? element.firstColumnSizeRatio : 5
     };
   }
 
-  private static createRadioButtonGroupElement(defaults: Record<string, any> = {}): RadioButtonGroupElement {
+  private static createRadioButtonGroupElement(element: Partial<RadioButtonGroupElement>): RadioButtonGroupElement {
     return {
-      ...ElementFactory.initInputElement('radio', { height: 85, ...defaults }),
+      ...ElementFactory.initInputElement({ height: 85, ...element }),
       type: 'radio',
-      options: [],
-      alignment: 'column',
-      strikeOtherOptions: false,
-      positionProps: ElementFactory.initPositionProps({ marginBottom: 30, ...defaults }),
-      styles: ElementFactory.initBasicStyles({ backgroundColor: 'transparent', ...defaults })
+      options: element.options !== undefined ? element.options : [],
+      alignment: element.alignment !== undefined ? element.alignment : 'column',
+      strikeOtherOptions: element.strikeOtherOptions !== undefined ? element.strikeOtherOptions : false,
+      position: ElementFactory.initPositionProps({ marginBottom: 30, ...element.position }),
+      styling: ElementFactory.initBasicStyles({ backgroundColor: 'transparent', ...element.styling })
     };
   }
 
-  private static createRadioButtonGroupComplexElement(defaults: Record<string, any> = {}): RadioButtonGroupComplexElement {
+  private static createRadioButtonGroupComplexElement(element: Partial<RadioButtonGroupComplexElement>):
+  RadioButtonGroupComplexElement {
     return {
-      ...ElementFactory.initInputElement('radio-group-images', { height: 100, ...defaults }), // TODO better name
+      ...ElementFactory.initInputElement({ height: 100, ...element }), // TODO better name
       type: 'radio-group-images',
-      columns: [],
-      positionProps: ElementFactory.initPositionProps(defaults),
-      styles: ElementFactory.initBasicStyles({ backgroundColor: 'transparent', ...defaults })
+      columns: element.columns !== undefined ? element.columns : [],
+      position: ElementFactory.initPositionProps(element.position),
+      styling: ElementFactory.initBasicStyles({ backgroundColor: 'transparent', ...element.styling })
     };
   }
 
-  private static createSliderElement(defaults: Record<string, any> = {}): SliderElement {
+  private static createSliderElement(element: Partial<SliderElement>): SliderElement {
     return {
-      ...ElementFactory.initInputElement('slider', { width: 300, height: 75, ...defaults }),
+      ...ElementFactory.initInputElement({ width: 300, height: 75, ...element }),
       type: 'slider',
-      minValue: 0,
-      maxValue: 100,
-      showValues: true,
-      barStyle: false,
-      thumbLabel: false,
-      positionProps: ElementFactory.initPositionProps(defaults),
-      styles: ElementFactory.initBasicStyles({ backgroundColor: 'transparent', ...defaults })
+      minValue: element.minValue !== undefined ? element.minValue : 0,
+      maxValue: element.maxValue !== undefined ? element.maxValue : 100,
+      showValues: element.showValues !== undefined ? element.showValues : true,
+      barStyle: element.barStyle !== undefined ? element.barStyle : false,
+      thumbLabel: element.thumbLabel !== undefined ? element.thumbLabel : false,
+      position: ElementFactory.initPositionProps(element.position),
+      styling: ElementFactory.initBasicStyles({ backgroundColor: 'transparent', ...element.styling })
     };
   }
 
-  private static createSpellCorrectElement(defaults: Record<string, any> = {}): SpellCorrectElement {
+  private static createSpellCorrectElement(element: Partial<SpellCorrectElement>): SpellCorrectElement {
     return {
-      ...ElementFactory.initInputElement('spell-correct', { width: 230, height: 80, ...defaults }),
+      ...ElementFactory.initInputElement({ width: 230, height: 80, ...element }),
       type: 'spell-correct',
-      positionProps: ElementFactory.initPositionProps(defaults),
-      styles: ElementFactory.initBasicStyles({ backgroundColor: 'transparent', ...defaults })
+      position: ElementFactory.initPositionProps(element.position),
+      styling: ElementFactory.initBasicStyles({ backgroundColor: 'transparent', ...element.styling })
     };
   }
 
-  private static createTextElement(defaults: Record<string, any> = {}): TextElement {
+  private static createTextElement(element: Partial<TextElement>): TextElement {
     return {
-      ...ElementFactory.initElement('text', { height: 98, ...defaults }),
+      ...ElementFactory.initElement({ height: 98, ...element }),
       type: 'text',
-      text: 'Lorem ipsum dolor sit amet',
-      highlightableOrange: false,
-      highlightableTurquoise: false,
-      highlightableYellow: false,
-      positionProps: ElementFactory.initPositionProps(defaults),
-      styles: {
-        ...ElementFactory.initBasicStyles({ backgroundColor: 'transparent', ...defaults }),
-        lineHeight: 135
+      text: element.text !== undefined ? element.text : 'Lorem ipsum dolor sit amet',
+      highlightableOrange: element.highlightableOrange !== undefined ? element.highlightableOrange : false,
+      highlightableTurquoise: element.highlightableTurquoise !== undefined ? element.highlightableTurquoise : false,
+      highlightableYellow: element.highlightableYellow !== undefined ? element.highlightableYellow : false,
+      position: ElementFactory.initPositionProps(element.position),
+      styling: {
+        ...ElementFactory.initBasicStyles({ backgroundColor: 'transparent', ...element.styling }),
+        lineHeight: element.lineHeight !== undefined ? element.lineHeight as number : 135
       }
     };
   }
 
-  private static createTextAreaElement(defaults: Record<string, any> = {}): TextAreaElement {
+  private static createTextAreaElement(element: Partial<TextAreaElement>): TextAreaElement {
     return {
-      ...ElementFactory.initInputElement('text-area', { width: 230, height: 132, ...defaults }),
+      ...ElementFactory.initInputElement({ width: 230, height: 132, ...element }),
       type: 'text-area',
-      appearance: 'outline',
-      resizeEnabled: false,
-      rowCount: 3,
-      inputAssistancePreset: 'none',
-      inputAssistancePosition: 'floating',
-      positionProps: ElementFactory.initPositionProps(defaults),
-      styles: {
-        ...ElementFactory.initBasicStyles({ backgroundColor: 'transparent', ...defaults }),
-        lineHeight: 135
+      appearance: element.appearance !== undefined ? element.appearance : 'outline',
+      resizeEnabled: element.resizeEnabled !== undefined ? element.resizeEnabled : false,
+      rowCount: element.rowCount !== undefined ? element.rowCount : 3,
+      inputAssistancePreset: element.inputAssistancePreset !== undefined ? element.inputAssistancePreset : 'none',
+      inputAssistancePosition: element.inputAssistancePosition !== undefined ?
+        element.inputAssistancePosition : 'floating',
+      position: ElementFactory.initPositionProps(element.position),
+      styling: {
+        ...ElementFactory.initBasicStyles({ backgroundColor: 'transparent', ...element.styling }),
+        lineHeight: element.lineHeight !== undefined ? element.lineHeight as number : 135
       }
     };
   }
 
-  private static createTextFieldElement(defaults: Record<string, any> = {}): TextFieldElement {
+  private static createTextFieldElement(element: Partial<TextFieldElement>): TextFieldElement {
     return {
-      ...ElementFactory.initInputElement('text-field', { width: 230, height: 100, ...defaults }),
+      ...ElementFactory.initInputElement({ width: 230, height: 100, ...element }),
       type: 'text-field',
-      appearance: 'outline',
-      minLength: 0,
-      minLengthWarnMessage: 'Eingabe zu kurz',
-      maxLength: 0,
-      maxLengthWarnMessage: 'Eingabe zu lang',
-      pattern: '',
-      patternWarnMessage: 'Eingabe entspricht nicht der Vorgabe',
-      inputAssistancePreset: 'none',
-      inputAssistancePosition: 'floating',
-      clearable: false,
-      positionProps: ElementFactory.initPositionProps(defaults),
-      styles: ElementFactory.initBasicStyles({ backgroundColor: 'transparent', ...defaults })
+      appearance: element.appearance !== undefined ? element.appearance : 'outline',
+      minLength: element.minLength !== undefined ? element.minLength : 0,
+      minLengthWarnMessage: element.minLengthWarnMessage !== undefined ?
+        element.minLengthWarnMessage : 'Eingabe zu kurz',
+      maxLength: element.maxLength !== undefined ? element.maxLength : 0,
+      maxLengthWarnMessage: element.maxLengthWarnMessage !== undefined ?
+        element.maxLengthWarnMessage : 'Eingabe zu lang',
+      pattern: element.pattern !== undefined ? element.pattern : '',
+      patternWarnMessage: element.patternWarnMessage !== undefined ?
+        element.patternWarnMessage : 'Eingabe entspricht nicht der Vorgabe',
+      inputAssistancePreset: element.inputAssistancePreset !== undefined ? element.inputAssistancePreset : 'none',
+      inputAssistancePosition: element.inputAssistancePosition !== undefined ?
+        element.inputAssistancePosition : 'floating',
+      clearable: element.clearable !== undefined ? element.clearable : false,
+      position: ElementFactory.initPositionProps(element.position),
+      styling: ElementFactory.initBasicStyles({ backgroundColor: 'transparent', ...element.styling })
     };
   }
 
-  private static createTextFieldSimpleElement(defaults: Record<string, any> = {}): TextFieldSimpleElement {
+  private static createTextFieldSimpleElement(element: Partial<TextFieldSimpleElement>): TextFieldSimpleElement {
     return {
-      ...ElementFactory.initInputElement('text-field', { height: 25, ...defaults }),
+      ...ElementFactory.initInputElement({ height: 25, ...element }),
       type: 'text-field',
-      label: undefined,
-      styles: ElementFactory.initBasicStyles(defaults)
+      label: element.label !== undefined ? element.label : undefined,
+      styling: ElementFactory.initBasicStyles(element.styling)
     };
   }
 
-  private static createToggleButtonElement(defaults: Record<string, any> = {}): ToggleButtonElement {
+  private static createToggleButtonElement(element: Partial<ToggleButtonElement>): ToggleButtonElement {
     return {
-      ...ElementFactory.initInputElement('toggle-button', { height: 25, ...defaults }),
+      ...ElementFactory.initInputElement({ height: 25, ...element }),
       type: 'toggle-button',
-      options: [],
-      strikeOtherOptions: false,
-      selectionColor: 'lightgreen',
-      verticalOrientation: false,
-      dynamicWidth: true,
-      styles: {
-        ...ElementFactory.initBasicStyles({ backgroundColor: 'transparent', ...defaults }),
-        lineHeight: 135
+      options: element.options !== undefined ? element.options : [],
+      strikeOtherOptions: element.strikeOtherOptions !== undefined ? element.strikeOtherOptions : false,
+      selectionColor: element.selectionColor !== undefined ? element.selectionColor : 'lightgreen',
+      verticalOrientation: element.verticalOrientation !== undefined ? element.verticalOrientation : false,
+      dynamicWidth: element.dynamicWidth !== undefined ? element.dynamicWidth : true,
+      styling: {
+        ...ElementFactory.initBasicStyles({ backgroundColor: 'transparent', ...element }),
+        lineHeight: element.lineHeight !== undefined ? element.lineHeight as number : 135
       }
     };
   }
 
-  private static createAudioElement(defaults: Record<string, any> = {}): AudioElement {
+  private static createAudioElement(element: Partial<AudioElement>): AudioElement {
     return {
-      ...ElementFactory.initElement('audio', { width: 250, height: 90, ...defaults }),
+      ...ElementFactory.initElement({ width: 250, height: 90, ...element }),
       type: 'audio',
-      src: defaults.src || '', // TODO eigentlich undefined
-      positionProps: ElementFactory.initPositionProps(defaults),
-      playerProps: ElementFactory.initPlayerProps(defaults)
+      src: element.src !== undefined ? element.src : '', // TODO eigentlich undefined
+      position: ElementFactory.initPositionProps(element.position),
+      player: ElementFactory.initPlayerProps(element.player)
     };
   }
 
-  private static createVideoElement(defaults: Record<string, any> = {}): VideoElement {
+  private static createVideoElement(element: Partial<VideoElement>): VideoElement {
     return {
-      ...ElementFactory.initElement('video', { width: 280, height: 230, ...defaults }),
+      ...ElementFactory.initElement({ width: 280, height: 230, ...element }),
       type: 'video',
-      src: defaults.src || '', // TODO eigentlich undefined
-      scale: false,
-      positionProps: ElementFactory.initPositionProps(defaults),
-      playerProps: ElementFactory.initPlayerProps(defaults)
+      src: element.src !== undefined ? element.src : '', // TODO eigentlich undefined
+      scale: element.scale !== undefined ? element.scale : false,
+      position: ElementFactory.initPositionProps(element.position),
+      player: ElementFactory.initPlayerProps(element.player)
     };
   }
 }
diff --git a/projects/common/util/unit-definition-sanitizer.ts b/projects/common/util/unit-definition-sanitizer.ts
index 0dca30bca..84539163b 100644
--- a/projects/common/util/unit-definition-sanitizer.ts
+++ b/projects/common/util/unit-definition-sanitizer.ts
@@ -1,199 +1,241 @@
 import { Editor } from '@tiptap/core';
 import StarterKit from '@tiptap/starter-kit';
-import { Page, Unit } from '../interfaces/unit';
+import { Page, Section, Unit } from '../interfaces/unit';
 import {
-  DragNDropValueObject, DropListElement, PlayerElement, UIElement, UIElementValue
+  ClozeElement,
+  DragNDropValueObject,
+  DropListElement,
+  ElementStyling, InputElement,
+  PlayerProperties, PositionedElement,
+  PositionProperties, TextElement,
+  UIElement,
+  UIElementValue
 } from '../interfaces/elements';
+import { IdService } from '../../editor/src/app/services/id.service';
+import packageJSON from '../../../package.json';
+import { MessageService } from '../services/message.service';
 import ToggleButtonExtension from '../tiptap-editor-extensions/toggle-button';
 import DropListExtension from '../tiptap-editor-extensions/drop-list';
 import TextFieldExtension from '../tiptap-editor-extensions/text-field';
-import { IdService } from '../../editor/src/app/services/id.service';
+import { ClozeDocument, ClozeDocumentParagraph, ClozeDocumentParagraphPart } from '../interfaces/cloze';
 
 export abstract class UnitDefinitionSanitizer {
-  private static unitVersion: [number, number, number] = [0, 0, 0];
-
-  static campatibilityHandlers: { (s: UIElement[]): void; }[] = [
-    UnitDefinitionSanitizer.handlePositionProps,
-    UnitDefinitionSanitizer.handleFontProps,
-    UnitDefinitionSanitizer.handleSurfaceProps,
-    UnitDefinitionSanitizer.handlePlayerProps,
-    UnitDefinitionSanitizer.handleTextElements,
-    UnitDefinitionSanitizer.handleClozeElements,
-    UnitDefinitionSanitizer.handleDropListElements,
-    UnitDefinitionSanitizer.handlePlusOne
-  ];
-
-  static sanitize(unitDefinition: Partial<Unit> & { pages: Page[], veronaModuleVersion?: string }): Unit {
-    UnitDefinitionSanitizer.unitVersion = unitDefinition.unitDefinitionType?.split('.')
-      .map(el => Number(el)) as [number, number, number] ||
-      unitDefinition.veronaModuleVersion?.split('.')
-        .map(el => Number(el)) as [number, number, number];
-    const elementList = UnitDefinitionSanitizer.getElementList(unitDefinition as Unit);
-    UnitDefinitionSanitizer.campatibilityHandlers.forEach(handler => handler(elementList));
-    return unitDefinition as Unit;
+  private static unitVersion: [number, number, number] =
+  packageJSON.config.unit_definition_version.split('.') as unknown as [number, number, number];
+
+  static sanitizeUnitDefinition(unitDefinition: Unit & { veronaModuleVersion?: string }): Unit {
+    if (UnitDefinitionSanitizer.checkVersion(unitDefinition)) return unitDefinition;
+
+    const x = {
+      ...unitDefinition,
+      pages: unitDefinition.pages.map((page: Page) => UnitDefinitionSanitizer.sanatizePage(page))
+    };
+    return x as Unit;
   }
 
-  private static getElementList(unitDefinition: Unit): UIElement[] {
-    return unitDefinition.pages.flat().map(page => page.sections.map(section => section.elements)).flat(2);
+  private static checkVersion(unitDefinition: Unit & { veronaModuleVersion?: string }) : boolean {
+    const defVersion: [number, number, number] =
+      unitDefinition.veronaModuleVersion?.split('@')[1].split('.') as unknown as [number, number, number];
+    if (!UnitDefinitionSanitizer.isVersionOlderThanCurrent(defVersion)) {
+      return true;
+    }
+    MessageService.getInstance().showWarning('Loaded an outdated unit definition');
+    return false;
   }
 
-  private static handlePositionProps(elementList: UIElement[]): void {
-    const positionProps = ['xPosition', 'yPosition',
-      'useMinHeight', 'gridColumnStart', 'gridColumnEnd', 'gridRowStart', 'gridRowEnd', 'marginLeft',
-      'marginRight', 'marginTop', 'marginBottom', 'zIndex', 'fixedSize', 'dynamicPositioning'];
-    UnitDefinitionSanitizer.movePropertiesToSubObject(elementList, 'positionProps', positionProps);
+  private static isVersionOlderThanCurrent(version: [number, number, number]): boolean {
+    if (version[0] < UnitDefinitionSanitizer.unitVersion[0]) {
+      return true;
+    }
+    if (version[1] < UnitDefinitionSanitizer.unitVersion[1]) {
+      return true;
+    }
+    return version[2] < UnitDefinitionSanitizer.unitVersion[2];
   }
 
-  private static handleFontProps(elementList: UIElement[]): void {
-    const fontProps = ['fontColor', 'font', 'fontSize', 'lineHeight', 'bold', 'italic', 'underline'];
-    UnitDefinitionSanitizer.movePropertiesToSubObject(elementList,
-      'styles',
-      fontProps,
-      'fontProps');
+  static sanatizePage(page: Page): Page {
+    return {
+      ...page,
+      sections: page.sections.map((section: Section) => UnitDefinitionSanitizer.sanatizeSection(section))
+    };
   }
 
-  private static handleSurfaceProps(elementList: UIElement[]): void {
-    UnitDefinitionSanitizer.movePropertiesToSubObject(elementList,
-      'styles',
-      ['backgroundColor'],
-      'surfaceProps');
+  static sanatizeSection(section: Section): Section {
+    return {
+      ...section,
+      elements: section.elements.map((element: UIElement) => (
+        UnitDefinitionSanitizer.sanatizeElement(element))) as PositionedElement[]
+    };
   }
 
-  private static handlePlayerProps(elementList: UIElement[]): void {
-    const playerProps = ['autostart', 'autostartDelay', 'loop', 'startControl', 'pauseControl',
-      'progressBar', 'interactiveProgressbar', 'volumeControl', 'defaultVolume', 'minVolume',
-      'muteControl', 'interactiveMuteControl', 'hintLabel', 'hintLabelDelay', 'activeAfterID',
-      'minRuns', 'maxRuns', 'showRestRuns', 'showRestTime', 'playbackTime'];
-    const filteredElementList: PlayerElement[] =
-      elementList.filter(element => ['audio', 'video'].includes(element.type)) as PlayerElement[];
-    UnitDefinitionSanitizer.movePropertiesToSubObject(filteredElementList,'playerProps', playerProps);
-    filteredElementList.forEach((element: PlayerElement) => {
-      element.playerProps.defaultVolume = element.playerProps.defaultVolume || 0.8;
-      element.playerProps.minVolume = element.playerProps.minVolume || 0;
-    });
+  static sanatizeElement(element: Record<string, UIElementValue>): UIElement {
+    let newElement: Partial<UIElement> = {
+      ...element,
+      position: UnitDefinitionSanitizer.getPositionProps(element),
+      styling: UnitDefinitionSanitizer.getStyleProps(element),
+      player: UnitDefinitionSanitizer.getPlayerProps(element)
+    };
+    if (newElement.type === 'text') {
+      newElement = UnitDefinitionSanitizer.handleTextElement(newElement);
+    }
+    if (newElement.type === 'cloze') {
+      newElement = UnitDefinitionSanitizer.handleClozeElement(newElement as Record<string, UIElementValue>);
+    }
+    if (newElement.type === 'drop-list') {
+      newElement = UnitDefinitionSanitizer.handleDropListElement(newElement as Record<string, UIElementValue>);
+    }
+    if (['dropdown', 'radio', 'likert-row', 'radio-group-images', 'toggle-button']
+      .includes(newElement.type as string)) {
+      newElement = UnitDefinitionSanitizer.handlePlusOne(newElement as InputElement);
+    }
+    return newElement as unknown as UIElement;
   }
 
-  private static movePropertiesToSubObject(elementList: UIElement[],
-                                           targetPropertyGroup: string,
-                                           propertyList: string[],
-                                           alternativeSourceGroup?: string): void {
-    elementList.forEach((element: UIElement) => {
-      let actualValues: Record<string, UIElementValue> = {};
-      if (element[targetPropertyGroup]) {
-        actualValues = element[targetPropertyGroup] as Record<string, UIElementValue>;
-      } else if (alternativeSourceGroup && alternativeSourceGroup in element) {
-        actualValues = element[alternativeSourceGroup] as Record<string, UIElementValue>;
-        delete element[alternativeSourceGroup];
-      } else {
-        actualValues = Object.keys(element)
-          .filter(key => propertyList.includes(key))
-          .reduce((obj, key) => {
-            (obj as any)[key] = element[key];
-            return obj;
-          }, {});
-      }
+  private static getPositionProps(element: Record<string, UIElementValue>): PositionProperties {
+    if (element.position !== undefined) {
+      return element.position as PositionProperties;
+    }
+    if (element.positionProps !== undefined) {
+      return element.positionProps as PositionProperties;
+    }
+    return element as unknown as PositionProperties;
+  }
 
-      // delete old values
-      if (alternativeSourceGroup) delete element[alternativeSourceGroup];
-      propertyList.forEach(prop => delete element[prop]);
+  /* Style properties are expected to be in 'stylings'. If not they may be in fontProps and/or
+  *  surfaceProps. Even older versions had them in the root of the object, which is uses as last resort.
+  *  The styles object then has all other properties of the element, but that is not a problem
+  *  since the factory methods only use the values they care for and all others are discarded. */
+  private static getStyleProps(element: Record<string, UIElementValue>): ElementStyling {
+    if (element.styling !== undefined) {
+      return element.styling as ElementStyling;
+    }
+    if (element.fontProps !== undefined) {
+      return {
+        ...(element.fontProps as Record<string, any>),
+        backgroundColor: (element.surfaceProps as Record<string, any>)?.backgroundColor,
+        borderRadius: element.borderRadius as number | undefined,
+        itemBackgroundColor: element.itemBackgroundColor as string | undefined,
+        borderWidth: element.borderWidth as number | undefined,
+        borderColor: element.borderColor as string | undefined,
+        borderStyle: element.borderStyle as
+          'solid' | 'dotted' | 'dashed' | 'double' | 'groove' | 'ridge' | 'inset' | 'outset' | undefined,
+        lineColoring: element.lineColoring as boolean | undefined,
+        lineColoringColor: element.lineColoringColor as string | undefined
+      };
+    }
+    return element as ElementStyling;
+  }
 
-      if (Object.keys(actualValues).length > 0) {
-        (element[targetPropertyGroup] as Record<string, UIElementValue>) = actualValues;
-      }
-    });
+  private static getPlayerProps(element: Record<string, UIElementValue>): PlayerProperties {
+    if (element.playerProps !== undefined) {
+      return element.playerProps as PlayerProperties;
+    }
+    return element as unknown as PlayerProperties;
   }
 
-  private static handleTextElements(elementList: UIElement[]): void {
-    const textElements = elementList.filter(element => element.type === 'text');
-    textElements.forEach((element: Record<string, unknown>) => {
-      if (element.highlightable || element.interaction === 'highlightable') {
-        element.highlightableYellow = true;
-        element.highlightableTurquoise = true;
-        element.highlightableOrange = true;
-        delete element.interaction;
-        delete element.highlightable;
-      }
-      if (element.interaction === 'underlinable') {
-        element.highlightableYellow = true;
-        delete element.interaction;
-      }
-    });
+  private static handleTextElement(element: Record<string, UIElementValue>): TextElement {
+    const newElement = { ...element };
+    if (newElement.highlightable || newElement.interaction === 'highlightable') {
+      newElement.highlightableYellow = true;
+      newElement.highlightableTurquoise = true;
+      newElement.highlightableOrange = true;
+    }
+    if (newElement.interaction === 'underlinable') {
+      newElement.highlightableYellow = true;
+    }
+    return newElement as TextElement;
   }
 
   /*
-  Replace raw text with backslash-markers with JSON representation.
-  The TipTap editor module can automate that. It needs plugins though to be able
+  Replace raw text with backslash-markers with HTML tags.
+  The TipTap editor module can create JSOM from the HTML. It needs plugins though to be able
   to create ui-elements.
+  Afterwards element models are added to the JSON.
    */
-  private static handleClozeElements(elementList: UIElement[]): void {
-    const clozeElements = elementList.filter(element => element.type === 'cloze');
-    if (clozeElements.length && clozeElements[0].text) {
-      clozeElements.forEach((element: Record<string, any>) => {
-        const replacedText = element.text.replace(/\\i|\\z|\\r/g, (match: string) => {
-          switch (match) {
-            case '\\i':
-              return '<aspect-nodeview-text-field></aspect-nodeview-text-field>';
-            case '\\z':
-              return '<aspect-nodeview-drop-list></aspect-nodeview-drop-list>';
-            case '\\r':
-              return '<aspect-nodeview-toggle-button></aspect-nodeview-toggle-button>';
-            default:
-              throw Error('error in match');
-          }
-        });
-        const editor = new Editor({
-          extensions: [
-            StarterKit,
-            ToggleButtonExtension,
-            DropListExtension,
-            TextFieldExtension
-          ],
-          content: replacedText
-        });
-        element.document = editor.getJSON();
-        delete element.text;
-      });
-    }
-  }
+  private static handleClozeElement(element: Record<string, UIElementValue>): ClozeElement {
+    if (!element.parts || !element.text) throw Error('Can\'t read Cloze Element');
+    const uiElementParts = (element.parts as any[])
+      .map((el: any) => el
+        .filter((el2: { type: string; }) => ['text-field', 'drop-list', 'toggle-button'].includes(el2.type)))
+      .flat();
 
-  private static handleDropListElements(elementList: UIElement[]): void {
-    const dropListElements: DropListElement[] =
-      elementList.filter(element => element.type === 'drop-list') as DropListElement[];
-    dropListElements.forEach((element: DropListElement) => {
-      if (element.options) {
-        element.value = [];
-        (element.options as string[]).forEach(option => {
-          (element.value as DragNDropValueObject[]).push({
-            id: IdService.getInstance().getNewID('value'),
-            stringValue: option
-          });
-        });
-        delete element.options;
-      }
-      if (element.value && !((element.value as DragNDropValueObject[])[0] instanceof Object)) {
-        const newValues: DragNDropValueObject[] = [];
-        (element.value as string[]).forEach(value => {
-          newValues.push({
-            id: IdService.getInstance().getNewID('value'),
-            stringValue: value
-          });
-        });
-        element.value = newValues;
+    const replacedText = (element.text as string).replace(/\\i|\\z|\\r/g, (match: string) => {
+      switch (match) {
+        case '\\i':
+          return '<aspect-nodeview-text-field></aspect-nodeview-text-field>';
+        case '\\z':
+          return '<aspect-nodeview-drop-list></aspect-nodeview-drop-list>';
+        case '\\r':
+          return '<aspect-nodeview-toggle-button></aspect-nodeview-toggle-button>';
+        default:
+          throw Error('error in match');
       }
     });
+
+    const editor = new Editor({
+      extensions: [StarterKit, ToggleButtonExtension, DropListExtension, TextFieldExtension],
+      content: replacedText
+    });
+    const doc: { type: string, content: ClozeDocumentParagraph[] } =
+      editor.getJSON() as { type: string, content: ClozeDocumentParagraph[] };
+
+    return {
+      ...element,
+      document: {
+        ...doc,
+        content: doc.content
+          .map((paragraph: ClozeDocumentParagraph) => ({
+            ...paragraph,
+            content: paragraph.content
+              .map((paraPart: ClozeDocumentParagraphPart) => (
+                ['TextField', 'DropList', 'ToggleButton'].includes(paraPart.type) ?
+                  {
+                    ...paraPart,
+                    attrs: {
+                      ...paraPart.attrs,
+                      model: UnitDefinitionSanitizer.sanatizeElement(uiElementParts.shift().value)
+                    }
+                  } :
+                  {
+                    ...paraPart
+                  }
+              ))
+          }))
+      } as ClozeDocument
+    } as ClozeElement;
   }
 
-  // version 1.1.0 is the only version where there was a plus one for values, which we rolled back afterwards
-  private static handlePlusOne(elementList: UIElement[]): void {
-    if (UnitDefinitionSanitizer.unitVersion === [1, 1, 0]) {
-      elementList.filter(el => (
-        ['dropdown', 'radio', 'likert-row', 'radio-group-images', 'toggle-button'].includes(el.type)
-      ))
-        .forEach(element => {
-          if (element.value && element.value > 0) {
-            (element.value as number) -= 1;
-          }
+  private static handleDropListElement(element: Record<string, UIElementValue>): DropListElement {
+    const newElement = element;
+    if (newElement.options) {
+      newElement.value = [];
+      (newElement.options as string[]).forEach(option => {
+        (newElement.value as DragNDropValueObject[]).push({
+          id: IdService.getInstance().getNewID('value'),
+          stringValue: option
         });
+      });
     }
+    if (newElement.value && !((newElement.value as DragNDropValueObject[])[0] instanceof Object)) {
+      const newValues: DragNDropValueObject[] = [];
+      (newElement.value as string[]).forEach(value => {
+        newValues.push({
+          id: IdService.getInstance().getNewID('value'),
+          stringValue: value
+        });
+      });
+      newElement.value = newValues;
+    }
+    return newElement as DropListElement;
+  }
+
+  // version 1.1.0 is the only version where there was a plus one for values, which was rolled back afterwards.
+  private static handlePlusOne(element: InputElement): InputElement {
+    return ((UnitDefinitionSanitizer.unitVersion === [1, 1, 0]) && (element.value && element.value > 0)) ?
+      {
+        ...element,
+        value: (element.value as number) - 1
+      } :
+      element;
   }
 }
diff --git a/projects/common/util/unit.factory.ts b/projects/common/util/unit.factory.ts
index 626dbe56a..d3b748d3a 100644
--- a/projects/common/util/unit.factory.ts
+++ b/projects/common/util/unit.factory.ts
@@ -1,36 +1,41 @@
 import { Page, Section, Unit } from '../interfaces/unit';
+import { ElementFactory } from './element.factory';
+import { PositionedElement } from '../interfaces/elements';
+import packageJSON from '../../../package.json';
 
 export abstract class UnitFactory {
-  static generateEmptyUnit(): Unit {
+  static createUnit(unit?: Unit): Unit {
     return {
-      unitDefinitionType: 'TODO',
-      pages: [UnitFactory.generateEmptyPage()]
+      unitDefinitionType: `veronaModuleVersion@${packageJSON.config.unit_definition_version}`,
+      pages: unit?.pages ? unit.pages.map(page => UnitFactory.createPage(page)) : [UnitFactory.createPage()]
     };
   }
 
-  static generateEmptyPage(): Page {
+  static createPage(page?: Page): Page {
     return {
-      sections: [UnitFactory.generateEmptySection()],
-      hasMaxWidth: false,
-      maxWidth: 900,
-      margin: 30,
+      sections: page ? page.sections.map(section => UnitFactory.createSection(section)) : [UnitFactory.createSection()],
+      hasMaxWidth: page && page.hasMaxWidth !== undefined ? page.hasMaxWidth : false,
+      maxWidth: page && page.hasMaxWidth !== undefined ? page.maxWidth : 900,
+      margin: page && page.margin !== undefined ? page.margin : 30,
       backgroundColor: '#ffffff',
-      alwaysVisible: false,
+      alwaysVisible: page && page.alwaysVisible !== undefined ? page.alwaysVisible : false,
       alwaysVisiblePagePosition: 'left',
-      alwaysVisibleAspectRatio: 50
+      alwaysVisibleAspectRatio: page && page.alwaysVisibleAspectRatio !== undefined ? page.alwaysVisibleAspectRatio : 50
     };
   }
 
-  static generateEmptySection(): Section {
+  static createSection(section?: Section): Section {
     return {
-      elements: [],
-      height: 400,
+      elements: section ?
+        section.elements.map(element => ElementFactory.createElement(element) as PositionedElement) :
+        [],
+      height: section && section.height !== undefined ? section.height : 400,
       backgroundColor: 'white',
-      dynamicPositioning: false,
-      autoColumnSize: true,
-      autoRowSize: true,
-      gridColumnSizes: '1fr 1fr',
-      gridRowSizes: '1fr'
+      dynamicPositioning: section && section.dynamicPositioning !== undefined ? section.dynamicPositioning : false,
+      autoColumnSize: section && section.autoColumnSize !== undefined ? section.autoColumnSize : true,
+      autoRowSize: section && section.autoRowSize !== undefined ? section.autoRowSize : true,
+      gridColumnSizes: section && section.gridColumnSizes !== undefined ? section.gridColumnSizes : '1fr 1fr',
+      gridRowSizes: section && section.gridRowSizes !== undefined ? section.gridRowSizes : '1fr'
     };
   }
 }
diff --git a/projects/editor/src/app/components/unit-view/page-view/canvas/canvas.component.ts b/projects/editor/src/app/components/unit-view/page-view/canvas/canvas.component.ts
index 4f8a0e7d9..5f69ef872 100644
--- a/projects/editor/src/app/components/unit-view/page-view/canvas/canvas.component.ts
+++ b/projects/editor/src/app/components/unit-view/page-view/canvas/canvas.component.ts
@@ -80,7 +80,7 @@ export class CanvasComponent {
         event.container.data.sectionIndex);
     } else {
       selectedElements.forEach((element: PositionedElement) => {
-        let newXPosition = element.positionProps.xPosition + event.distance.x;
+        let newXPosition = element.position.xPosition + event.distance.x;
         if (newXPosition < 0) {
           newXPosition = 0;
         }
@@ -89,7 +89,7 @@ export class CanvasComponent {
         }
         this.unitService.updateElementProperty([element], 'xPosition', newXPosition);
 
-        let newYPosition = element.positionProps.yPosition + event.distance.y;
+        let newYPosition = element.position.yPosition + event.distance.y;
         if (newYPosition < 0) {
           newYPosition = 0;
         }
diff --git a/projects/editor/src/app/components/unit-view/page-view/canvas/overlays/dynamic-canvas-overlay.component.ts b/projects/editor/src/app/components/unit-view/page-view/canvas/overlays/dynamic-canvas-overlay.component.ts
index 36e3ce3c2..881425cf6 100644
--- a/projects/editor/src/app/components/unit-view/page-view/canvas/overlays/dynamic-canvas-overlay.component.ts
+++ b/projects/editor/src/app/components/unit-view/page-view/canvas/overlays/dynamic-canvas-overlay.component.ts
@@ -8,47 +8,47 @@ import { UIElement } from '../../../../../../../../common/interfaces/elements';
 @Component({
   selector: 'aspect-dynamic-canvas-overlay',
   template: `
-    <!-- TabIndex is needed to make the div selectable and catch keyboard events (delete). -->
-    <!-- DragStart and DragEnd are part of a cursor hack to style the body. See global styling file. -->
-    <div #draggableElement class="draggable-element"
-         [class.fixed-size-content-wrapper]="element.positionProps?.dynamicPositioning &&
-            element.positionProps?.fixedSize"
-         [class.temporaryHighlight]="temporaryHighlight"
-         [style.display]="dragging ? 'none' : ''"
-         tabindex="-1"
-         cdkDrag [cdkDragData]="{dragType: 'move', element: element}"
-         (click)="selectElement($event.shiftKey); $event.stopPropagation()" (dblclick)="openEditDialog()"
-         (cdkDragStarted)="moveDragStart()"
-         (cdkDragEnded)="moveDragEnd()"
-         [style.outline]="isSelected ? 'purple solid 1px' : ''"
-         [style.z-index]="isSelected ? 2 : 1">
-      <div *cdkDragPlaceholder></div>
-      <div *ngIf="isSelected"
-           [style.width.%]="dragging ? 100 : 0"
-           [style.height.%]="dragging ? 100 : 0"
-           cdkDrag [cdkDragData]="{dragType: 'resize', element: element}"
-           (cdkDragStarted)="resizeDragStart()" (cdkDragEnded)="resizeDragEnd()"
-           (cdkDragMoved)="resizeDragMove($event)">
-        <div class="resizeHandle">
-          <mat-icon>aspect_ratio</mat-icon>
+      <!-- TabIndex is needed to make the div selectable and catch keyboard events (delete). -->
+      <!-- DragStart and DragEnd are part of a cursor hack to style the body. See global styling file. -->
+      <div #draggableElement class="draggable-element"
+           [class.fixed-size-content-wrapper]="element.position?.dynamicPositioning &&
+            element.position?.fixedSize"
+           [class.temporaryHighlight]="temporaryHighlight"
+           [style.display]="dragging ? 'none' : ''"
+           tabindex="-1"
+           cdkDrag [cdkDragData]="{dragType: 'move', element: element}"
+           (click)="selectElement($event.shiftKey); $event.stopPropagation()" (dblclick)="openEditDialog()"
+           (cdkDragStarted)="moveDragStart()"
+           (cdkDragEnded)="moveDragEnd()"
+           [style.outline]="isSelected ? 'purple solid 1px' : ''"
+           [style.z-index]="isSelected ? 2 : 1">
           <div *cdkDragPlaceholder></div>
-        </div>
-      </div>
-      <div [class.fixed-size-content]="element.positionProps?.dynamicPositioning &&
-            element.positionProps?.fixedSize"
-           [style.width]="element.positionProps?.dynamicPositioning && element.positionProps?.fixedSize ?
+          <div *ngIf="isSelected"
+               [style.width.%]="dragging ? 100 : 0"
+               [style.height.%]="dragging ? 100 : 0"
+               cdkDrag [cdkDragData]="{dragType: 'resize', element: element}"
+               (cdkDragStarted)="resizeDragStart()" (cdkDragEnded)="resizeDragEnd()"
+               (cdkDragMoved)="resizeDragMove($event)">
+              <div class="resizeHandle">
+                  <mat-icon>aspect_ratio</mat-icon>
+                  <div *cdkDragPlaceholder></div>
+              </div>
+          </div>
+          <div [class.fixed-size-content]="element.position?.dynamicPositioning &&
+            element.position?.fixedSize"
+               [style.width]="element.position?.dynamicPositioning && element.position?.fixedSize ?
                       element.width + 'px' : '100%'"
-           [style.height]="element.positionProps?.dynamicPositioning && element.positionProps?.fixedSize ?
+               [style.height]="element.position?.dynamicPositioning && element.position?.fixedSize ?
                       element.height + 'px' : '100%'">
-        <ng-template #elementContainer></ng-template>
+              <ng-template #elementContainer></ng-template>
+          </div>
+      </div>
+      <div class="resize-preview"
+           [style.position]="'relative'"
+           [style.width.px]="dragging ? elementWidth : 0"
+           [style.height.px]="dragging ? elementHeight : 0"
+           [style.border]="'1px dashed purple'">
       </div>
-    </div>
-    <div class="resize-preview"
-         [style.position]="'relative'"
-         [style.width.px]="dragging ? elementWidth : 0"
-         [style.height.px]="dragging ? elementHeight : 0"
-         [style.border]="'1px dashed purple'">
-    </div>
   `,
   styles: [
     '.draggable-element {position: relative; width: 100%; height: 100%}',
diff --git a/projects/editor/src/app/components/unit-view/page-view/canvas/overlays/static-canvas-overlay.component.ts b/projects/editor/src/app/components/unit-view/page-view/canvas/overlays/static-canvas-overlay.component.ts
index 35759f408..a59f3fe1b 100644
--- a/projects/editor/src/app/components/unit-view/page-view/canvas/overlays/static-canvas-overlay.component.ts
+++ b/projects/editor/src/app/components/unit-view/page-view/canvas/overlays/static-canvas-overlay.component.ts
@@ -21,9 +21,9 @@ import { UIElement } from '../../../../../../../../common/interfaces/elements';
       <!-- Needs extra div because styling can interfere with drag and drop-->
       <div [style.position]="'absolute'"
            [style.outline]="isSelected ? '1px dashed purple' : ''"
-           [style.left.px]="element.positionProps?.xPosition"
-           [style.top.px]="element.positionProps?.yPosition"
-           [style.z-index]="element.positionProps?.zIndex">
+           [style.left.px]="element.position?.xPosition"
+           [style.top.px]="element.position?.yPosition"
+           [style.z-index]="element.position?.zIndex">
         <div *ngIf="isSelected" class="resizeHandle"
              cdkDrag (cdkDragStarted)="resizeDragStart()"
              (cdkDragMoved)="resizeElement($event)"
diff --git a/projects/editor/src/app/components/unit-view/page-view/canvas/section-dynamic.component.ts b/projects/editor/src/app/components/unit-view/page-view/canvas/section-dynamic.component.ts
index 9f4aa0865..b0d93a45f 100644
--- a/projects/editor/src/app/components/unit-view/page-view/canvas/section-dynamic.component.ts
+++ b/projects/editor/src/app/components/unit-view/page-view/canvas/section-dynamic.component.ts
@@ -10,54 +10,54 @@ import { UIElement, UIElementType } from '../../../../../../../common/interfaces
 @Component({
   selector: 'aspect-section-dynamic',
   template: `
-      <div [style.display]="'grid'"
-           [style.grid-template-columns]="section.autoColumnSize ? '' : section.gridColumnSizes"
-           [style.grid-template-rows]="section.autoRowSize ? '' : section.gridRowSizes"
-           [style.height.%]="100"
-           cdkDropListGroup
-           [style.border]="isSelected ? '2px solid #ff4081': '1px dotted'"
-           [style.height.px]="section.height"
-           [style.background-color]="section.backgroundColor">
+    <div [style.display]="'grid'"
+         [style.grid-template-columns]="section.autoColumnSize ? '' : section.gridColumnSizes"
+         [style.grid-template-rows]="section.autoRowSize ? '' : section.gridRowSizes"
+         [style.height.%]="100"
+         cdkDropListGroup
+         [style.border]="isSelected ? '2px solid #ff4081': '1px dotted'"
+         [style.height.px]="section.height"
+         [style.background-color]="section.backgroundColor">
 
-          <!-- Dynamic sections have the droplists for the grid cells next to the actual elements. Elements can not
-               be children of the grid cells because they can span over multiple cells. -->
-          <ng-container *ngFor="let column of this.section.gridColumnSizes.split(' '); let x = index">
-              <ng-container *ngFor="let row of this.section.gridRowSizes.split(' '); let y = index">
-                  <div class="grid-placeholder"
-                       [style.grid-column-start]="x + 1"
-                       [style.grid-column-end]="x + 1"
-                       [style.grid-row-start]="y + 1"
-                       [style.grid-row-end]="y + 1"
-                       cdkDropList [cdkDropListData]="{ sectionIndex: sectionIndex, gridCoordinates: [x + 1, y + 1] }"
-                       (cdkDropListDropped)="drop($any($event))"
-                       id="list-{{sectionIndex}}-{{x+1}}-{{y+1}}"
-                       (dragover)="$event.preventDefault()" (drop)="newElementDropped($event, x + 1, y + 1)">
-                      {{x + 1}} / {{y + 1}}
-                  </div>
-              </ng-container>
-          </ng-container>
+      <!-- Dynamic sections have the droplists for the grid cells next to the actual elements. Elements can not
+           be children of the grid cells because they can span over multiple cells. -->
+      <ng-container *ngFor="let column of this.section.gridColumnSizes.split(' '); let x = index">
+        <ng-container *ngFor="let row of this.section.gridRowSizes.split(' '); let y = index">
+          <div class="grid-placeholder"
+               [style.grid-column-start]="x + 1"
+               [style.grid-column-end]="x + 1"
+               [style.grid-row-start]="y + 1"
+               [style.grid-row-end]="y + 1"
+               cdkDropList [cdkDropListData]="{ sectionIndex: sectionIndex, gridCoordinates: [x + 1, y + 1] }"
+               (cdkDropListDropped)="drop($any($event))"
+               id="list-{{sectionIndex}}-{{x+1}}-{{y+1}}"
+               (dragover)="$event.preventDefault()" (drop)="newElementDropped($event, x + 1, y + 1)">
+              {{x + 1}} / {{y + 1}}
+          </div>
+        </ng-container>
+      </ng-container>
 
-          <aspect-dynamic-canvas-overlay *ngFor="let element of section.elements"
-                                         #elementComponent
-                                         [element]="$any(element)"
-                                         [style.min-width.px]="element.width"
-                                         [style.min-height.px]="element.height"
-                                         [style.margin-left.px]="element.positionProps.marginLeft"
-                                         [style.margin-right.px]="element.positionProps.marginRight"
-                                         [style.margin-top.px]="element.positionProps.marginTop"
-                                         [style.margin-bottom.px]="element.positionProps.marginBottom"
-                                         [style.grid-column-start]="element.positionProps.gridColumnStart"
-                                         [style.grid-column-end]="element.positionProps.gridColumnEnd"
-                                         [style.grid-row-start]="element.positionProps.gridRowStart"
-                                         [style.grid-row-end]="element.positionProps.gridRowEnd"
-                                         cdkDropList cdkDropListSortingDisabled
-                                         [cdkDropListData]="{ sectionIndex: sectionIndex }"
-                                         [cdkDropListConnectedTo]="dropListList"
-                                         (resize)="resizeOverlay($event)"
-                                         [style.position]="'relative'"
-                                         [style.pointer-events]="dragging ? 'none' : 'auto'">
-          </aspect-dynamic-canvas-overlay>
-      </div>
+      <aspect-dynamic-canvas-overlay *ngFor="let element of section.elements"
+                                     #elementComponent
+                                     [element]="$any(element)"
+                                     [style.min-width.px]="element.width"
+                                     [style.min-height.px]="element.height"
+                                     [style.margin-left.px]="element.position.marginLeft"
+                                     [style.margin-right.px]="element.position.marginRight"
+                                     [style.margin-top.px]="element.position.marginTop"
+                                     [style.margin-bottom.px]="element.position.marginBottom"
+                                     [style.grid-column-start]="element.position.gridColumnStart"
+                                     [style.grid-column-end]="element.position.gridColumnEnd"
+                                     [style.grid-row-start]="element.position.gridRowStart"
+                                     [style.grid-row-end]="element.position.gridRowEnd"
+                                     cdkDropList cdkDropListSortingDisabled
+                                     [cdkDropListData]="{ sectionIndex: sectionIndex }"
+                                     [cdkDropListConnectedTo]="dropListList"
+                                     (resize)="resizeOverlay($event)"
+                                     [style.position]="'relative'"
+                                     [style.pointer-events]="dragging ? 'none' : 'auto'">
+      </aspect-dynamic-canvas-overlay>
+    </div>
   `,
   styles: [
     '.grid-placeholder {border: 5px solid aliceblue; color: lightblue; text-align: center;}'
diff --git a/projects/editor/src/app/components/unit-view/page-view/properties-panel/element-properties-panel.component.html b/projects/editor/src/app/components/unit-view/page-view/properties-panel/element-properties-panel.component.html
index 142a03c66..9441a47ae 100644
--- a/projects/editor/src/app/components/unit-view/page-view/properties-panel/element-properties-panel.component.html
+++ b/projects/editor/src/app/components/unit-view/page-view/properties-panel/element-properties-panel.component.html
@@ -12,21 +12,21 @@
       </aspect-element-model-properties-component>
     </mat-tab>
 
-    <mat-tab *ngIf="combinedProperties.positionProps">
+    <mat-tab *ngIf="combinedProperties.position">
       <ng-template mat-tab-label>
         <mat-icon class="example-tab-icon">format_shapes</mat-icon>
       </ng-template>
       <aspect-element-postion-properties [dimensions]="{ width: combinedProperties.width, height: combinedProperties.height }"
-                                         [positionProperties]="combinedProperties.positionProps"
+                                         [positionProperties]="combinedProperties.position"
                                          (updateModel)="updateModel($event.property, $event.value, $event.isInputValid)">
       </aspect-element-postion-properties>
     </mat-tab>
 
-    <mat-tab *ngIf="combinedProperties.styles">
+    <mat-tab *ngIf="combinedProperties.styling">
       <ng-template mat-tab-label>
         <mat-icon class="example-tab-icon">palette</mat-icon>
       </ng-template>
-      <aspect-element-style-properties [styles]="$any(combinedProperties.styles)"
+      <aspect-element-style-properties [styles]="$any(combinedProperties.styling)"
                                        (updateModel)="updateModel($event.property, $event.value)">
       </aspect-element-style-properties>
     </mat-tab>
diff --git a/projects/editor/src/app/components/unit-view/page-view/properties-panel/model-properties-tab/element-model-properties.component.html b/projects/editor/src/app/components/unit-view/page-view/properties-panel/model-properties-tab/element-model-properties.component.html
index 391edde53..f20bbef13 100644
--- a/projects/editor/src/app/components/unit-view/page-view/properties-panel/model-properties-tab/element-model-properties.component.html
+++ b/projects/editor/src/app/components/unit-view/page-view/properties-panel/model-properties-tab/element-model-properties.component.html
@@ -25,7 +25,7 @@
     </button>
   </ng-container>
 
-  <ng-container *ngIf="combinedProperties.playerProps">
+  <ng-container *ngIf="combinedProperties.player">
     <button (click)="unitService.showDefaultEditDialog(selectedElements[0])">
       <mat-icon>build_circle</mat-icon>
     </button>
diff --git a/projects/editor/src/app/components/unit-view/page-view/properties-panel/style-properties-tab/element-style-properties.component.ts b/projects/editor/src/app/components/unit-view/page-view/properties-panel/style-properties-tab/element-style-properties.component.ts
index 4c6ea5497..7556ec391 100644
--- a/projects/editor/src/app/components/unit-view/page-view/properties-panel/style-properties-tab/element-style-properties.component.ts
+++ b/projects/editor/src/app/components/unit-view/page-view/properties-panel/style-properties-tab/element-style-properties.component.ts
@@ -1,7 +1,7 @@
 import {
   Component, EventEmitter, Input, Output
 } from '@angular/core';
-import { ElementStyles } from '../../../../../../../../common/interfaces/elements';
+import { ElementStyling } from '../../../../../../../../common/interfaces/elements';
 
 @Component({
   selector: 'aspect-element-style-properties',
@@ -121,7 +121,7 @@ import { ElementStyles } from '../../../../../../../../common/interfaces/element
   `
 })
 export class ElementStylePropertiesComponent {
-  @Input() styles: ElementStyles = {};
+  @Input() styles: ElementStyling = {};
   @Output() updateModel = new EventEmitter<{
     property: string;
     value: string | boolean,
diff --git a/projects/editor/src/app/components/unit-view/unit-view.component.ts b/projects/editor/src/app/components/unit-view/unit-view.component.ts
index e4229444f..81c7d219c 100644
--- a/projects/editor/src/app/components/unit-view/unit-view.component.ts
+++ b/projects/editor/src/app/components/unit-view/unit-view.component.ts
@@ -32,7 +32,7 @@ export class UnitViewComponent implements OnDestroy {
   }
 
   addPage(): void {
-    this.unitService.unit.pages.push(UnitFactory.generateEmptyPage());
+    this.unitService.unit.pages.push(UnitFactory.createPage());
 
     this.selectedPageIndex = this.unitService.unit.pages.length - 1;
     this.selectionService.selectedPageIndex = this.selectedPageIndex;
diff --git a/projects/editor/src/app/services/unit.service.ts b/projects/editor/src/app/services/unit.service.ts
index 439f31069..16c8e6bb5 100644
--- a/projects/editor/src/app/services/unit.service.ts
+++ b/projects/editor/src/app/services/unit.service.ts
@@ -42,16 +42,16 @@ export class UnitService {
               private dialogService: DialogService,
               private sanitizer: DomSanitizer,
               private translateService: TranslateService) {
-    this.unit = UnitFactory.generateEmptyUnit();
+    this.unit = UnitFactory.createUnit({} as Unit);
   }
 
   loadUnitDefinition(unitDefinition: string): void {
     this.idService.reset();
-    this.unit = UnitDefinitionSanitizer.sanitize(JSON.parse(unitDefinition));
+    this.unit = UnitFactory.createUnit(UnitDefinitionSanitizer.sanitizeUnitDefinition(JSON.parse(unitDefinition)));
     UnitService.readIDs(this.unit);
   }
 
-  private static readIDs(unit: Unit): void {
+  private static readIDs(unit: Unit): void { // TODO likert and cloze children
     UnitUtils.findUIElements(unit).forEach(element => {
       IdService.getInstance().addID(element.id);
     });
@@ -62,7 +62,7 @@ export class UnitService {
   }
 
   addSection(page: Page): void {
-    page.sections.push(UnitFactory.generateEmptySection());
+    page.sections.push(UnitFactory.createSection());
     this.veronaApiService.sendVoeDefinitionChangedNotification();
   }
 
@@ -112,29 +112,31 @@ export class UnitService {
           break;
         // no default
       }
-      newElement = ElementFactory.createElement(elementType, { // TODO
+      newElement = ElementFactory.createElement({
+        type: elementType,
         id: this.idService.getNewID(elementType),
         src: mediaSrc,
         positionProps: {
           dynamicPositioning: section.dynamicPositioning
         }
-      } as unknown as Partial<UIElement>) as PositionedElement;
+      } as unknown as UIElement) as PositionedElement;
     } else {
-      newElement = ElementFactory.createElement(elementType, {
+      newElement = ElementFactory.createElement({
+        type: elementType,
         id: this.idService.getNewID(elementType),
         positionProps: {
           dynamicPositioning: section.dynamicPositioning
         }
-      } as unknown as Partial<UIElement>) as PositionedElement;
+      } as unknown as UIElement) as PositionedElement;
     }
     if (coordinates && section.dynamicPositioning) {
-      newElement.positionProps.gridColumnStart = coordinates.x;
-      newElement.positionProps.gridColumnEnd = coordinates.x + 1;
-      newElement.positionProps.gridRowStart = coordinates.y;
-      newElement.positionProps.gridRowEnd = coordinates.y + 1;
+      newElement.position.gridColumnStart = coordinates.x;
+      newElement.position.gridColumnEnd = coordinates.x + 1;
+      newElement.position.gridRowStart = coordinates.y;
+      newElement.position.gridRowEnd = coordinates.y + 1;
     } else if (coordinates && !section.dynamicPositioning) {
-      newElement.positionProps.xPosition = coordinates.x;
-      newElement.positionProps.yPosition = coordinates.y;
+      newElement.position.xPosition = coordinates.x;
+      newElement.position.yPosition = coordinates.y;
     }
     section.elements.push(newElement);
     this.veronaApiService.sendVoeDefinitionChangedNotification();
@@ -164,7 +166,7 @@ export class UnitService {
     previousSection.elements = previousSection.elements.filter(element => !elements.includes(element));
     elements.forEach(element => {
       newSection.elements.push(element as PositionedElement);
-      (element as PositionedElement).positionProps.dynamicPositioning = newSection.dynamicPositioning;
+      (element as PositionedElement).position.dynamicPositioning = newSection.dynamicPositioning;
     });
     this.veronaApiService.sendVoeDefinitionChangedNotification();
   }
@@ -175,8 +177,8 @@ export class UnitService {
     (elements as PositionedElement[]).forEach((element: PositionedElement) => {
       const newElement = JSON.parse(JSON.stringify(element));
       newElement.id = this.idService.getNewID(element.type);
-      newElement.positionProps.xPosition = element.positionProps.xPosition + 10;
-      newElement.positionProps.yPosition = element.positionProps.yPosition + 10;
+      newElement.positionProps.xPosition = element.position.xPosition + 10;
+      newElement.positionProps.yPosition = element.position.yPosition + 10;
 
       if ('value' in newElement && newElement.value instanceof Object) { // replace value Ids with fresh ones (dropList)
         newElement.value.forEach((valueObject: { id: string }) => {
@@ -210,7 +212,7 @@ export class UnitService {
     if (property === 'dynamicPositioning') {
       section.dynamicPositioning = value as boolean;
       section.elements.forEach((element: PositionedElement) => {
-        element.positionProps.dynamicPositioning = value as boolean;
+        element.position.dynamicPositioning = value as boolean;
       });
     } else {
       section[property] = value;
@@ -248,16 +250,16 @@ export class UnitService {
       } else if (['fixedSize', 'dynamicPositioning', 'xPosition', 'yPosition', 'useMinHeight', 'gridColumnStart',
         'gridColumnEnd', 'gridRowStart', 'gridRowEnd', 'marginLeft', 'marginRight', 'marginTop',
         'marginBottom', 'zIndex'].includes(property)) {
-        element.positionProps![property] = Copy.getCopy(value);
+        element.position![property] = Copy.getCopy(value);
       } else if (['fontColor', 'font', 'fontSize', 'lineHeight', 'bold', 'italic', 'underline',
         'backgroundColor', 'borderRadius', 'itemBackgroundColor', 'borderWidth', 'borderColor',
         'borderStyle', 'lineColoring', 'lineColoringColor'].includes(property)) {
-        element.styles![property] = Copy.getCopy(value);
+        element.styling![property] = Copy.getCopy(value);
       } else if (['autostart', 'autostartDelay', 'loop', 'startControl', 'pauseControl',
         'progressBar', 'interactiveProgressbar', 'volumeControl', 'defaultVolume', 'minVolume',
         'muteControl', 'interactiveMuteControl', 'hintLabel', 'hintLabelDelay', 'activeAfterID',
         'minRuns', 'maxRuns', 'showRestRuns', 'showRestTime', 'playbackTime'].includes(property)) {
-        element.playerProps![property] = Copy.getCopy(value);
+        element.player![property] = Copy.getCopy(value);
       } else {
         element[property] = Copy.getCopy(value);
       }
@@ -358,28 +360,28 @@ export class UnitService {
         this.updateElementProperty(
           elements,
           'xPosition',
-          Math.min(...elements.map(element => element.positionProps.xPosition))
+          Math.min(...elements.map(element => element.position.xPosition))
         );
         break;
       case 'right':
         this.updateElementProperty(
           elements,
           'xPosition',
-          Math.max(...elements.map(element => element.positionProps.xPosition))
+          Math.max(...elements.map(element => element.position.xPosition))
         );
         break;
       case 'top':
         this.updateElementProperty(
           elements,
           'yPosition',
-          Math.min(...elements.map(element => element.positionProps.yPosition))
+          Math.min(...elements.map(element => element.position.yPosition))
         );
         break;
       case 'bottom':
         this.updateElementProperty(
           elements,
           'yPosition',
-          Math.max(...elements.map(element => element.positionProps.yPosition))
+          Math.max(...elements.map(element => element.position.yPosition))
         );
         break;
       // no default
@@ -411,7 +413,7 @@ export class UnitService {
       case 'text':
         this.dialogService.showRichTextEditDialog(
           (element as TextElement).text,
-          (element as TextElement).styles.fontSize
+          (element as TextElement).styling.fontSize
         ).subscribe((result: string) => {
           if (result) {
             // TODO add proper sanitization
@@ -426,7 +428,7 @@ export class UnitService {
       case 'cloze':
         this.dialogService.showClozeTextEditDialog(
           (element as ClozeElement).document,
-          (element as ClozeElement).styles.fontSize
+          (element as ClozeElement).styling.fontSize
         ).subscribe((result: string) => {
           if (result) {
             // TODO add proper sanitization
@@ -456,7 +458,7 @@ export class UnitService {
         break;
       case 'audio':
       case 'video':
-        this.dialogService.showPlayerEditDialog((element as PlayerElement).playerProps)
+        this.dialogService.showPlayerEditDialog((element as PlayerElement).player)
           .subscribe((result: PlayerProperties) => {
             Object.keys(result).forEach(key => this.updateElementProperty([element], key, result[key]));
           });
diff --git a/projects/editor/src/app/text-editor/angular-node-views/drop-list-component-extension.ts b/projects/editor/src/app/text-editor/angular-node-views/drop-list-component-extension.ts
index d2a909b8f..4a762cf6d 100644
--- a/projects/editor/src/app/text-editor/angular-node-views/drop-list-component-extension.ts
+++ b/projects/editor/src/app/text-editor/angular-node-views/drop-list-component-extension.ts
@@ -14,7 +14,7 @@ const DropListComponentExtension = (injector: Injector): Node => {
     addAttributes() {
       return {
         model: {
-          default: ElementFactory.createElement('drop-list', { height: 25, width: 100 })
+          default: ElementFactory.createElement({ type: 'drop-list', height: 25, width: 100 })
         }
       };
     },
diff --git a/projects/editor/src/app/text-editor/angular-node-views/text-field-component-extension.ts b/projects/editor/src/app/text-editor/angular-node-views/text-field-component-extension.ts
index 67d15a6ee..f3a8bda41 100644
--- a/projects/editor/src/app/text-editor/angular-node-views/text-field-component-extension.ts
+++ b/projects/editor/src/app/text-editor/angular-node-views/text-field-component-extension.ts
@@ -13,7 +13,7 @@ const TextFieldComponentExtension = (injector: Injector): Node => {
     addAttributes() {
       return {
         model: {
-          default: ElementFactory.createElement('text-field-simple', { height: 25, width: 100 })
+          default: ElementFactory.createElement({ type: 'text-field-simple', height: 25, width: 100 })
         }
       };
     },
diff --git a/projects/editor/src/app/text-editor/angular-node-views/toggle-button-component-extension.ts b/projects/editor/src/app/text-editor/angular-node-views/toggle-button-component-extension.ts
index 57580092f..b1f4da545 100644
--- a/projects/editor/src/app/text-editor/angular-node-views/toggle-button-component-extension.ts
+++ b/projects/editor/src/app/text-editor/angular-node-views/toggle-button-component-extension.ts
@@ -14,7 +14,7 @@ const ToggleButtonComponentExtension = (injector: Injector): Node => {
     addAttributes() {
       return {
         model: {
-          default: ElementFactory.createElement('toggle-button', { height: 25, width: 100 })
+          default: ElementFactory.createElement({ type: 'toggle-button', height: 25, width: 100 })
         }
       };
     },
diff --git a/projects/editor/src/app/util/cloze-parser.ts b/projects/editor/src/app/util/cloze-parser.ts
index 0ba9263b5..ec7694431 100644
--- a/projects/editor/src/app/util/cloze-parser.ts
+++ b/projects/editor/src/app/util/cloze-parser.ts
@@ -38,13 +38,13 @@ export abstract class ClozeParser {
     let newElement: InputElement;
     switch (elementModel.type) {
       case 'text-field':
-        newElement = ElementFactory.createElement('text-field-simple', elementModel) as InputElement;
+        newElement = ElementFactory.createElement(elementModel as UIElement) as InputElement;
         break;
       case 'drop-list':
-        newElement = ElementFactory.createElement('drop-list', elementModel) as InputElement;
+        newElement = ElementFactory.createElement(elementModel as UIElement) as InputElement;
         break;
       case 'toggle-button':
-        newElement = ElementFactory.createElement('toggle-button', elementModel) as InputElement;
+        newElement = ElementFactory.createElement(elementModel as UIElement) as InputElement;
         break;
       default:
         throw new Error(`ElementType ${elementModel.type} not found!`);
diff --git a/projects/editor/tsconfig.app.json b/projects/editor/tsconfig.app.json
index b6ed01d7e..fd37f74d7 100644
--- a/projects/editor/tsconfig.app.json
+++ b/projects/editor/tsconfig.app.json
@@ -3,9 +3,7 @@
   "extends": "../../tsconfig.json",
   "compilerOptions": {
     "outDir": "../../out-tsc/app",
-    "types": [],
-    "resolveJsonModule": true,
-    "allowSyntheticDefaultImports": true
+    "types": []
   },
   "files": [
     "src/main.ts",
diff --git a/projects/player/src/app/app.component.ts b/projects/player/src/app/app.component.ts
index 440cd9a7d..8ea7cadac 100644
--- a/projects/player/src/app/app.component.ts
+++ b/projects/player/src/app/app.component.ts
@@ -13,6 +13,7 @@ import { MediaPlayerService } from './services/media-player.service';
 import { Page, Unit } from '../../../common/interfaces/unit';
 import { UnitDefinitionSanitizer } from '../../../common/util/unit-definition-sanitizer';
 import { ValidatorService } from './services/validator.service';
+import { UnitFactory } from '../../../common/util/unit.factory';
 
 @Component({
   selector: 'aspect-player',
@@ -60,7 +61,9 @@ export class AppComponent implements OnInit {
       // eslint-disable-next-line no-console
       console.log('player: onStart', message);
       if (message.unitDefinition) {
-        const unitDefinition: Unit = UnitDefinitionSanitizer.sanitize(JSON.parse(message.unitDefinition));
+        const unitDefinition: Unit = UnitFactory.createUnit(
+          UnitDefinitionSanitizer.sanitizeUnitDefinition(JSON.parse(message.unitDefinition))
+        );
         this.unitStateElementMapperService.registerDropListValueIds(unitDefinition);
         this.playerConfig = message.playerConfig || {};
         this.veronaPostService.sessionId = message.sessionId;
diff --git a/projects/player/src/app/components/element-media-player-group/element-media-player-group.component.ts b/projects/player/src/app/components/element-media-player-group/element-media-player-group.component.ts
index d4e2fadb4..4af6e03ca 100644
--- a/projects/player/src/app/components/element-media-player-group/element-media-player-group.component.ts
+++ b/projects/player/src/app/components/element-media-player-group/element-media-player-group.component.ts
@@ -34,20 +34,20 @@ export class ElementMediaPlayerGroupComponent extends ElementGroupDirective impl
   ngOnInit(): void {
     const unitStateValue = this.unitStateService.getUnitStateElement(this.elementModel.id)?.value;
     this.initialValue = unitStateValue !== undefined ?
-      unitStateValue as number : (this.elementModel as AudioElement).playerProps.playbackTime;
+      unitStateValue as number : (this.elementModel as AudioElement).player.playbackTime;
 
     this.mediaPlayerService.registerMediaElement(
       this.elementModel.id,
       this.elementComponent,
-      this.elementModel.playerProps?.activeAfterID as string,
-      this.elementModel.playerProps?.minRuns as number === 0
+      this.elementModel.player?.activeAfterID as string,
+      this.elementModel.player?.minRuns as number === 0
     );
   }
 
   ngAfterViewInit(): void {
     const initialValue = this.elementModel.type === 'audio' ?
-      (this.elementModel as AudioElement).playerProps.playbackTime :
-      (this.elementModel as VideoElement).playerProps.playbackTime;
+      (this.elementModel as AudioElement).player.playbackTime :
+      (this.elementModel as VideoElement).player.playbackTime;
     this.registerAtUnitStateService(this.elementModel.id, initialValue, this.elementComponent, this.pageIndex);
   }
 }
diff --git a/projects/player/src/app/components/element-splitter/element-splitter.component.html b/projects/player/src/app/components/element-splitter/element-splitter.component.html
index 67fd2cd12..e55b688de 100644
--- a/projects/player/src/app/components/element-splitter/element-splitter.component.html
+++ b/projects/player/src/app/components/element-splitter/element-splitter.component.html
@@ -1,10 +1,10 @@
-<div [class]="elementModel.positionProps?.dynamicPositioning && elementModel.positionProps?.fixedSize ?
+<div [class]="elementModel.position?.dynamicPositioning && elementModel.position?.fixedSize ?
          'fixed-size-content-wrapper' : 'inline-container'">
-  <div [class]="elementModel.positionProps?.dynamicPositioning && elementModel.positionProps?.fixedSize ?
+  <div [class]="elementModel.position?.dynamicPositioning && elementModel.position?.fixedSize ?
             'fixed-size-content' : 'inline-container'"
-       [style.width]="elementModel.positionProps?.dynamicPositioning && elementModel.positionProps?.fixedSize ?
+       [style.width]="elementModel.position?.dynamicPositioning && elementModel.position?.fixedSize ?
                       elementModel.width + 'px' : '100%'"
-       [style.height]="elementModel.positionProps?.dynamicPositioning && elementModel.positionProps?.fixedSize ?
+       [style.height]="elementModel.position?.dynamicPositioning && elementModel.position?.fixedSize ?
                       elementModel.height + 'px' : '100%'">
           <aspect-element-text-input-group
               *ngIf="'textInputGroup' === selectedGroup"
@@ -43,4 +43,3 @@
           </aspect-element-base-group>
   </div>
 </div>
-
diff --git a/projects/player/src/app/components/section/section.component.html b/projects/player/src/app/components/section/section.component.html
index 282ee7602..305e835a2 100644
--- a/projects/player/src/app/components/section/section.component.html
+++ b/projects/player/src/app/components/section/section.component.html
@@ -6,9 +6,9 @@
         class="static-element fixed-size-content"
         [style.width.px]="element.width"
         [style.height.px]="element.height"
-        [style.left.px]="element.positionProps.xPosition"
-        [style.top.px]="element.positionProps.yPosition"
-        [style.z-index]="element.positionProps?.zIndex"
+        [style.left.px]="element.position.xPosition"
+        [style.top.px]="element.position.yPosition"
+        [style.z-index]="element.position?.zIndex"
         [elementModel]="element"
         [pageIndex]="pageIndex">
     </aspect-element-splitter>
@@ -26,16 +26,16 @@
     <ng-container *ngFor="let element of section.elements; let i = index">
       <aspect-element-splitter
           [style.min-width.px]="element.width"
-          [style.min-height.px]="element.positionProps.useMinHeight ? element.height : 0"
-          [style.margin-left.px]="element.positionProps.marginLeft"
-          [style.margin-right.px]="element.positionProps.marginRight"
-          [style.margin-top.px]="element.positionProps.marginTop"
-          [style.margin-bottom.px]="element.positionProps.marginBottom"
-          [style.grid-column-start]="element.positionProps.gridColumnStart"
-          [style.grid-column-end]="element.positionProps.gridColumnEnd"
-          [style.grid-row-start]="element.positionProps.gridRowStart"
-          [style.grid-row-end]="element.positionProps.gridRowEnd"
-          [style.z-index]="element.positionProps?.zIndex"
+          [style.min-height.px]="element.position.useMinHeight ? element.height : 0"
+          [style.margin-left.px]="element.position.marginLeft"
+          [style.margin-right.px]="element.position.marginRight"
+          [style.margin-top.px]="element.position.marginTop"
+          [style.margin-bottom.px]="element.position.marginBottom"
+          [style.grid-column-start]="element.position.gridColumnStart"
+          [style.grid-column-end]="element.position.gridColumnEnd"
+          [style.grid-row-start]="element.position.gridRowStart"
+          [style.grid-row-end]="element.position.gridRowEnd"
+          [style.z-index]="element.position?.zIndex"
           [elementModel]="element"
           [pageIndex]="pageIndex">
       </aspect-element-splitter>
diff --git a/projects/player/src/app/services/unit-state-element-mapper.service.ts b/projects/player/src/app/services/unit-state-element-mapper.service.ts
index bc6a50f66..525637a6c 100644
--- a/projects/player/src/app/services/unit-state-element-mapper.service.ts
+++ b/projects/player/src/app/services/unit-state-element-mapper.service.ts
@@ -35,11 +35,11 @@ export class UnitStateElementMapperService {
       case 'audio':
         return unitStateValue !== undefined ?
           unitStateValue as number :
-          (elementModel as AudioElement).playerProps.playbackTime;
+          (elementModel as AudioElement).player.playbackTime;
       case 'video':
         return unitStateValue !== undefined ?
           unitStateValue as number :
-          (elementModel as VideoElement).playerProps.playbackTime;
+          (elementModel as VideoElement).player.playbackTime;
       case 'radio':
       case 'radio-group-images':
       case 'dropdown':
diff --git a/tsconfig.json b/tsconfig.json
index 874b1670a..e0901b6e5 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -14,6 +14,8 @@
     "experimentalDecorators": true,
     "moduleResolution": "node",
     "importHelpers": true,
+    "resolveJsonModule": true,
+    "allowSyntheticDefaultImports": true,
     "target": "es2020",
     "module": "es2020",
     "lib": [
-- 
GitLab