From 585c42247d8976daa9d9e9b15c589d407fb5764f Mon Sep 17 00:00:00 2001
From: jojohoch <joachim.hoch@iqb.hu-berlin.de>
Date: Thu, 11 Nov 2021 13:01:34 +0100
Subject: [PATCH] [player] Move code from ElementContainerComponent to
 MarkingService

The MarkingService now takes care of the selection and its validation.
The text component sends its change via elementValueChanged.
---
 .../element-components/text.component.ts      |  2 ++
 .../element-container.component.ts            | 32 ++---------------
 .../src/app/services/marking.service.ts       | 34 ++++++++++++++++++-
 3 files changed, 38 insertions(+), 30 deletions(-)

diff --git a/projects/common/element-components/text.component.ts b/projects/common/element-components/text.component.ts
index c7b229a88..e0484ea4f 100644
--- a/projects/common/element-components/text.component.ts
+++ b/projects/common/element-components/text.component.ts
@@ -3,6 +3,7 @@ import {
 } from '@angular/core';
 import { ElementComponent } from '../element-component.directive';
 import { TextElement } from '../models/text-element';
+import { ValueChangeElement } from '../models/uI-element';
 
 @Component({
   selector: 'app-text',
@@ -62,6 +63,7 @@ import { TextElement } from '../models/text-element';
 })
 export class TextComponent extends ElementComponent {
   elementModel!: TextElement;
+  @Output() elementValueChanged = new EventEmitter<ValueChangeElement>();
   @Output() startSelection = new EventEmitter<MouseEvent>();
   @Output() applySelection = new EventEmitter <{
     mode: 'mark' | 'underline' | 'delete',
diff --git a/projects/player/src/app/components/element-container/element-container.component.ts b/projects/player/src/app/components/element-container/element-container.component.ts
index 4d9a7a746..76a10e817 100644
--- a/projects/player/src/app/components/element-container/element-container.component.ts
+++ b/projects/player/src/app/components/element-container/element-container.component.ts
@@ -30,6 +30,7 @@ import { ImageElement } from '../../../../../common/models/image-element';
 import { VeronaPostService } from '../../services/verona-post.service';
 import { MediaPlayerElementComponent } from '../../../../../common/media-player-element-component.directive';
 import { MediaPlayerService } from '../../services/media-player.service';
+import { TextComponent } from '../../../../../common/element-components/text.component';
 
 @Component({
   selector: 'app-element-container',
@@ -122,7 +123,8 @@ export class ElementContainerComponent implements OnInit {
         .pipe(takeUntil(this.ngUnsubscribe))
         .subscribe((selection:
         { mode: 'mark' | 'underline' | 'delete', color: string; element: HTMLElement; clear: boolean }) => {
-          this.applySelection(selection.mode, selection.color, selection.element);
+          this.markingService
+            .applySelection(selection.mode, selection.color, selection.element, elementComponent as TextComponent);
         });
     }
 
@@ -251,34 +253,6 @@ export class ElementContainerComponent implements OnInit {
       });
   }
 
-  private applySelection(mode: 'mark' | 'underline' | 'delete', color: string, element: HTMLElement): void {
-    const selection = window.getSelection();
-    if (selection && selection.rangeCount > 0) {
-      const range = selection.getRangeAt(0);
-      if (this.isDescendantOf(range.startContainer, element) &&
-        this.isDescendantOf(range.endContainer, element)) {
-        const markMode = mode === 'mark' ? 'marked' : 'underlined';
-        this.markingService.applySelection(range, selection, mode === 'delete', color, markMode);
-        this.unitStateService.changeElementValue({
-          id: this.elementModel.id,
-          values: [this.elementModel.text as string, element.innerHTML]
-        });
-        this.elementModel.text = element.innerHTML;
-      }
-      selection.removeAllRanges();
-    } // nothing to do!
-  }
-
-  private isDescendantOf(node: Node | null, element: HTMLElement): boolean {
-    if (!node || node === document) {
-      return false;
-    }
-    if (node.parentElement === element) {
-      return true;
-    }
-    return this.isDescendantOf(node.parentNode, element);
-  }
-
   ngOnDestroy(): void {
     this.ngUnsubscribe.next();
     this.ngUnsubscribe.complete();
diff --git a/projects/player/src/app/services/marking.service.ts b/projects/player/src/app/services/marking.service.ts
index bd75193e6..1bdeb46b8 100644
--- a/projects/player/src/app/services/marking.service.ts
+++ b/projects/player/src/app/services/marking.service.ts
@@ -1,4 +1,5 @@
 import { Injectable } from '@angular/core';
+import { TextComponent } from '../../../../common/element-components/text.component';
 
 @Injectable({
   providedIn: 'root'
@@ -7,7 +8,38 @@ export class MarkingService {
   private static readonly MARKING_TAG = 'MARKED';
   private static readonly UNDERLINE_TAG = 'UNDERLINED';
 
-  applySelection(
+  applySelection(mode: 'mark' | 'underline' | 'delete',
+                 color: string,
+                 element: HTMLElement,
+                 textComponent: TextComponent): void {
+    const selection = window.getSelection();
+    if (selection && selection.rangeCount > 0) {
+      const range = selection.getRangeAt(0);
+      if (this.isDescendantOf(range.startContainer, element) &&
+        this.isDescendantOf(range.endContainer, element)) {
+        const markMode = mode === 'mark' ? 'marked' : 'underlined';
+        this.applyRange(range, selection, mode === 'delete', color, markMode);
+        textComponent.elementValueChanged.emit({
+          id: textComponent.elementModel.id,
+          values: [textComponent.elementModel.text as string, element.innerHTML]
+        });
+        textComponent.elementModel.text = element.innerHTML;
+      }
+      selection.removeAllRanges();
+    } // nothing to do!
+  }
+
+  private isDescendantOf(node: Node | null, element: HTMLElement): boolean {
+    if (!node || node === document) {
+      return false;
+    }
+    if (node.parentElement === element) {
+      return true;
+    }
+    return this.isDescendantOf(node.parentNode, element);
+  }
+
+  private applyRange(
     range: Range, selection: Selection, clear: boolean, color: string, markMode: 'marked' | 'underlined'
   ): void {
     if (range.startContainer === range.endContainer) {
-- 
GitLab