From e80b30915c28d2d25171de2b99df8061b722e1e7 Mon Sep 17 00:00:00 2001
From: jojohoch <joachim.hoch@iqb.hu-berlin.de>
Date: Thu, 8 Dec 2022 12:34:49 +0100
Subject: [PATCH] [player] Fix deletion of text when removing markers on the
 text element

---
 docs/release-notes-player.md                  |  5 ++
 .../src/app/services/text-marking.service.ts  | 55 ++++++++-----------
 2 files changed, 28 insertions(+), 32 deletions(-)

diff --git a/docs/release-notes-player.md b/docs/release-notes-player.md
index bd1b353c5..f65f32d96 100644
--- a/docs/release-notes-player.md
+++ b/docs/release-notes-player.md
@@ -5,6 +5,11 @@ Player
 - Darstellung und Verhalten der Warnmeldung von Formelelementen
   verhalten sich analog zu anderen Elementen
 
+### Fehlerbehebungen
+- Behebt das versehentliche Löschen von Text beim Entfernen von 
+  Markierungen aus Textelementen (im Firefox-Browser)  
+
+
 ## 1.28.0
 
 ### Neue Funktionen
diff --git a/projects/player/src/app/services/text-marking.service.ts b/projects/player/src/app/services/text-marking.service.ts
index e1dd89d2a..f1a66b781 100644
--- a/projects/player/src/app/services/text-marking.service.ts
+++ b/projects/player/src/app/services/text-marking.service.ts
@@ -109,52 +109,43 @@ export class TextMarkingService {
   private static applyRange(
     range: Range, selection: Selection, clear: boolean, color: string
   ): void {
-    if (range.startContainer === range.endContainer) {
+    const nodes: Node[] = TextMarkingService.getSelectedNodes(range, selection);
+    if ((range.startContainer === range.endContainer) && range.startContainer.nodeType === Node.TEXT_NODE) {
       if (clear) {
-        TextMarkingService.clearMarkingFromNode(range);
+        if (range.startContainer.nodeType === Node.TEXT_NODE) {
+          TextMarkingService.clearMarkingFromNode(range);
+        } else {
+          TextMarkingService.clearNodes(nodes, range);
+        }
       } else {
         TextMarkingService.markNode(range, color);
       }
+    } else if (clear) {
+      TextMarkingService.clearNodes(nodes, range);
     } else {
-      const nodes: Node[] = TextMarkingService.getSelectedNodes(range, selection);
-      if (clear) {
-        TextMarkingService.clearNodes(nodes, range);
-      } else {
-        TextMarkingService.markNodes(nodes, range, color);
-      }
+      TextMarkingService.markNodes(nodes, range, color);
     }
   }
 
   private static getSelectedNodes = (range: Range, selection: Selection): Node[] => {
+    let startContainerNodes: Node[] = [];
+    const endContainerNodes: Node[] = [];
     const nodes: Node[] = TextMarkingService.findNodes(range.commonAncestorContainer.childNodes, selection);
-    // When the user finishes selecting between paragraphs and the selection happens from
-    // back to front, Firefox does not consider the start container as a selected child node.
-    // Therefore, it is added to the list of selected nodes at the beginning.
+    // The range is structured differently in FF and Chrome.
+    // With the same selection startcontainer and endcontainer differ.
+    // Under certain conditions, startcontainer and endcontainer are not present
+    // in the list of child nodes in FF and must therefore be added here
     if (!nodes.includes(range.startContainer)) {
-      nodes.unshift(range.startContainer);
-    }
-    // When the user finishes selecting between paragraphs the browser does not consider the end container
-    // as a selected child node. Therefore, it is added to the list of selected nodes at the end.
-    if (range.endOffset === 0) {
-      const endContainer = TextMarkingService.getEndContainer(range.endContainer);
-      if (endContainer && !nodes.includes(endContainer)) {
-        nodes.push(endContainer);
-      }
-    }
-    return nodes;
-  };
-
-  private static getEndContainer = (endContainer: Node): Node | null => {
-    if (endContainer.nodeType === Node.ELEMENT_NODE) {
-      if (endContainer.childNodes.length) {
-        return (endContainer.childNodes[0]);
+      if (range.startContainer.nodeType === Node.TEXT_NODE) {
+        startContainerNodes.push(range.startContainer);
+      } else {
+        startContainerNodes = TextMarkingService.findNodes(range.startContainer.childNodes, selection);
       }
-      return endContainer;
     }
-    if (endContainer.nodeType === Node.TEXT_NODE) {
-      return endContainer;
+    if (range.endOffset === 0 && !nodes.includes(range.endContainer) && !range.endContainer.childNodes.length) {
+      endContainerNodes.push(range.endContainer);
     }
-    return null;
+    return [...startContainerNodes, ...nodes, ...endContainerNodes];
   };
 
   private static clearMarkingFromNode(range: Range): void {
-- 
GitLab