From 6d1ad52c8edfe14a53b40746394a11e7ad64befe Mon Sep 17 00:00:00 2001
From: rhenck <richard.henck@iqb.hu-berlin.de>
Date: Mon, 7 Nov 2022 12:20:41 +0100
Subject: [PATCH] Re-implement DropList element

- Replace Material Droplist with native HTML events
- Remove simple-drop-list element; Cloze elements now use the normal
DropList element
- Add example units
---
 docs/unit_definition_changelog.txt            |   4 +-
 example_data/droplist/dnd1.json               |   1 +
 example_data/droplist/dnd2.json               |   1 +
 example_data/droplist/dnd3.json               |   1 +
 example_data/droplist/dnd4.json               |   1 +
 package.json                                  |   2 +-
 .../drop-list-simple.component.ts             | 171 --------
 .../cloze/compound-child-overlay.component.ts |  12 +-
 .../input-elements/drop-list.component.ts     | 415 ++++++++++--------
 .../cloze-child-elements/drop-list-simple.ts  |  67 ---
 .../elements/compound-elements/cloze/cloze.ts |  11 +-
 .../tiptap-editor-extensions/drop-list.ts     |   6 +-
 projects/common/models/elements/element.ts    |   9 +-
 .../elements/input-elements/drop-list.ts      |  31 +-
 projects/common/models/section.ts             |  13 +-
 projects/common/models/unit.ts                |   3 +-
 .../common/services/sanitization.service.ts   |   1 -
 projects/common/shared.module.ts              |  15 +-
 projects/common/util/element.factory.ts       |   4 -
 .../canvas/overlays/canvas-element-overlay.ts |  13 +-
 .../element-properties-panel.component.html   |   2 -
 .../drop-list-properties.component.ts         |   9 +-
 .../editor/src/app/services/id.service.ts     |   1 -
 .../editor/src/app/services/unit.service.ts   |   8 +-
 .../drop-list-component-extension.ts          |  11 +-
 .../drop-list-nodeview.component.ts           |   6 +-
 projects/editor/src/assets/i18n/de.json       |   3 +-
 ...ment-model-element-code-mapping.service.ts |   2 -
 28 files changed, 316 insertions(+), 507 deletions(-)
 create mode 100644 example_data/droplist/dnd1.json
 create mode 100644 example_data/droplist/dnd2.json
 create mode 100644 example_data/droplist/dnd3.json
 create mode 100644 example_data/droplist/dnd4.json
 delete mode 100644 projects/common/components/compound-elements/cloze/cloze-child-elements/drop-list-simple.component.ts
 delete mode 100644 projects/common/models/elements/compound-elements/cloze/cloze-child-elements/drop-list-simple.ts

diff --git a/docs/unit_definition_changelog.txt b/docs/unit_definition_changelog.txt
index c7320369c..f1bcc976a 100644
--- a/docs/unit_definition_changelog.txt
+++ b/docs/unit_definition_changelog.txt
@@ -53,4 +53,6 @@ iqb-aspect-definition@1.0.0
                     +hasKeyboardIcon: boolean;
 - TextFieldElement: +hasKeyboardIcon: boolean;
 - TextFieldElement/TextFieldSimpleElement/SpellCorrectElement/TextAreaElement: InputAssistancePreset +'custom'
-                                                                               +inputAssistanceCustomKeys: string;
+
+3.9.0
+- remove drop-list-simple as cloze child; is now a drop-list
diff --git a/example_data/droplist/dnd1.json b/example_data/droplist/dnd1.json
new file mode 100644
index 000000000..075844082
--- /dev/null
+++ b/example_data/droplist/dnd1.json
@@ -0,0 +1 @@
+{"type":"aspect-unit-definition","pages":[{"sections":[{"elements":[{"width":180,"height":98,"type":"text","id":"text_1","text":"<p style=\"padding-left: 0px; text-indent: 0px; margin-bottom: 0px; margin-top: 0\" indentsize=\"20\">Normale Liste</p>","highlightableOrange":false,"highlightableTurquoise":false,"highlightableYellow":false,"hasSelectionPopup":true,"columnCount":1,"position":{"fixedSize":false,"dynamicPositioning":true,"xPosition":0,"yPosition":0,"useMinHeight":false,"gridColumn":1,"gridColumnRange":1,"gridRow":1,"gridRowRange":1,"marginLeft":0,"marginRight":0,"marginTop":0,"marginBottom":0,"zIndex":0},"styling":{"backgroundColor":"transparent","lineHeight":135,"fontColor":"#000000","font":"Roboto","fontSize":20,"bold":false,"italic":false,"underline":false}},{"width":180,"height":100,"type":"drop-list","id":"drop-list_1","label":"Beschriftung","value":[{"text":"aaa","imgSrc":null,"imgPosition":"above","id":"value_1"},{"text":"bbb","imgSrc":null,"imgPosition":"above","id":"value_2"},{"text":"ccc","imgSrc":null,"imgPosition":"above","id":"value_3"}],"required":false,"requiredWarnMessage":"Eingabe erforderlich","readOnly":false,"onlyOneItem":false,"isSortList":false,"connectedTo":["drop-list_2","drop-list_3","drop-list_4"],"copyOnDrop":false,"orientation":"vertical","highlightReceivingDropList":true,"highlightReceivingDropListColor":"#006064","position":{"fixedSize":false,"dynamicPositioning":true,"xPosition":0,"yPosition":0,"useMinHeight":true,"gridColumn":null,"gridColumnRange":1,"gridRow":null,"gridRowRange":1,"marginLeft":0,"marginRight":0,"marginTop":0,"marginBottom":0,"zIndex":0},"styling":{"backgroundColor":"#f4f4f2","itemBackgroundColor":"#c9e0e0","fontColor":"#000000","font":"Roboto","fontSize":20,"bold":false,"italic":false,"underline":false}},{"width":180,"height":98,"type":"text","id":"text_2","text":"<p style=\"padding-left: 0px; text-indent: 0px; margin-bottom: 0px; margin-top: 0\" indentsize=\"20\">Liste 2</p>","highlightableOrange":false,"highlightableTurquoise":false,"highlightableYellow":false,"hasSelectionPopup":true,"columnCount":1,"position":{"fixedSize":false,"dynamicPositioning":true,"xPosition":0,"yPosition":0,"useMinHeight":false,"gridColumn":null,"gridColumnRange":1,"gridRow":null,"gridRowRange":1,"marginLeft":0,"marginRight":0,"marginTop":0,"marginBottom":0,"zIndex":0},"styling":{"backgroundColor":"transparent","lineHeight":135,"fontColor":"#000000","font":"Roboto","fontSize":20,"bold":false,"italic":false,"underline":false}},{"width":180,"height":100,"type":"drop-list","id":"drop-list_2","label":"Beschriftung","value":[{"text":"ddd","imgSrc":null,"imgPosition":"above","id":"value_4"},{"text":"eee","imgSrc":null,"imgPosition":"above","id":"value_5"},{"text":"fff","imgSrc":null,"imgPosition":"above","id":"value_6"}],"required":false,"requiredWarnMessage":"Eingabe erforderlich","readOnly":false,"onlyOneItem":false,"sorting":false,"connectedTo":["drop-list_1","drop-list_3"],"copyOnDrop":false,"orientation":"vertical","highlightReceivingDropList":true,"highlightReceivingDropListColor":"#006064","position":{"fixedSize":false,"dynamicPositioning":true,"xPosition":0,"yPosition":0,"useMinHeight":true,"gridColumn":null,"gridColumnRange":1,"gridRow":null,"gridRowRange":1,"marginLeft":0,"marginRight":0,"marginTop":0,"marginBottom":0,"zIndex":0},"styling":{"backgroundColor":"#f4f4f2","itemBackgroundColor":"#c9e0e0","fontColor":"#000000","font":"Roboto","fontSize":20,"bold":false,"italic":false,"underline":false}},{"width":180,"height":98,"type":"text","id":"text_3","text":"<p style=\"padding-left: 0px; text-indent: 0px; margin-bottom: 0px; margin-top: 0\" indentsize=\"20\">Leere Liste</p>","highlightableOrange":false,"highlightableTurquoise":false,"highlightableYellow":false,"hasSelectionPopup":true,"columnCount":1,"position":{"fixedSize":false,"dynamicPositioning":true,"xPosition":0,"yPosition":0,"useMinHeight":false,"gridColumn":null,"gridColumnRange":1,"gridRow":null,"gridRowRange":1,"marginLeft":0,"marginRight":0,"marginTop":0,"marginBottom":0,"zIndex":0},"styling":{"backgroundColor":"transparent","lineHeight":135,"fontColor":"#000000","font":"Roboto","fontSize":20,"bold":false,"italic":false,"underline":false}},{"width":180,"height":100,"type":"drop-list","id":"drop-list_3","label":"Beschriftung","value":[],"required":false,"requiredWarnMessage":"Eingabe erforderlich","readOnly":false,"onlyOneItem":false,"sorting":false,"connectedTo":["drop-list_1","drop-list_2"],"copyOnDrop":false,"orientation":"vertical","highlightReceivingDropList":false,"highlightReceivingDropListColor":"#006064","position":{"fixedSize":false,"dynamicPositioning":true,"xPosition":0,"yPosition":0,"useMinHeight":true,"gridColumn":null,"gridColumnRange":1,"gridRow":null,"gridRowRange":1,"marginLeft":0,"marginRight":0,"marginTop":0,"marginBottom":0,"zIndex":0},"styling":{"backgroundColor":"#f4f4f2","itemBackgroundColor":"#c9e0e0","fontColor":"#000000","font":"Roboto","fontSize":20,"bold":false,"italic":false,"underline":false}}],"height":400,"backgroundColor":"#ffffff","dynamicPositioning":true,"autoColumnSize":true,"autoRowSize":true,"gridColumnSizes":"1fr 1fr","gridRowSizes":"1fr","activeAfterID":null},{"elements":[{"width":180,"height":200,"type":"cloze","id":"cloze_1","document":{"type":"doc","content":[{"type":"paragraph","attrs":{"textAlign":"left","indent":null,"indentSize":20,"hangingIndent":false,"margin":0},"content":[{"type":"text","text":"Lorem Ipsum"},{"type":"ToggleButton","attrs":{"model":{"width":100,"height":25,"type":"toggle-button","id":"toggle-button_1","label":"Beschriftung","value":null,"required":false,"requiredWarnMessage":"Eingabe erforderlich","readOnly":false,"options":[],"strikeOtherOptions":false,"strikeSelectedOption":false,"verticalOrientation":false,"dynamicWidth":true,"styling":{"lineHeight":135,"selectionColor":"#c7f3d0","backgroundColor":"transparent","fontColor":"#000000","font":"Roboto","fontSize":20,"bold":false,"italic":false,"underline":false}}}},{"type":"DropList","attrs":{"model":{"width":150,"height":30,"type":"drop-list","id":"drop-list_4","label":"Beschriftung","value":[],"required":false,"requiredWarnMessage":"Eingabe erforderlich","readOnly":false,"onlyOneItem":false,"sorting":false,"connectedTo":["drop-list_1"],"copyOnDrop":false,"orientation":"vertical","highlightReceivingDropList":false,"highlightReceivingDropListColor":"#006064","styling":{"backgroundColor":"#f4f4f2","itemBackgroundColor":"#c9e0e0","fontColor":"#000000","font":"Roboto","fontSize":20,"bold":false,"italic":false,"underline":false}}}}]}]},"columnCount":1,"position":{"fixedSize":false,"dynamicPositioning":true,"xPosition":0,"yPosition":0,"useMinHeight":false,"gridColumn":null,"gridColumnRange":1,"gridRow":null,"gridRowRange":1,"marginLeft":0,"marginRight":0,"marginTop":0,"marginBottom":0,"zIndex":0},"styling":{"lineHeight":150,"fontColor":"#000000","font":"Roboto","fontSize":20,"bold":false,"italic":false,"underline":false,"backgroundColor":"#d3d3d3"}}],"height":400,"backgroundColor":"#ffffff","dynamicPositioning":true,"autoColumnSize":true,"autoRowSize":true,"gridColumnSizes":"1fr 1fr","gridRowSizes":"1fr","activeAfterID":null}],"hasMaxWidth":false,"maxWidth":900,"margin":30,"backgroundColor":"#ffffff","alwaysVisible":false,"alwaysVisiblePagePosition":"left","alwaysVisibleAspectRatio":50}],"version":"3.8.0"}
diff --git a/example_data/droplist/dnd2.json b/example_data/droplist/dnd2.json
new file mode 100644
index 000000000..c740cdceb
--- /dev/null
+++ b/example_data/droplist/dnd2.json
@@ -0,0 +1 @@
+{"type":"aspect-unit-definition","pages":[{"sections":[{"elements":[{"width":180,"height":98,"type":"text","id":"text_1","text":"<p style=\"padding-left: 0px; text-indent: 0px; margin-bottom: 0px; margin-top: 0\" indentsize=\"20\">Sortierliste 1</p>","highlightableOrange":false,"highlightableTurquoise":false,"highlightableYellow":false,"hasSelectionPopup":true,"columnCount":1,"position":{"fixedSize":false,"dynamicPositioning":true,"xPosition":0,"yPosition":0,"useMinHeight":false,"gridColumn":1,"gridColumnRange":1,"gridRow":1,"gridRowRange":1,"marginLeft":0,"marginRight":0,"marginTop":0,"marginBottom":0,"zIndex":0},"styling":{"backgroundColor":"transparent","lineHeight":135,"fontColor":"#000000","font":"Roboto","fontSize":20,"bold":false,"italic":false,"underline":false}},{"width":180,"height":100,"type":"drop-list","id":"drop-list_1","label":"Beschriftung","value":[{"text":"aaa","imgSrc":null,"imgPosition":"above","id":"value_5"},{"text":"bbb","imgSrc":null,"imgPosition":"above","id":"value_6"},{"text":"ccc","imgSrc":null,"imgPosition":"above","id":"value_7"},{"text":"ddd","imgSrc":null,"imgPosition":"above","id":"value_8"}],"required":false,"requiredWarnMessage":"Eingabe erforderlich","readOnly":false,"onlyOneItem":false,"isSortList":true,"connectedTo":[],"copyOnDrop":false,"orientation":"vertical","highlightReceivingDropList":false,"highlightReceivingDropListColor":"#006064","position":{"fixedSize":false,"dynamicPositioning":true,"xPosition":0,"yPosition":0,"useMinHeight":true,"gridColumn":null,"gridColumnRange":1,"gridRow":null,"gridRowRange":1,"marginLeft":0,"marginRight":0,"marginTop":0,"marginBottom":0,"zIndex":0},"styling":{"backgroundColor":"#f4f4f2","itemBackgroundColor":"#c9e0e0","fontColor":"#000000","font":"Roboto","fontSize":20,"bold":false,"italic":false,"underline":false}}],"height":400,"backgroundColor":"#ffffff","dynamicPositioning":true,"autoColumnSize":true,"autoRowSize":true,"gridColumnSizes":"1fr 1fr","gridRowSizes":"1fr","activeAfterID":null},{"elements":[{"width":180,"height":98,"type":"text","id":"text_2","text":"<p style=\"padding-left: 0px; text-indent: 0px; margin-bottom: 0px; margin-top: 0\" indent=\"0\" indentsize=\"20\">Sortierliste 2</p>","highlightableOrange":false,"highlightableTurquoise":false,"highlightableYellow":false,"hasSelectionPopup":true,"columnCount":1,"position":{"fixedSize":false,"dynamicPositioning":false,"xPosition":10,"yPosition":10,"useMinHeight":false,"gridColumn":1,"gridColumnRange":1,"gridRow":1,"gridRowRange":1,"marginLeft":0,"marginRight":0,"marginTop":0,"marginBottom":0,"zIndex":0},"styling":{"backgroundColor":"transparent","lineHeight":135,"fontColor":"#000000","font":"Roboto","fontSize":20,"bold":false,"italic":false,"underline":false}},{"width":865,"height":367,"type":"drop-list","id":"drop-list_2","label":"Beschriftung","value":[{"text":"eee","imgSrc":null,"id":"value_1"},{"text":"fff","imgSrc":null,"id":"value_2"},{"text":"ggg","imgSrc":null,"id":"value_3"},{"text":"hhh","imgSrc":null,"id":"value_4"}],"required":false,"requiredWarnMessage":"Eingabe erforderlich","readOnly":false,"onlyOneItem":false,"sorting":true,"connectedTo":[],"copyOnDrop":false,"orientation":"vertical","highlightReceivingDropList":false,"highlightReceivingDropListColor":"#006064","position":{"fixedSize":false,"dynamicPositioning":false,"xPosition":10,"yPosition":10,"useMinHeight":true,"gridColumn":null,"gridColumnRange":1,"gridRow":null,"gridRowRange":1,"marginLeft":0,"marginRight":0,"marginTop":0,"marginBottom":0,"zIndex":0},"styling":{"backgroundColor":"#f4f4f2","itemBackgroundColor":"#c9e0e0","fontColor":"#000000","font":"Roboto","fontSize":20,"bold":false,"italic":false,"underline":false}}],"height":400,"backgroundColor":"#ffffff","dynamicPositioning":false,"autoColumnSize":true,"autoRowSize":true,"gridColumnSizes":"1fr 1fr","gridRowSizes":"1fr","activeAfterID":null}],"hasMaxWidth":false,"maxWidth":900,"margin":30,"backgroundColor":"#ffffff","alwaysVisible":false,"alwaysVisiblePagePosition":"left","alwaysVisibleAspectRatio":50}],"version":"3.8.0"}
diff --git a/example_data/droplist/dnd3.json b/example_data/droplist/dnd3.json
new file mode 100644
index 000000000..ce6a8b62e
--- /dev/null
+++ b/example_data/droplist/dnd3.json
@@ -0,0 +1 @@
+{"type":"aspect-unit-definition","pages":[{"sections":[{"elements":[{"width":180,"height":98,"type":"text","id":"text_1","text":"<p style=\"padding-left: 0px; text-indent: 0px; margin-bottom: 0px; margin-top: 0\" indentsize=\"20\">Sortierliste 1</p>","highlightableOrange":false,"highlightableTurquoise":false,"highlightableYellow":false,"hasSelectionPopup":true,"columnCount":1,"position":{"fixedSize":false,"dynamicPositioning":true,"xPosition":0,"yPosition":0,"useMinHeight":false,"gridColumn":1,"gridColumnRange":1,"gridRow":1,"gridRowRange":1,"marginLeft":0,"marginRight":0,"marginTop":0,"marginBottom":0,"zIndex":0},"styling":{"backgroundColor":"transparent","lineHeight":135,"fontColor":"#000000","font":"Roboto","fontSize":20,"bold":false,"italic":false,"underline":false}},{"width":180,"height":100,"type":"drop-list","id":"drop-list_1","label":"Beschriftung","value":[{"text":"aaa","imgSrc":null,"imgPosition":"above","id":"value_5"},{"text":"bbb","imgSrc":null,"imgPosition":"above","id":"value_6"},{"text":"ccc","imgSrc":null,"imgPosition":"above","id":"value_7"},{"text":"ddd","imgSrc":null,"imgPosition":"above","id":"value_8"}],"required":false,"requiredWarnMessage":"Eingabe erforderlich","readOnly":false,"onlyOneItem":false,"isSortList":true,"connectedTo":[],"copyOnDrop":false,"orientation":"vertical","highlightReceivingDropList":false,"highlightReceivingDropListColor":"#006064","position":{"fixedSize":false,"dynamicPositioning":true,"xPosition":0,"yPosition":0,"useMinHeight":true,"gridColumn":null,"gridColumnRange":1,"gridRow":null,"gridRowRange":1,"marginLeft":0,"marginRight":0,"marginTop":0,"marginBottom":0,"zIndex":0},"styling":{"backgroundColor":"#f4f4f2","itemBackgroundColor":"#c9e0e0","fontColor":"#000000","font":"Roboto","fontSize":20,"bold":false,"italic":false,"underline":false}}],"height":400,"backgroundColor":"#ffffff","dynamicPositioning":true,"autoColumnSize":true,"autoRowSize":true,"gridColumnSizes":"1fr 1fr","gridRowSizes":"1fr","activeAfterID":null},{"elements":[{"width":180,"height":98,"type":"text","id":"text_2","text":"<p style=\"padding-left: 0px; text-indent: 0px; margin-bottom: 0px; margin-top: 0\" indent=\"0\" indentsize=\"20\">Sortierliste 2</p>","highlightableOrange":false,"highlightableTurquoise":false,"highlightableYellow":false,"hasSelectionPopup":true,"columnCount":1,"position":{"fixedSize":false,"dynamicPositioning":false,"xPosition":10,"yPosition":10,"useMinHeight":false,"gridColumn":1,"gridColumnRange":1,"gridRow":1,"gridRowRange":1,"marginLeft":0,"marginRight":0,"marginTop":0,"marginBottom":0,"zIndex":0},"styling":{"backgroundColor":"transparent","lineHeight":135,"fontColor":"#000000","font":"Roboto","fontSize":20,"bold":false,"italic":false,"underline":false}},{"width":865,"height":367,"type":"drop-list","id":"drop-list_2","label":"Beschriftung","value":[],"required":false,"requiredWarnMessage":"Eingabe erforderlich","readOnly":false,"onlyOneItem":false,"sorting":true,"connectedTo":[],"copyOnDrop":false,"orientation":"vertical","highlightReceivingDropList":false,"highlightReceivingDropListColor":"#006064","position":{"fixedSize":false,"dynamicPositioning":false,"xPosition":10,"yPosition":10,"useMinHeight":true,"gridColumn":null,"gridColumnRange":1,"gridRow":null,"gridRowRange":1,"marginLeft":0,"marginRight":0,"marginTop":0,"marginBottom":0,"zIndex":0},"styling":{"backgroundColor":"#f4f4f2","itemBackgroundColor":"#c9e0e0","fontColor":"#000000","font":"Roboto","fontSize":20,"bold":false,"italic":false,"underline":false}}],"height":400,"backgroundColor":"#ffffff","dynamicPositioning":false,"autoColumnSize":true,"autoRowSize":true,"gridColumnSizes":"1fr 1fr","gridRowSizes":"1fr","activeAfterID":null}],"hasMaxWidth":false,"maxWidth":900,"margin":30,"backgroundColor":"#ffffff","alwaysVisible":false,"alwaysVisiblePagePosition":"left","alwaysVisibleAspectRatio":50}],"version":"3.8.0"}
diff --git a/example_data/droplist/dnd4.json b/example_data/droplist/dnd4.json
new file mode 100644
index 000000000..0c20918be
--- /dev/null
+++ b/example_data/droplist/dnd4.json
@@ -0,0 +1 @@
+{"type":"aspect-unit-definition","pages":[{"sections":[{"elements":[{"width":180,"height":100,"type":"drop-list","id":"drop-list_1","label":"Beschriftung","value":[{"text":"aaa","imgSrc":null,"imgPosition":"above","id":"value_1"},{"text":"bbb","imgSrc":null,"imgPosition":"above","id":"value_2"},{"text":"ccc","imgSrc":null,"imgPosition":"above","id":"value_3"}],"required":false,"requiredWarnMessage":"Eingabe erforderlich","readOnly":false,"onlyOneItem":false,"isSortList":false,"connectedTo":["drop-list_2"],"copyOnDrop":false,"orientation":"vertical","highlightReceivingDropList":false,"highlightReceivingDropListColor":"#006064","position":{"fixedSize":false,"dynamicPositioning":true,"xPosition":0,"yPosition":0,"useMinHeight":true,"gridColumn":null,"gridColumnRange":1,"gridRow":null,"gridRowRange":1,"marginLeft":0,"marginRight":0,"marginTop":0,"marginBottom":0,"zIndex":0},"styling":{"backgroundColor":"#f4f4f2","itemBackgroundColor":"#c9e0e0","fontColor":"#000000","font":"Roboto","fontSize":20,"bold":false,"italic":false,"underline":false}},{"width":180,"height":200,"type":"cloze","id":"cloze_1","document":{"type":"doc","content":[{"type":"paragraph","attrs":{"textAlign":"left","indent":null,"indentSize":20,"hangingIndent":false,"margin":0},"content":[{"type":"text","text":"Lorem Ipsum"},{"type":"DropList","attrs":{"model":{"width":150,"height":30,"type":"drop-list","id":"drop-list_2","label":"Beschriftung","value":[],"required":false,"requiredWarnMessage":"Eingabe erforderlich","readOnly":false,"onlyOneItem":false,"sorting":false,"connectedTo":["drop-list_1"],"copyOnDrop":false,"orientation":"vertical","highlightReceivingDropList":false,"highlightReceivingDropListColor":"#006064","styling":{"backgroundColor":"#f4f4f2","itemBackgroundColor":"#c9e0e0","fontColor":"#000000","font":"Roboto","fontSize":20,"bold":false,"italic":false,"underline":false}}}}]}]},"columnCount":1,"position":{"fixedSize":false,"dynamicPositioning":true,"xPosition":0,"yPosition":0,"useMinHeight":false,"gridColumn":null,"gridColumnRange":1,"gridRow":null,"gridRowRange":1,"marginLeft":0,"marginRight":0,"marginTop":0,"marginBottom":0,"zIndex":0},"styling":{"lineHeight":150,"fontColor":"#000000","font":"Roboto","fontSize":20,"bold":false,"italic":false,"underline":false,"backgroundColor":"#d3d3d3"}}],"height":400,"backgroundColor":"#ffffff","dynamicPositioning":true,"autoColumnSize":true,"autoRowSize":true,"gridColumnSizes":"1fr 1fr","gridRowSizes":"1fr","activeAfterID":null}],"hasMaxWidth":false,"maxWidth":900,"margin":30,"backgroundColor":"#ffffff","alwaysVisible":false,"alwaysVisiblePagePosition":"left","alwaysVisibleAspectRatio":50}],"version":"3.8.0"}
diff --git a/package.json b/package.json
index 972fa676a..931a04627 100644
--- a/package.json
+++ b/package.json
@@ -3,7 +3,7 @@
   "config": {
     "player_version": "1.27.0",
     "editor_version": "1.34.0",
-    "unit_definition_version": "3.8.0"
+    "unit_definition_version": "3.9.0"
   },
   "scripts": {
     "ng": "ng",
diff --git a/projects/common/components/compound-elements/cloze/cloze-child-elements/drop-list-simple.component.ts b/projects/common/components/compound-elements/cloze/cloze-child-elements/drop-list-simple.component.ts
deleted file mode 100644
index d1f4440ce..000000000
--- a/projects/common/components/compound-elements/cloze/cloze-child-elements/drop-list-simple.component.ts
+++ /dev/null
@@ -1,171 +0,0 @@
-import { Component, Input } from '@angular/core';
-import { CdkDragDrop, CdkDragEnter, CdkDragStart } from '@angular/cdk/drag-drop/drag-events';
-import {
-  CdkDrag, CdkDropList, moveItemInArray, transferArrayItem
-} from '@angular/cdk/drag-drop';
-import { FormElementComponent } from 'common/directives/form-element-component.directive';
-import { DropListSimpleElement } from
-  'common/models/elements/compound-elements/cloze/cloze-child-elements/drop-list-simple';
-import { DragNDropValueObject } from 'common/models/elements/element';
-import { DropListComponent } from 'common/components/input-elements/drop-list.component';
-
-@Component({
-  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.-->
-      <div class="list"
-           [class.errors]="elementFormControl.errors && elementFormControl.touched"
-           [class.dropList-highlight]="elementModel.highlightReceivingDropList"
-           [style.min-height.px]="elementModel.height"
-           [style.border-color]="elementModel.highlightReceivingDropListColor"
-           [style.border-width.px]="elementModel.highlightReceivingDropList ? 2 : 0"
-           [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"
-           [matTooltip]="elementFormControl.errors && elementFormControl.touched ?
-                         (elementFormControl.errors | errorTransform: elementModel) : ''"
-           [matTooltipClass]="'error-tooltip'"
-           cdkDropList
-           [id]="elementModel.id"
-           [cdkDropListData]="this"
-           [cdkDropListConnectedTo]="elementModel.connectedTo"
-           [cdkDropListEnterPredicate]="onlyOneItemPredicate"
-           tabindex="0"
-           (focusout)="elementFormControl.markAsTouched()"
-           (cdkDropListDropped)="drop($event)">
-        <ng-container *ngIf="!parentForm">
-            <ng-container *ngFor="let dropListValueElement of $any(elementModel.value)">
-                <ng-container [ngTemplateOutlet]="dropObject"
-                              [ngTemplateOutletContext]="{ $implicit: dropListValueElement }">
-                </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>
-            </ng-container>
-        </ng-container>
-
-        <ng-template #dropObject let-value>
-          <div class="item"
-               [style.background-color]="elementModel.styling.itemBackgroundColor"
-               cdkDrag [cdkDragData]="{ element: value }"
-               (cdkDragStarted)="dragStart($event)" (cdkDragEnded)="dragEnd()" (cdkDragEntered)="dragEnter($event)">
-            <div *cdkDragPreview
-                 [style.font-size.px]="elementModel.styling.fontSize"
-                 [style.background-color]="elementModel.styling.itemBackgroundColor">
-              {{value.text}}
-            </div>
-            <div class="drag-placeholder" *cdkDragPlaceholder
-                 [class.drag-placeholder-border]="placeholderDimensions.width !== '0px'"
-                 [style.height]="placeholderDimensions.height"
-                 [style.width]="placeholderDimensions.width">
-            </div>
-            {{value.text}}
-          </div>
-        </ng-template>
-      </div>
-    </div>
-  `,
-  styles: [
-    '.list-container {display: flex; flex-direction: column; width: 100%; height: 100%;}',
-    '.list {width: 100%; height: 100%; border-radius: 5px; overflow: hidden}',
-    '.item {border-radius: 5px; padding: 0 5px; height: 100%; text-align: center;}',
-    '.item:not(:last-child) {margin-bottom: 5px;}',
-    '.item:active {cursor: grabbing}',
-    '.errors {box-sizing: border-box; border: 2px solid #f44336 !important;}',
-    '.error-message {font-size: 75%; margin-top: 10px;}',
-    '.cdk-drag-preview {padding: 8px 20px; border-radius: 5px; box-shadow: 2px 2px 5px black;}',
-    '.drag-placeholder {background-color: lightgrey; transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);}',
-    '.drag-placeholder-border {box-sizing: border-box; border: solid 3px #999; border-radius: 5px}',
-    '.cdk-drag-animating {transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);}',
-
-    '.dropList-highlight.cdk-drop-list-receiving {border: solid;}',
-    '.dropList-highlight.cdk-drop-list-dragging {border: solid;}'
-  ]
-})
-export class DropListSimpleComponent extends FormElementComponent {
-  @Input() elementModel!: DropListSimpleElement;
-  placeholderDimensions: { width: string, height: string } = { width: '1px', height: '1px' };
-
-  bodyElement: HTMLElement = document.body;
-
-  dragStart(event: CdkDragStart<DropListSimpleComponent>): void {
-    this.setPlaceholderDimensions(
-      event.source.dropContainer.data.elementFormControl.value.length - 1,
-      event.source.dropContainer.data.elementModel.orientation
-    );
-    this.bodyElement.classList.add('inheritCursors');
-    this.bodyElement.style.cursor = 'grabbing';
-  }
-
-  dragEnd(): void {
-    this.bodyElement.classList.remove('inheritCursors');
-    this.bodyElement.style.cursor = 'unset';
-  }
-
-  drop(event: CdkDragDrop<DropListSimpleComponent>): void {
-    if (!this.elementModel.readOnly) {
-      if (event.previousContainer === event.container) {
-        moveItemInArray(event.container.data.elementFormControl.value as unknown as DragNDropValueObject[],
-          event.previousIndex,
-          event.currentIndex);
-        this.elementFormControl.setValue(
-          (event.container.data.elementFormControl.value as DragNDropValueObject[])
-        );
-      } else {
-        transferArrayItem(
-          event.previousContainer.data.elementFormControl.value as unknown as DragNDropValueObject[],
-          event.container.data.elementFormControl.value as unknown as DragNDropValueObject[],
-          event.previousIndex,
-          event.currentIndex
-        );
-        event.previousContainer.data.elementFormControl.setValue(
-          (event.previousContainer.data.elementFormControl.value as DragNDropValueObject[])
-        );
-      }
-      this.elementFormControl.setValue(
-        (event.container.data.elementFormControl.value as DragNDropValueObject[])
-      );
-    }
-  }
-
-  dragEnter(event: CdkDragEnter<DropListSimpleComponent | DropListComponent, { element: DragNDropValueObject }>) {
-    const presentValueIDs = event.container.data.elementFormControl.value
-      .map((value: DragNDropValueObject) => value.id);
-    const itemCountOffset = presentValueIDs.includes(event.item.data.element.id) ? 1 : 0;
-    this.setPlaceholderDimensions(
-      presentValueIDs.length - itemCountOffset,
-      event.container.data.elementModel.orientation);
-  }
-
-  setPlaceholderDimensions(itemsCount: number, orientation: unknown): void {
-    switch (orientation) {
-      case 'vertical': {
-        this.placeholderDimensions.width = '100%';
-        this.placeholderDimensions.height = itemsCount ? '1px' : '100%';
-        break;
-      }
-      case 'horizontal': {
-        this.placeholderDimensions.width = itemsCount ? '1px' : '100%';
-        this.placeholderDimensions.height = '100%';
-        break;
-      }
-      default: { // 'flex'
-        this.placeholderDimensions.width = itemsCount ? '0px' : '100%';
-        this.placeholderDimensions.height = itemsCount ? '0px' : '100%';
-      }
-    }
-  }
-
-  onlyOneItemPredicate = (drag: CdkDrag, drop: CdkDropList): boolean => (
-    drop.data.elementFormControl.value.length < 1
-  );
-}
diff --git a/projects/common/components/compound-elements/cloze/compound-child-overlay.component.ts b/projects/common/components/compound-elements/cloze/compound-child-overlay.component.ts
index f41139468..4dd7a4f3a 100644
--- a/projects/common/components/compound-elements/cloze/compound-child-overlay.component.ts
+++ b/projects/common/components/compound-elements/cloze/compound-child-overlay.component.ts
@@ -6,7 +6,6 @@ import { FormGroup } from '@angular/forms';
 import { ElementComponent } from '../../../directives/element-component.directive';
 import { ToggleButtonElement } from 'common/models/elements/compound-elements/cloze/cloze-child-elements/toggle-button';
 import { TextFieldSimpleElement } from 'common/models/elements/compound-elements/cloze/cloze-child-elements/text-field-simple';
-import { DropListSimpleElement } from 'common/models/elements/compound-elements/cloze/cloze-child-elements/drop-list-simple';
 import { ValueChangeElement } from 'common/models/elements/element';
 
 @Component({
@@ -21,13 +20,14 @@ import { ValueChangeElement } from 'common/models/elements/element';
                                 [style.width.px]="element.width"
                                 [style.height.px]="element.height">
       </aspect-text-field-simple>
-      <aspect-drop-list-simple *ngIf="element.type === 'drop-list-simple'" #childComponent
+      <aspect-drop-list *ngIf="element.type === 'drop-list'" #childComponent
+                               [clozeContext]="true"
                                [style.pointer-events]="editorMode ? 'none' : 'auto'"
                                [parentForm]="parentForm"
                                [elementModel]="$any(element)"
                                [style.width.px]="element.width"
                                [style.height.px]="element.height">
-      </aspect-drop-list-simple>
+      </aspect-drop-list>
       <aspect-toggle-button *ngIf="element.type === 'toggle-button'" #childComponent
                             [style.pointer-events]="editorMode ? 'none' : 'auto'"
                             [parentForm]="parentForm"
@@ -47,12 +47,12 @@ import { ValueChangeElement } from 'common/models/elements/element';
     ':host {vertical-align: middle;}',
     ':host > div {border-radius: 3px;}',
     ':host div > * {display: inline-block; padding-bottom: 2px; box-sizing: border-box;}',
-    'aspect-drop-list-simple, aspect-text-field-simple {width: 100%; height: 100%;}',
-    'aspect-drop-list-simple {line-height: unset; vertical-align: top;}'
+    'aspect-drop-list, aspect-text-field-simple {width: 100%; height: 100%;}',
+    'aspect-drop-list {line-height: unset; vertical-align: top;}'
   ]
 })
 export class CompoundChildOverlayComponent { // TODO rename to ClozeChildOverlay
-  @Input() element!: ToggleButtonElement | TextFieldSimpleElement | DropListSimpleElement;
+  @Input() element!: ToggleButtonElement | TextFieldSimpleElement;
   @Input() parentForm!: FormGroup;
   @Input() editorMode: boolean = false;
   @Input() lineHeight!: number;
diff --git a/projects/common/components/input-elements/drop-list.component.ts b/projects/common/components/input-elements/drop-list.component.ts
index ffb1cbc74..f4b74ec61 100644
--- a/projects/common/components/input-elements/drop-list.component.ts
+++ b/projects/common/components/input-elements/drop-list.component.ts
@@ -1,225 +1,254 @@
-import { Component, Input } from '@angular/core';
+// eslint-disable-next-line max-classes-per-file
 import {
-  CdkDragDrop, CdkDragEnter, CdkDragStart
-} from '@angular/cdk/drag-drop/drag-events';
-import {
-  CdkDrag, CdkDropList, moveItemInArray
-} from '@angular/cdk/drag-drop';
+  AfterViewInit,
+  Component, ElementRef, Input, OnDestroy, OnInit, Pipe, PipeTransform, ViewChild
+} from '@angular/core';
 import { DropListElement } from 'common/models/elements/input-elements/drop-list';
 import { DragNDropValueObject } from 'common/models/elements/element';
-import {
-  DropListSimpleComponent
-} from 'common/components/compound-elements/cloze/cloze-child-elements/drop-list-simple.component';
 import { FormElementComponent } from '../../directives/form-element-component.directive';
 
 @Component({
   selector: 'aspect-drop-list',
   template: `
-    <div class="list-container" fxLayout="column">
-      <!-- Border width is a workaround to enable/disable the Material cdk-drop-list-receiving-->
-      <!-- class style.-->
-      <!-- min-height for the following div is important for iOS 14!
-      iOS 14 is not able to determine the height of the flex container-->
-      <div class="list"
-           [ngClass]="{ 'align-flex' : elementModel.orientation === 'flex', 'copyOnDrop': elementModel.copyOnDrop }"
-           [class.errors]="elementFormControl.errors && elementFormControl.touched"
-           [style.min-height.px]="elementModel.position.useMinHeight ? elementModel.height - 6 : null"
-           [class.dropList-highlight]="elementModel.highlightReceivingDropList"
-           [style.outline-color]="elementModel.highlightReceivingDropListColor"
-           [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
-           [id]="elementModel.id"
-           [cdkDropListData]="this"
-           [cdkDropListConnectedTo]="elementModel.connectedTo"
-           [cdkDropListOrientation]="elementModel.orientation !== 'flex' ? $any(elementModel.orientation) : ''"
-           [cdkDropListEnterPredicate]="onlyOneItemPredicate"
-           tabindex="0"
-           (focusout)="elementFormControl.markAsTouched()"
-           (cdkDropListDropped)="drop($event)">
-
-        <ng-container *ngIf="!parentForm">
-          <ng-container *ngFor="let dropListValueElement of $any(elementModel.value); let index = index;">
-            <ng-container [ngTemplateOutlet]="dropObject"
-                          [ngTemplateOutletContext]="{ $implicit: dropListValueElement, index: index }">
-            </ng-container>
-          </ng-container>
-        </ng-container>
-
-        <ng-container *ngIf="parentForm">
-          <ng-container *ngFor="let dropListValueElement of elementFormControl.value; let index = index;">
-            <ng-container [ngTemplateOutlet]="dropObject"
-                          [ngTemplateOutletContext]="{ $implicit: dropListValueElement, index: index }">
-            </ng-container>
-          </ng-container>
-        </ng-container>
-        <!--Leave template within the dom to ensure dragNdrop-->
-        <ng-template #dropObject let-dropListValueElement let-index="index">
-          <div class="item text-item" *ngIf="!dropListValueElement.imgSrc"
-               [ngClass]="{ 'vertical-orientation' : elementModel.orientation === 'vertical',
-                      'horizontal-orientation' : elementModel.orientation === 'horizontal'}"
-               [style.background-color]="elementModel.styling.itemBackgroundColor"
-               cdkDrag
-               [cdkDragData]="{ element: dropListValueElement, index: index }"
-               (cdkDragStarted)="dragStart(index, $event)" (cdkDragEnded)="dragEnd()" (cdkDragEntered)="dragEnter($event)">
-            <div *cdkDragPreview
-                 [style.font-size.px]="elementModel.styling.fontSize"
-                 [style.background-color]="elementModel.styling.itemBackgroundColor">
-              {{dropListValueElement.text}}
-            </div>
-            <div class="drag-placeholder" *cdkDragPlaceholder
-                 [class.drag-placeholder-border]="placeholderDimensions.width !== '0px'"
-                 [style.padding]="0"
-                 [style.margin]="0"
-                 [style.height]="placeholderDimensions.height"
-                 [style.width]="placeholderDimensions.width">
-            </div>
-            {{dropListValueElement.text}}
-          </div>
-
-          <!-- actual placeholder when item is being dragged from copy-list -->
-          <div *ngIf="elementModel.copyOnDrop && draggedItemIndex === index" class="item text-item"
-               [style.font-size.px]="elementModel.styling.fontSize"
-               [ngClass]="{ 'vertical-orientation' : elementModel.orientation === 'vertical',
-                            'horizontal-orientation' : elementModel.orientation === 'horizontal'}"
-               [style.background-color]="elementModel.styling.itemBackgroundColor">
-            {{dropListValueElement.text}}
-          </div>
-
-          <img *ngIf="dropListValueElement.imgSrc"
-               [src]="dropListValueElement.imgSrc | safeResourceUrl" alt="Image Placeholder"
-               [style.display]="elementModel.orientation === 'flex' ? '' : 'block'"
-               class="item"
-               [ngClass]="{ 'vertical-orientation' : elementModel.orientation === 'vertical',
-                      'horizontal-orientation' : elementModel.orientation === 'horizontal'}"
-               cdkDrag [cdkDragData]="{ element: dropListValueElement, index: index }"
-               (cdkDragStarted)="dragStart(index, $event)" (cdkDragEnded)="dragEnd()"
-               [style.object-fit]="'scale-down'">
-          <img *ngIf="elementModel.copyOnDrop && draggedItemIndex === index && dropListValueElement.imgSrc"
-               [src]="dropListValueElement.imgSrc | safeResourceUrl" alt="Image Placeholder"
-               [style.display]="elementModel.orientation === 'flex' ? '' : 'block'"
-               class="item"
-               [ngClass]="{ 'vertical-orientation' : elementModel.orientation === 'vertical',
-                      'horizontal-orientation' : elementModel.orientation === 'horizontal'}"
-               [style.object-fit]="'scale-down'">
-        </ng-template>
-      </div>
-      <mat-error *ngIf="elementFormControl.errors && elementFormControl.touched"
-                 class="error-message">
-        {{elementFormControl.errors | errorTransform: elementModel}}
-      </mat-error>
+    <div class="list" [id]="elementModel.id"
+         [fxLayout]="elementModel.orientation | droplistLayout"
+         [fxLayoutAlign]="elementModel.orientation |  droplistLayoutAlign"
+         [ngClass]="{ 'vertical-orientation' : elementModel.orientation === 'vertical',
+                      'horizontal-orientation' : elementModel.orientation === 'horizontal',
+                      'clozeContext': clozeContext}"
+         [style.min-height.px]="elementModel.position?.useMinHeight ? elementModel.height : undefined"
+         [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"
+         [class.errors]="elementFormControl.errors && elementFormControl.touched"
+         [style.outline-color]="elementModel.highlightReceivingDropListColor"
+         [class.highlight-valid-drop]="highlightValidDrop"
+         [class.highlight-as-receiver]="highlightAsReceiver"
+         (drop)="drop($event)" (dragenter)="dragEnterList($event)" (dragleave)="dragLeaveList($event)"
+         (dragover)="$event.preventDefault()">
+      <ng-container *ngFor="let dropListValueElement of viewModel let index = index;">
+        <div class="list-item"
+             draggable="true"
+             (dragstart)="dragStart($event, dropListValueElement, index)" (dragend)="dragEnd($event)"
+             (dragenter)="dragEnterItem($event)"
+             [class.show-as-placeholder]="showAsPlaceholder && placeHolderIndex === index"
+             [class.show-as-hidden]="hidePlaceholder && placeHolderIndex === index"
+             [style.pointer-events]="dragging && elementModel.isSortList === false ? 'none' : ''"
+             [style.background-color]="elementModel.styling.itemBackgroundColor">
+          <span>{{dropListValueElement.text}}</span>
+        </div>
+        <img *ngIf="dropListValueElement.imgSrc"
+             class="list-item"
+             [src]="dropListValueElement.imgSrc | safeResourceUrl" alt="Image Placeholder"
+             draggable="true" [id]="dropListValueElement.id"
+             (dragstart)="dragStart($event, dropListValueElement, index)" (dragend)="dragEnd($event)"
+             [style.object-fit]="'scale-down'">
+      </ng-container>
     </div>
+    <mat-error *ngIf="elementFormControl.errors && elementFormControl.touched"
+               class="error-message">
+      {{elementFormControl.errors | errorTransform: elementModel}}
+    </mat-error>
   `,
   styles: [
-    '.list-container {width: 100%; height: 100%;}',
-    '.list {border-radius: 5px; width: calc(100% - 6px); overflow: hidden}',
-    '.list {height: calc(100% - 6px); margin-top: 3px; margin-left: 3px;}',
-    '.text-item {border-radius: 5px; padding: 10px;}',
-    '.item {cursor: grab}',
-    '.item:active {cursor: grabbing}',
-    '.copyOnDrop .item {transform: none !important}',
-    '.vertical-orientation.item:not(:last-child) {margin-bottom: 5px;}',
-    '.horizontal-orientation.item:not(:last-child) {margin-right: 5px}',
+    '.list {width: 100%; height: 100%; background-color: rgb(244, 244, 242); padding: 3px;}',
+    ':not(.clozeContext) .list-item {border-radius: 5px; padding: 10px;}',
+    '.vertical-orientation .list-item:not(:last-child) {margin-bottom: 5px;}',
+    '.horizontal-orientation .list-item:not(:last-child) {margin-right: 5px;}',
     '.errors {outline: 2px solid #f44336 !important;}',
-    '.error-message {font-size: 75%; margin-top: 10px;}',
-    '.cdk-drag-preview {padding: 8px 20px; border-radius: 5px; z-index: 5; box-shadow: 2px 2px 5px black;}',
-    '.drag-placeholder-border {box-sizing: border-box; border: solid 3px #999; border-radius: 5px}',
-    '.drag-placeholder {background-color: lightgrey; transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);}',
-    '.cdk-drag-animating {transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);}',
-    '.dropList-highlight.cdk-drop-list-receiving {outline: solid;}',
-    '.dropList-highlight.cdk-drop-list-dragging {outline: solid;}',
-    '.align-flex {flex: 1 1 auto; flex-flow: row wrap; display: flex; place-content: center space-around; gap: 10px}',
-    ':host .copyOnDrop .cdk-drag-placeholder {position: relative; visibility: hidden;}',
-    ':host .copyOnDrop .cdk-drag-placeholder {height: 0 !important; min-height: 0 !important;}',
-    ':host .copyOnDrop .cdk-drag-placeholder {margin: 0 !important; padding: 0 !important; border: 0;}'
+    '.list-item {cursor: grab;}',
+    '.list-item:active {cursor: grabbing}',
+    '.show-as-placeholder {opacity: 0.5 !important; pointer-events: none;}',
+    '.highlight-valid-drop {background-color: lightblue !important;}',
+    '.highlight-as-receiver {outline: 2px solid;}',
+    '.show-as-hidden {visibility: hidden;}'
   ]
 })
-export class DropListComponent extends FormElementComponent {
+export class DropListComponent extends FormElementComponent implements OnInit, AfterViewInit, OnDestroy {
   @Input() elementModel!: DropListElement;
+  @Input() clozeContext: boolean = false;
+  @ViewChild('placeholder') placeholder!: ElementRef<HTMLElement>;
+  static dragAndDropComponents: { [id: string]: DropListComponent } = {};
+
+  viewModel: DragNDropValueObject[] = [];
+  placeHolderIndex?: number;
+  highlightAsReceiver = false;
+
+  dragging = false;
+
+  showAsPlaceholder = false;
+  hidePlaceholder = false;
+  highlightValidDrop = false;
+
+  static draggedElement?: DragNDropValueObject;
+  static sourceList?: DropListComponent;
 
-  bodyElement: HTMLElement = document.body;
-  draggedItemIndex: number | null = null;
-  placeholderDimensions: { width: string, height: string } = { width: '1px', height: '1px' };
-
-  dragStart(itemIndex: number, event: CdkDragStart<DropListComponent>): void {
-    this.setPlaceholderDimensions(
-      event.source.dropContainer.data.elementFormControl.value.length - 1,
-      event.source.dropContainer.data.elementModel.orientation
-    );
-    this.draggedItemIndex = itemIndex;
-    this.bodyElement.classList.add('inheritCursors');
-    this.bodyElement.style.cursor = 'grabbing';
+  ngOnInit() {
+    super.ngOnInit();
+    this.viewModel = [...this.elementFormControl.value];
   }
 
-  dragEnd(): void {
-    this.draggedItemIndex = null;
-    this.bodyElement.classList.remove('inheritCursors');
-    this.bodyElement.style.cursor = 'unset';
+  ngAfterViewInit() {
+    DropListComponent.dragAndDropComponents[this.elementModel.id] = this;
   }
 
-  drop(event: CdkDragDrop<DropListComponent>): void {
-    if (event.previousContainer === event.container && !event.container.data.elementModel.copyOnDrop) {
-      moveItemInArray(
-        event.container.data.elementFormControl.value as unknown as DragNDropValueObject[],
-        event.previousIndex,
-        event.currentIndex
-      );
-      this.elementFormControl.setValue(
-        (event.container.data.elementFormControl.value as DragNDropValueObject[])
-      );
+  dragStart(dragEvent: DragEvent,
+            dropListValueElement: DragNDropValueObject,
+            sourceListIndex: number) {
+    if (dragEvent.dataTransfer) {
+      dragEvent.dataTransfer.effectAllowed = 'copyMove';
+      dragEvent.dataTransfer.setDragImage(
+        DropListComponent.createDragImage(dragEvent.target as Node, dropListValueElement.id), 0, 0);
+    }
+
+    DropListComponent.draggedElement = dropListValueElement;
+    DropListComponent.sourceList = this;
+    this.placeHolderIndex = sourceListIndex;
+    if (this.elementModel.isSortList) {
+      this.showAsPlaceholder = true;
     } else {
-      const presentValueIDs = event.container.data.elementFormControl.value
-        .map((value2: DragNDropValueObject) => value2.id);
-      if (!presentValueIDs.includes(event.item.data.element.id)) {
-        event.container.data.elementFormControl.value.splice(event.currentIndex, 0, event.item.data.element);
-        event.container.data.elementFormControl
-          .setValue(event.container.data.elementFormControl.value);
-      }
-      if (!event.previousContainer.data.elementModel.copyOnDrop) {
-        event.previousContainer.data.elementFormControl.value.splice(event.item.data.index, 1);
-        event.previousContainer.data.elementFormControl.setValue(
-          (event.previousContainer.data.elementFormControl.value as DragNDropValueObject[])
-        );
+      this.hidePlaceholder = true;
+      this.highlightValidDrop = true;
+    }
+
+    Object.entries(DropListComponent.dragAndDropComponents)
+      .forEach(([, value]) => {
+        value.dragging = true;
+      });
+
+    if (this.elementModel.highlightReceivingDropList) {
+      this.highlightAsReceiver = true;
+      this.elementModel.connectedTo.forEach(connectedDropListID => {
+        DropListComponent.dragAndDropComponents[connectedDropListID].highlightAsReceiver = true;
+      });
+    }
+  }
+
+  static createDragImage(baseElement: Node, baseID: string): HTMLElement {
+    const dragImage: HTMLElement = baseElement.cloneNode(true) as HTMLElement;
+    dragImage.id = `${baseID}-dragimage`;
+    dragImage.style.display = 'inline-block';
+    document.body.appendChild(dragImage);
+    return dragImage;
+  }
+
+  dragEnterItem(event: DragEvent) {
+    event.preventDefault();
+
+    if (this.elementModel.isSortList && DropListComponent.sourceList === this) {
+      const sourceIndex: number = this.placeHolderIndex as number;
+      const targetIndex: number = Array.from((event.target as any).parentNode.children).indexOf(event.target);
+      const removedElement = this.viewModel.splice(sourceIndex, 1)[0];
+      this.viewModel.splice(targetIndex, 0, removedElement);
+      this.placeHolderIndex = targetIndex;
+    }
+  }
+
+  dragEnterList(event: DragEvent) {
+    event.preventDefault();
+
+    if (!this.elementModel.isSortList) {
+      this.highlightValidDrop = true;
+    } else if (DropListComponent.sourceList !== this) {
+      this.viewModel.push(DropListComponent.draggedElement as DragNDropValueObject);
+      const sourceList = DropListComponent.sourceList as DropListComponent;
+      sourceList.viewModel.splice(sourceList.placeHolderIndex as number, 1);
+      sourceList.elementFormControl.setValue(sourceList.viewModel);
+      sourceList.placeHolderIndex = undefined;
+      DropListComponent.sourceList = this;
+      this.placeHolderIndex = this.viewModel.length > 0 ? this.viewModel.length - 1 : 0;
+    }
+  }
+
+  dragLeaveList(event: DragEvent) {
+    event.preventDefault();
+    this.highlightValidDrop = false;
+  }
+
+  drop(event: DragEvent) {
+    event.preventDefault();
+
+    if (DropListComponent.sourceList === this && this.elementModel.isSortList) {
+      this.elementFormControl.setValue(this.viewModel);
+    } else if (this.isDropAllowed((DropListComponent.sourceList as DropListComponent).elementModel.connectedTo)) {
+      const presentValueIDs = this.elementFormControl.value
+        .map((valueValue: DragNDropValueObject) => valueValue.id);
+      if (!presentValueIDs.includes(DropListComponent.draggedElement?.id)) {
+        this.viewModel.push(DropListComponent.draggedElement as DragNDropValueObject);
+        this.elementFormControl.setValue(this.viewModel);
+        if (!DropListComponent.sourceList?.elementModel.copyOnDrop) {
+          DropListComponent.sourceList?.viewModel.splice(this.placeHolderIndex as number, 1);
+          DropListComponent.sourceList?.elementFormControl.setValue(DropListComponent.sourceList.viewModel);
+        }
       }
+    } else {
+      console.log('Not an allowed target list');
     }
+    this.dragEnd();
+  }
+
+  isDropAllowed(connectedDropLists: string[]): boolean {
+    return (connectedDropLists as string[]).includes(this.elementModel.id) &&
+           !(this.elementModel.onlyOneItem && this.elementModel.value.length > 0);
+    // TODO presentValueIDs?
+  }
+
+  dragEnd(event?: DragEvent) {
+    event?.preventDefault();
+
+    Object.entries(DropListComponent.dragAndDropComponents)
+      .forEach(([, value]) => {
+        value.highlightAsReceiver = false;
+        value.dragging = false;
+        value.highlightValidDrop = false;
+      });
+    if (DropListComponent.sourceList) DropListComponent.sourceList.placeHolderIndex = undefined;
+    this.placeHolderIndex = undefined;
+
+    document.getElementById(`${DropListComponent.draggedElement?.id}-dragimage`)?.remove();
   }
 
-  dragEnter(event: CdkDragEnter<DropListSimpleComponent | DropListComponent, { element: DragNDropValueObject }>) {
-    const presentValueIDs = event.container.data.elementFormControl.value
-      .map((value: DragNDropValueObject) => value.id);
-    const itemCountOffset = presentValueIDs.includes(event.item.data.element.id) ? 1 : 0;
-    this.setPlaceholderDimensions(
-      presentValueIDs.length - itemCountOffset,
-      event.container.data.elementModel.orientation);
+  ngOnDestroy(): void {
+    delete DropListComponent.dragAndDropComponents[this.elementModel.id];
   }
+}
 
-  setPlaceholderDimensions(itemsCount: number, orientation: unknown): void {
+@Pipe({
+  name: 'droplistLayout'
+})
+export class DropListLayoutPipe implements PipeTransform {
+  transform(orientation: string): string {
     switch (orientation) {
-      case 'vertical': {
-        this.placeholderDimensions.width = '100%';
-        this.placeholderDimensions.height = itemsCount ? '1px' : '100%';
-        break;
-      }
-      case 'horizontal': {
-        this.placeholderDimensions.width = itemsCount ? '1px' : '100%';
-        this.placeholderDimensions.height = '100%';
-        break;
-      }
-      default: { // 'flex'
-        this.placeholderDimensions.width = itemsCount ? '0px' : '100%';
-        this.placeholderDimensions.height = itemsCount ? '0px' : '100%';
-      }
+      case 'horizontal':
+        return 'row';
+      case 'vertical':
+        return 'column';
+      case 'flex':
+        return 'row wrap';
+      default:
+        throw Error(`droplist orientation invalid: ${orientation}`);
     }
   }
+}
 
-  onlyOneItemPredicate = (drag: CdkDrag, drop: CdkDropList): boolean => (
-    !drop.data.elementModel.onlyOneItem || drop.data.elementFormControl.value.length < 1
-  );
+@Pipe({
+  name: 'droplistLayoutAlign'
+})
+export class DropListLayoutAlignPipe implements PipeTransform {
+  transform(orientation: string): string {
+    switch (orientation) {
+      case 'horizontal':
+        return 'start start';
+      case 'vertical':
+        return 'start stretch';
+      case 'flex':
+        return 'space-around center';
+      default:
+        throw Error(`droplist orientation invalid: ${orientation}`);
+    }
+  }
 }
diff --git a/projects/common/models/elements/compound-elements/cloze/cloze-child-elements/drop-list-simple.ts b/projects/common/models/elements/compound-elements/cloze/cloze-child-elements/drop-list-simple.ts
deleted file mode 100644
index 7b7022b7b..000000000
--- a/projects/common/models/elements/compound-elements/cloze/cloze-child-elements/drop-list-simple.ts
+++ /dev/null
@@ -1,67 +0,0 @@
-import {
-  BasicStyles, DragNDropValueObject, InputElement, AnswerScheme,
-  AnswerSchemeValue, UIElement
-} from 'common/models/elements/element';
-import { Type } from '@angular/core';
-import { ElementComponent } from 'common/directives/element-component.directive';
-import {
-  DropListSimpleComponent
-} from 'common/components/compound-elements/cloze/cloze-child-elements/drop-list-simple.component';
-import { DropListElement } from 'common/models/elements/input-elements/drop-list';
-
-export class DropListSimpleElement extends InputElement {
-  value: DragNDropValueObject[] = [];
-  connectedTo: string[] = [];
-  copyOnDrop: boolean = false;
-  highlightReceivingDropList: boolean = false;
-  highlightReceivingDropListColor: string = '#006064';
-  styling: BasicStyles & {
-    itemBackgroundColor: string;
-  };
-
-  constructor(element: Partial<DropListSimpleElement>) {
-    super({ width: 150, height: 30, ...element });
-    this.value = element.value || [];
-    if (element.connectedTo) this.connectedTo = element.connectedTo;
-    if (element.copyOnDrop) this.copyOnDrop = element.copyOnDrop;
-    if (element.highlightReceivingDropList) this.highlightReceivingDropList = element.highlightReceivingDropList;
-    if (element.highlightReceivingDropListColor) {
-      this.highlightReceivingDropListColor = element.highlightReceivingDropListColor;
-    }
-    this.styling = {
-      ...UIElement.initStylingProps({
-        backgroundColor: '#f4f4f2',
-        itemBackgroundColor: '#c9e0e0',
-        ...element.styling
-      })
-    };
-  }
-
-  hasAnswerScheme(): boolean {
-    return Boolean(this.getAnswerScheme);
-  }
-
-  getAnswerScheme(dropLists: Array<DropListElement | DropListSimpleElement>): AnswerScheme {
-    return {
-      id: this.id,
-      type: 'string',
-      format: '',
-      multiple: true,
-      nullable: false,
-      values: this.getAnswerSchemeValues(dropLists),
-      valuesComplete: true
-    };
-  }
-
-  getAnswerSchemeValues(dropLists: Array<DropListElement | DropListSimpleElement>): AnswerSchemeValue[] {
-    const valueDropLists = dropLists.filter(dropList => dropList.connectedTo.includes(this.id));
-    return [this, ...valueDropLists]
-      .map(dropList => dropList.value as DragNDropValueObject[])
-      .flat()
-      .map(option => ({ value: option.id, label: option.text as string }));
-  }
-
-  getElementComponent(): Type<ElementComponent> {
-    return DropListSimpleComponent;
-  }
-}
diff --git a/projects/common/models/elements/compound-elements/cloze/cloze.ts b/projects/common/models/elements/compound-elements/cloze/cloze.ts
index fa9bf59ca..eaa8a05bc 100644
--- a/projects/common/models/elements/compound-elements/cloze/cloze.ts
+++ b/projects/common/models/elements/compound-elements/cloze/cloze.ts
@@ -4,7 +4,7 @@ import {
   InputElement,
   PositionedUIElement,
   PositionProperties,
-  UIElement, UIElementValue
+  UIElement, UIElementType, UIElementValue
 } from 'common/models/elements/element';
 import { Type } from '@angular/core';
 import { ElementComponent } from 'common/directives/element-component.directive';
@@ -12,11 +12,9 @@ import { ClozeComponent } from 'common/components/compound-elements/cloze/cloze.
 import {
   TextFieldSimpleElement
 } from 'common/models/elements/compound-elements/cloze/cloze-child-elements/text-field-simple';
-import {
-  DropListSimpleElement
-} from 'common/models/elements/compound-elements/cloze/cloze-child-elements/drop-list-simple';
 import { ToggleButtonElement } from 'common/models/elements/compound-elements/cloze/cloze-child-elements/toggle-button';
 import { ButtonElement } from 'common/models/elements/button/button';
+import { DropListElement } from 'common/models/elements/input-elements/drop-list';
 
 export class ClozeElement extends CompoundElement implements PositionedUIElement {
   document: ClozeDocument = { type: 'doc', content: [] };
@@ -145,8 +143,9 @@ export class ClozeElement extends CompoundElement implements PositionedUIElement
       case 'text-field-simple':
         newElement = new TextFieldSimpleElement(elementModel as TextFieldSimpleElement);
         break;
-      case 'drop-list-simple':
-        newElement = new DropListSimpleElement(elementModel as DropListSimpleElement);
+      case 'drop-list':
+      case 'drop-list-simple' as UIElementType: // keep here for compatibility
+        newElement = new DropListElement({ ...elementModel as DropListElement, type: 'drop-list' });
         break;
       case 'toggle-button':
         newElement = new ToggleButtonElement(elementModel as ToggleButtonElement);
diff --git a/projects/common/models/elements/compound-elements/cloze/tiptap-editor-extensions/drop-list.ts b/projects/common/models/elements/compound-elements/cloze/tiptap-editor-extensions/drop-list.ts
index 2ca23e9bb..f546d6b28 100644
--- a/projects/common/models/elements/compound-elements/cloze/tiptap-editor-extensions/drop-list.ts
+++ b/projects/common/models/elements/compound-elements/cloze/tiptap-editor-extensions/drop-list.ts
@@ -1,7 +1,5 @@
 import { Node, mergeAttributes } from '@tiptap/core';
-import {
-  DropListSimpleElement
-} from 'common/models/elements/compound-elements/cloze/cloze-child-elements/drop-list-simple';
+import { DropListElement } from 'common/models/elements/input-elements/drop-list';
 
 const DropListExtension =
   Node.create({
@@ -12,7 +10,7 @@ const DropListExtension =
     addAttributes() {
       return {
         model: {
-          default: new DropListSimpleElement({ type: 'drop-list-simple' })
+          default: new DropListElement({ type: 'drop-list' })
         }
       };
     },
diff --git a/projects/common/models/elements/element.ts b/projects/common/models/elements/element.ts
index 23deb30da..3ce40b183 100644
--- a/projects/common/models/elements/element.ts
+++ b/projects/common/models/elements/element.ts
@@ -6,7 +6,7 @@ import { LikertRowElement } from 'common/models/elements/compound-elements/liker
 
 export type UIElementType = 'text' | 'button' | 'text-field' | 'text-field-simple' | 'text-area' | 'checkbox'
 | 'dropdown' | 'radio' | 'image' | 'audio' | 'video' | 'likert' | 'likert-row' | 'radio-group-images' | 'hotspot-image'
-| 'drop-list' | 'drop-list-simple' | 'cloze' | 'spell-correct' | 'slider' | 'frame' | 'toggle-button' | 'geometry';
+| 'drop-list' | 'cloze' | 'spell-correct' | 'slider' | 'frame' | 'toggle-button' | 'geometry';
 
 export type UIElementValue = string | number | boolean | undefined | UIElementType | InputElementValue |
 TextLabel | TextLabel[] | ClozeDocument | LikertRowElement[] | Hotspot[] |
@@ -34,7 +34,12 @@ export abstract class UIElement {
   }
 
   setProperty(property: string, value: UIElementValue): void {
-    this[property] = value;
+    if (Array.isArray(this[property])) { // keep array reference intact
+      (this[property] as UIElementValue[])
+        .splice(0, (this[property] as UIElementValue[]).length, ...(value as UIElementValue[]));
+    } else {
+      this[property] = value;
+    }
   }
 
   setStyleProperty(property: string, value: UIElementValue): void {
diff --git a/projects/common/models/elements/input-elements/drop-list.ts b/projects/common/models/elements/input-elements/drop-list.ts
index 0c33e5099..883ecbc67 100644
--- a/projects/common/models/elements/input-elements/drop-list.ts
+++ b/projects/common/models/elements/input-elements/drop-list.ts
@@ -1,25 +1,23 @@
 import { Type } from '@angular/core';
 import {
-  InputElement, PositionedUIElement,
+  InputElement,
   DragNDropValueObject,
   BasicStyles, PositionProperties,
   AnswerScheme, AnswerSchemeValue, UIElement
 } from 'common/models/elements/element';
 import { ElementComponent } from 'common/directives/element-component.directive';
 import { DropListComponent } from 'common/components/input-elements/drop-list.component';
-import {
-  DropListSimpleElement
-} from 'common/models/elements/compound-elements/cloze/cloze-child-elements/drop-list-simple';
 
-export class DropListElement extends InputElement implements PositionedUIElement {
+export class DropListElement extends InputElement {
   value: DragNDropValueObject[];
   onlyOneItem: boolean = false;
+  isSortList: boolean = false;
   connectedTo: string[] = [];
   copyOnDrop: boolean = false;
   orientation: 'vertical' | 'horizontal' | 'flex' = 'vertical';
   highlightReceivingDropList: boolean = false;
   highlightReceivingDropListColor: string = '#006064';
-  position: PositionProperties;
+  position: PositionProperties | undefined;
   styling: BasicStyles & {
     itemBackgroundColor: string;
   };
@@ -28,6 +26,7 @@ export class DropListElement extends InputElement implements PositionedUIElement
     super({ height: 100, ...element });
     this.value = element.value !== undefined ? [...element.value] : [];
     if (element.onlyOneItem) this.onlyOneItem = element.onlyOneItem;
+    if (element.isSortList) this.isSortList = element.isSortList;
     if (element.connectedTo) this.connectedTo = element.connectedTo;
     if (element.copyOnDrop) this.copyOnDrop = element.copyOnDrop;
     if (element.orientation) this.orientation = element.orientation;
@@ -35,21 +34,21 @@ export class DropListElement extends InputElement implements PositionedUIElement
     if (element.highlightReceivingDropListColor) {
       this.highlightReceivingDropListColor = element.highlightReceivingDropListColor;
     }
-    this.position = UIElement.initPositionProps({ useMinHeight: true, ...element.position });
-    this.styling = {
-      ...UIElement.initStylingProps({
-        backgroundColor: '#f4f4f2',
-        itemBackgroundColor: '#c9e0e0',
-        ...element.styling
-      })
-    };
+    this.position = element.position ?
+      UIElement.initPositionProps({ useMinHeight: true, ...element.position as Partial<PositionProperties> }) :
+      undefined;
+    this.styling = UIElement.initStylingProps({
+      backgroundColor: '#f4f4f2',
+      itemBackgroundColor: '#c9e0e0',
+      ...element.styling
+    });
   }
 
   hasAnswerScheme(): boolean {
     return Boolean(this.getAnswerScheme);
   }
 
-  getAnswerScheme(options: Array<DropListElement | DropListSimpleElement>): AnswerScheme {
+  getAnswerScheme(options: Array<DropListElement>): AnswerScheme {
     return {
       id: this.id,
       type: 'string',
@@ -61,7 +60,7 @@ export class DropListElement extends InputElement implements PositionedUIElement
     };
   }
 
-  private getAnswerSchemeValues(dropLists: Array<DropListElement | DropListSimpleElement>): AnswerSchemeValue[] {
+  private getAnswerSchemeValues(dropLists: Array<DropListElement>): AnswerSchemeValue[] {
     const valueDropLists = dropLists.filter(dropList => dropList.connectedTo.includes(this.id));
     if (valueDropLists.length || this.isSortingList()) {
       return [this, ...valueDropLists]
diff --git a/projects/common/models/section.ts b/projects/common/models/section.ts
index a50f7f180..fffe89e51 100644
--- a/projects/common/models/section.ts
+++ b/projects/common/models/section.ts
@@ -27,12 +27,11 @@ export class Section {
     if (section?.gridRowSizes !== undefined) this.gridRowSizes = section.gridRowSizes;
     if (section?.activeAfterID) this.activeAfterID = section.activeAfterID;
     this.elements =
-      section?.elements?.map(element => (
-        ElementFactory.createElement({
-          ...element,
-          position: UIElement.initPositionProps(element.position)
-        }) as PositionedUIElement)
-      ) || [];
+      section?.elements?.map(element => ElementFactory.createElement({
+        ...element,
+        position: UIElement.initPositionProps(element.position)
+      }) as PositionedUIElement) ||
+      [];
   }
 
   setProperty(property: string, value: UIElementValue): void {
@@ -58,7 +57,7 @@ export class Section {
   getAnswerScheme(dropLists: UIElement[]): AnswerScheme[] {
     return this.getAllElements()
       .filter(element => element.hasAnswerScheme())
-      .map(element => ((element.type === 'drop-list' || element.type === 'drop-list-simple') ?
+      .map(element => ((element.type === 'drop-list') ?
         (element as InputElement).getAnswerScheme(dropLists) :
         (element as InputElement | PlayerElement | TextElement | ImageElement).getAnswerScheme()));
   }
diff --git a/projects/common/models/unit.ts b/projects/common/models/unit.ts
index 0907972d7..de374d1c2 100644
--- a/projects/common/models/unit.ts
+++ b/projects/common/models/unit.ts
@@ -18,8 +18,7 @@ export class Unit {
 
   getAnswerScheme(): AnswerScheme[] {
     const dropLists = [
-      ...this.getAllElements('drop-list'),
-      ...this.getAllElements('drop-list-simple')
+      ...this.getAllElements('drop-list')
     ];
     return this.pages.map(page => page.getAnswerScheme(dropLists)).flat();
   }
diff --git a/projects/common/services/sanitization.service.ts b/projects/common/services/sanitization.service.ts
index 617aa16c6..e4af0b49f 100644
--- a/projects/common/services/sanitization.service.ts
+++ b/projects/common/services/sanitization.service.ts
@@ -311,7 +311,6 @@ export class SanitizationService {
     // repair child element types
     childElements.forEach(childElement => {
       childElement.type = childElement.type === 'text-field' ? 'text-field-simple' : childElement.type;
-      childElement.type = childElement.type === 'drop-list' ? 'drop-list-simple' : childElement.type;
     });
 
     return {
diff --git a/projects/common/shared.module.ts b/projects/common/shared.module.ts
index d17113c90..ecd0d1b83 100644
--- a/projects/common/shared.module.ts
+++ b/projects/common/shared.module.ts
@@ -50,13 +50,14 @@ import {
 } from './components/compound-elements/likert/likert-radio-button-group.component';
 import { ImageMagnifierComponent } from './components/media-elements/image-magnifier.component';
 import { RadioGroupImagesComponent } from './components/input-elements/radio-group-images.component';
-import { DropListComponent } from './components/input-elements/drop-list.component';
+import {
+  DropListComponent,
+  DropListLayoutAlignPipe,
+  DropListLayoutPipe
+} from './components/input-elements/drop-list.component';
 import { ClozeComponent } from './components/compound-elements/cloze/cloze.component';
 import { SliderComponent } from './components/input-elements/slider.component';
 import { SpellCorrectComponent } from './components/input-elements/spell-correct.component';
-import {
-  DropListSimpleComponent
-} from './components/compound-elements/cloze/cloze-child-elements/drop-list-simple.component';
 import { FrameComponent } from './components/frame/frame.component';
 import {
   ToggleButtonComponent
@@ -119,7 +120,6 @@ import { UpdateTextareaRowsPipe } from './pipes/update-textarea-rows.pipe';
     DropListComponent,
     ClozeComponent,
     HotspotImageComponent,
-    DropListSimpleComponent,
     SliderComponent,
     SpellCorrectComponent,
     FrameComponent,
@@ -134,7 +134,9 @@ import { UpdateTextareaRowsPipe } from './pipes/update-textarea-rows.pipe';
     MathAtanPipe,
     MathDegreesPipe,
     ArrayIncludesPipe,
-    UpdateTextareaRowsPipe
+    UpdateTextareaRowsPipe,
+    DropListLayoutPipe,
+    DropListLayoutAlignPipe
   ],
   exports: [
     CommonModule,
@@ -155,7 +157,6 @@ import { UpdateTextareaRowsPipe } from './pipes/update-textarea-rows.pipe';
     ToggleButtonComponent,
     TextFieldComponent,
     TextFieldSimpleComponent,
-    DropListSimpleComponent,
     TextAreaComponent,
     AudioComponent,
     VideoComponent,
diff --git a/projects/common/util/element.factory.ts b/projects/common/util/element.factory.ts
index 73a161461..68a258965 100644
--- a/projects/common/util/element.factory.ts
+++ b/projects/common/util/element.factory.ts
@@ -16,9 +16,6 @@ import { VideoElement } from 'common/models/elements/media-elements/video';
 import { LikertElement } from 'common/models/elements/compound-elements/likert/likert';
 import { RadioButtonGroupComplexElement } from 'common/models/elements/input-elements/radio-button-group-complex';
 import { DropListElement } from 'common/models/elements/input-elements/drop-list';
-import {
-  DropListSimpleElement
-} from 'common/models/elements/compound-elements/cloze/cloze-child-elements/drop-list-simple';
 import { ClozeElement } from 'common/models/elements/compound-elements/cloze/cloze';
 import { SliderElement } from 'common/models/elements/input-elements/slider';
 import { SpellCorrectElement } from 'common/models/elements/input-elements/spell-correct';
@@ -43,7 +40,6 @@ export abstract class ElementFactory {
     likert: LikertElement,
     'radio-group-images': RadioButtonGroupComplexElement,
     'drop-list': DropListElement,
-    'drop-list-simple': DropListSimpleElement,
     cloze: ClozeElement,
     slider: SliderElement,
     'spell-correct': SpellCorrectElement,
diff --git a/projects/editor/src/app/components/canvas/overlays/canvas-element-overlay.ts b/projects/editor/src/app/components/canvas/overlays/canvas-element-overlay.ts
index 9a64e1c46..e7a89a152 100644
--- a/projects/editor/src/app/components/canvas/overlays/canvas-element-overlay.ts
+++ b/projects/editor/src/app/components/canvas/overlays/canvas-element-overlay.ts
@@ -9,11 +9,14 @@ import { CompoundElementComponent } from 'common/directives/compound-element.dir
 import { ClozeComponent } from 'common/components/compound-elements/cloze/cloze.component';
 import { CompoundChildOverlayComponent } from
   'common/components/compound-elements/cloze/compound-child-overlay.component';
-import { UIElement } from 'common/models/elements/element';
+import { DragNDropValueObject, UIElement } from 'common/models/elements/element';
 import { GeometryComponent } from 'common/components/geometry/geometry.component';
 import { GeometryElement } from 'common/models/elements/geometry/geometry';
 import { UnitService } from '../../../services/unit.service';
 import { SelectionService } from '../../../services/selection.service';
+import { DropListComponent } from 'common/components/input-elements/drop-list.component';
+import { DropListElement } from 'common/models/elements/input-elements/drop-list';
+import { FormElementComponent } from 'common/directives/form-element-component.directive';
 
 @Directive()
 export abstract class CanvasElementOverlay implements OnInit, OnDestroy {
@@ -34,6 +37,14 @@ export abstract class CanvasElementOverlay implements OnInit, OnDestroy {
   ngOnInit(): void {
     this.childComponent = this.elementContainer.createComponent(this.element.getElementComponent());
     this.childComponent.instance.elementModel = this.element;
+    this.childComponent.changeDetectorRef.detectChanges(); // this fires onInit, which initializes the FormControl
+    if (this.childComponent.instance instanceof FormElementComponent) {
+      (this.childComponent.instance as FormElementComponent).elementFormControl.setValue(this.element.value);
+    }
+    // DropList keeps a special viewModel variable, which needs to be updated
+    if (this.childComponent.instance instanceof DropListComponent) {
+      (this.childComponent.instance as DropListComponent).viewModel = this.element.value as DragNDropValueObject[];
+    }
 
     // Make children not clickable. This way the only relevant events are managed by the overlay.
     this.childComponent.location.nativeElement.style.pointerEvents = 'none';
diff --git a/projects/editor/src/app/components/properties-panel/element-properties-panel.component.html b/projects/editor/src/app/components/properties-panel/element-properties-panel.component.html
index d7a996b46..c5356915f 100644
--- a/projects/editor/src/app/components/properties-panel/element-properties-panel.component.html
+++ b/projects/editor/src/app/components/properties-panel/element-properties-panel.component.html
@@ -48,13 +48,11 @@
     <mat-divider></mat-divider>
     <button mat-raised-button [disabled]="selectedElements.length > 1 ||
                                           combinedProperties.type == 'toggle-button' ||
-                                          combinedProperties.type == 'drop-list-simple' ||
                                           combinedProperties.type == 'text-field-simple'"
             (click)="duplicateElement()">
       {{'propertiesPanel.duplicateElement' | translate }}
     </button>
     <button mat-raised-button color="warn" [disabled]="combinedProperties.type == 'toggle-button' ||
-                                                       combinedProperties.type == 'drop-list-simple' ||
                                                        combinedProperties.type == 'text-field-simple'"
             (click)="deleteElement()">
       {{'propertiesPanel.deleteElement' | translate }}
diff --git a/projects/editor/src/app/components/properties-panel/model-properties-tab/input-groups/drop-list-properties.component.ts b/projects/editor/src/app/components/properties-panel/model-properties-tab/input-groups/drop-list-properties.component.ts
index eb49caada..6655ad5a0 100644
--- a/projects/editor/src/app/components/properties-panel/model-properties-tab/input-groups/drop-list-properties.component.ts
+++ b/projects/editor/src/app/components/properties-panel/model-properties-tab/input-groups/drop-list-properties.component.ts
@@ -14,8 +14,7 @@ import { IDService } from 'editor/src/app/services/id.service';
 @Component({
   selector: 'aspect-drop-list-properties',
   template: `
-    <div *ngIf="combinedProperties.type === 'drop-list' ||
-                combinedProperties.type === 'drop-list-simple'"
+    <div *ngIf="combinedProperties.type === 'drop-list'"
                 fxLayout="column">
       <aspect-option-list-panel [title]="'preset'" [textFieldLabel]="'Neue Option'"
                                 [itemList]="$any(combinedProperties.value)"
@@ -52,6 +51,12 @@ import { IDService } from 'editor/src/app/services/id.service';
         </mat-select>
       </mat-form-field>
 
+      <mat-checkbox *ngIf="combinedProperties.isSortList !== undefined"
+                    [checked]="$any(combinedProperties.isSortList)"
+                    (change)="updateModel.emit({ property: 'isSortList', value: $event.checked })">
+        {{'propertiesPanel.isSortList' | translate }}
+      </mat-checkbox>
+
       <mat-checkbox *ngIf="combinedProperties.onlyOneItem !== undefined"
                     [checked]="$any(combinedProperties.onlyOneItem)"
                     (change)="updateModel.emit({ property: 'onlyOneItem', value: $event.checked })">
diff --git a/projects/editor/src/app/services/id.service.ts b/projects/editor/src/app/services/id.service.ts
index d96646ed7..35ded1c1b 100644
--- a/projects/editor/src/app/services/id.service.ts
+++ b/projects/editor/src/app/services/id.service.ts
@@ -28,7 +28,6 @@ export class IDService {
     'spell-correct': 0,
     'radio-group-images': 0,
     'drop-list': 0,
-    'drop-list-simple': 0,
     cloze: 0,
     frame: 0,
     'toggle-button': 0,
diff --git a/projects/editor/src/app/services/unit.service.ts b/projects/editor/src/app/services/unit.service.ts
index 10aae508d..8835e0340 100644
--- a/projects/editor/src/app/services/unit.service.ts
+++ b/projects/editor/src/app/services/unit.service.ts
@@ -11,7 +11,7 @@ import {
   CompoundElement,
   DragNDropValueObject, InputElement,
   InputElementValue, TextLabel, PlayerElement, PlayerProperties, PositionedUIElement,
-  UIElement, UIElementType, UIElementValue, Hotspot
+  UIElement, UIElementType, UIElementValue, Hotspot, PositionProperties
 } from 'common/models/elements/element';
 import { ClozeDocument, ClozeElement } from 'common/models/elements/compound-elements/cloze/cloze';
 import { LikertRowElement } from 'common/models/elements/compound-elements/likert/likert-row';
@@ -128,17 +128,17 @@ export class UnitService {
     }
 
     if (coordinates) {
-      newElement.position = UIElement.initPositionProps({
+      newElement.position = {
         ...(section.dynamicPositioning && { gridColumn: coordinates.x }),
         ...(section.dynamicPositioning && { gridRow: coordinates.y }),
         ...(!section.dynamicPositioning && { yPosition: coordinates.y }),
         ...(!section.dynamicPositioning && { yPosition: coordinates.y })
-      });
+      } as PositionProperties;
     }
     section.addElement(ElementFactory.createElement({
       ...newElement,
       id: this.idService.getAndRegisterNewID(newElement.type),
-      position: UIElement.initPositionProps(newElement.position)
+      position: { ...newElement.position } as PositionProperties
     }) as PositionedUIElement);
     this.veronaApiService.sendVoeDefinitionChangedNotification(this.unit);
   }
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 cf7df19a0..032c6659e 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
@@ -2,8 +2,7 @@ import { Injector } from '@angular/core';
 import { Node, mergeAttributes } from '@tiptap/core';
 import { AngularNodeViewRenderer } from 'ngx-tiptap';
 import { DropListNodeviewComponent } from './drop-list-nodeview.component';
-import { DropListSimpleElement }
-  from 'common/models/elements/compound-elements/cloze/cloze-child-elements/drop-list-simple';
+import { DropListElement } from 'common/models/elements/input-elements/drop-list';
 
 const DropListComponentExtension = (injector: Injector): Node => {
   return Node.create({
@@ -14,7 +13,13 @@ const DropListComponentExtension = (injector: Injector): Node => {
     addAttributes() {
       return {
         model: {
-          default: new DropListSimpleElement({ type: 'drop-list-simple', id: 'cloze-child-id-placeholder' })
+          default: new DropListElement({
+            type: 'drop-list',
+            id: 'cloze-child-id-placeholder',
+            width: 150,
+            height: 30,
+            onlyOneItem: true
+          })
         }
       };
     },
diff --git a/projects/editor/src/app/text-editor/angular-node-views/drop-list-nodeview.component.ts b/projects/editor/src/app/text-editor/angular-node-views/drop-list-nodeview.component.ts
index a2021cf06..ab50bfb7c 100644
--- a/projects/editor/src/app/text-editor/angular-node-views/drop-list-nodeview.component.ts
+++ b/projects/editor/src/app/text-editor/angular-node-views/drop-list-nodeview.component.ts
@@ -8,9 +8,9 @@ import { AngularNodeViewComponent } from 'ngx-tiptap';
          [style.vertical-align]="'middle'"
          [style.width.px]="node.attrs.model.width"
          [style.height.px]="node.attrs.model.height">
-      <aspect-drop-list-simple [elementModel]="node.attrs.model"
-                               [matTooltip]="'ID: ' + node.attrs.model.id">
-      </aspect-drop-list-simple>
+      <aspect-drop-list [elementModel]="node.attrs.model"
+                        [matTooltip]="'ID: ' + node.attrs.model.id">
+      </aspect-drop-list>
     </div>
   `
 })
diff --git a/projects/editor/src/assets/i18n/de.json b/projects/editor/src/assets/i18n/de.json
index 387202ddf..a9daae04c 100644
--- a/projects/editor/src/assets/i18n/de.json
+++ b/projects/editor/src/assets/i18n/de.json
@@ -184,7 +184,8 @@
     "hotspots": "Aktive Bereiche",
     "newHotspot": "Neuer Bereich",
     "hasDynamicRowCount": "Dynamische Zeilen",
-    "expectedCharactersCount": "Erwartete Zeichenanzahl"
+    "expectedCharactersCount": "Erwartete Zeichenanzahl",
+    "isSortList": "Sortierliste"
   },
   "hotspot": {
     "top": "Abstand von oben",
diff --git a/projects/player/src/app/services/element-model-element-code-mapping.service.ts b/projects/player/src/app/services/element-model-element-code-mapping.service.ts
index 8a49d63cf..c08a9f685 100644
--- a/projects/player/src/app/services/element-model-element-code-mapping.service.ts
+++ b/projects/player/src/app/services/element-model-element-code-mapping.service.ts
@@ -26,7 +26,6 @@ export class ElementModelElementCodeMappingService {
   : InputElementValue => {
     switch (elementModel.type) {
       case 'drop-list':
-      case 'drop-list-simple':
         return (elementCodeValue !== undefined) ?
           (elementCodeValue as string[]).map(id => this.getDragNDropValueObjectById(id)) as DragNDropValueObject[] :
           (elementModel as InputElement).value;
@@ -69,7 +68,6 @@ export class ElementModelElementCodeMappingService {
   mapToElementCodeValue = (elementModelValue: InputElementValue, elementType: UIElementType): InputElementValue => {
     switch (elementType) {
       case 'drop-list':
-      case 'drop-list-simple':
         return (elementModelValue as DragNDropValueObject[]).map(object => object.id);
       case 'hotspot-image':
         return (elementModelValue as Hotspot[]).map(hotspot => hotspot.value);
-- 
GitLab