From 2f2f090372e3613fa95a88c1d7be4eb9caed10e2 Mon Sep 17 00:00:00 2001 From: jojohoch <joachim.hoch@iqb.hu-berlin.de> Date: Thu, 6 Jan 2022 15:37:36 +0100 Subject: [PATCH] [player] Improve handling of start selection - Check if the selection refers to the content of the text component --- .../common/ui-elements/text/text.component.ts | 2 +- .../element-container.component.ts | 22 ++++++++++++++----- .../src/app/services/marking.service.ts | 20 ++++++++--------- .../src/app/services/native-event.service.ts | 10 +++++++++ 4 files changed, 38 insertions(+), 16 deletions(-) diff --git a/projects/common/ui-elements/text/text.component.ts b/projects/common/ui-elements/text/text.component.ts index be5b2d981..a682eb2d7 100644 --- a/projects/common/ui-elements/text/text.component.ts +++ b/projects/common/ui-elements/text/text.component.ts @@ -29,7 +29,7 @@ import { ValueChangeElement } from '../../models/uI-element'; [style.font-weight]="elementModel.fontProps.bold ? 'bold' : ''" [style.font-style]="elementModel.fontProps.italic ? 'italic' : ''" [style.text-decoration]="elementModel.fontProps.underline ? 'underline' : ''" - (mouseup)="startSelection.emit($event)" + (mousedown)="startSelection.emit($event)" [innerHTML]="elementModel.text | safeResourceHTML"> </div> </div> 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 9dbe5b3da..50de60e53 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 @@ -4,7 +4,7 @@ import { import { FormBuilder, FormControl, FormGroup, ValidatorFn } from '@angular/forms'; -import { takeUntil } from 'rxjs/operators'; +import { first, takeUntil } from 'rxjs/operators'; import { Subject } from 'rxjs'; import { InputElement, UIElement, ValueChangeElement @@ -28,6 +28,7 @@ import { MarkingService } from '../../services/marking.service'; import { MediaPlayerService } from '../../services/media-player.service'; import { UnitStateElementMapperService } from '../../services/unit-state-element-mapper.service'; import { VeronaPostService } from '../../services/verona-post.service'; +import { NativeEventService } from '../../services/native-event.service'; @Component({ selector: 'app-element-container', @@ -54,6 +55,7 @@ export class ElementContainerComponent implements OnInit { private formService: FormService, private unitStateService: UnitStateService, private formBuilder: FormBuilder, + private nativeEventService: NativeEventService, private veronaPostService: VeronaPostService, private mediaPlayerService: MediaPlayerService, private unitStateElementMapperService: UnitStateElementMapperService, @@ -173,14 +175,24 @@ export class ElementContainerComponent implements OnInit { elementComponent.startSelection .pipe(takeUntil(this.ngUnsubscribe)) .subscribe((mouseEvent: MouseEvent) => { - const selection = window.getSelection(); - if (mouseEvent.ctrlKey && selection?.rangeCount) { - selection.removeAllRanges(); - } + this.nativeEventService.mouseUp + .pipe(takeUntil(this.ngUnsubscribe), first()) + .subscribe(() => this.startSelection(mouseEvent, elementComponent)); }); } } + private startSelection(mouseEvent: MouseEvent, elementComponent: TextComponent) { + const selection = window.getSelection(); + if (selection) { + if (!this.markingService.isDescendantOf(selection.anchorNode, elementComponent.containerDiv.nativeElement) || + !this.markingService.isDescendantOf(selection.focusNode, elementComponent.containerDiv.nativeElement) || + (mouseEvent.ctrlKey && selection.rangeCount)) { + selection.removeAllRanges(); + } + } + } + private subscribeApplySelection(elementComponent: TextComponent): void { if (elementComponent.applySelection) { elementComponent.applySelection diff --git a/projects/player/src/app/services/marking.service.ts b/projects/player/src/app/services/marking.service.ts index ee88cf0ec..6bcdcfa54 100644 --- a/projects/player/src/app/services/marking.service.ts +++ b/projects/player/src/app/services/marking.service.ts @@ -77,6 +77,16 @@ export class MarkingService { return newHtmlText; } + 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 getMarkingColor = (tag: string): string => { const colors = tag.match(/\d{1,3}, \d{1,3}, \d{1,3}/); return (colors) ? this.rgbToHex(colors[0].split(',').map(value => Number(value))) : 'none'; @@ -89,16 +99,6 @@ export class MarkingService { } style="background-color: rgb(${rgb[0]}, ${rgb[1]}, ${rgb[2]});">`; } - 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 ): void { diff --git a/projects/player/src/app/services/native-event.service.ts b/projects/player/src/app/services/native-event.service.ts index 4561cb172..b3c456ca9 100644 --- a/projects/player/src/app/services/native-event.service.ts +++ b/projects/player/src/app/services/native-event.service.ts @@ -10,6 +10,7 @@ import { mergeMap } from 'rxjs/operators'; }) export class NativeEventService { private _focus = new Subject<boolean>(); + private _mouseUp = new Subject<Event>(); constructor(@Inject(DOCUMENT) private document: Document) { from(['blur', 'focus']) @@ -19,9 +20,18 @@ export class NativeEventService { .subscribe( () => this._focus.next(document.hasFocus())// Do something with the event here ); + + fromEvent(window, 'mouseup') + .subscribe((mouseEvent: Event) => { + this._mouseUp.next(mouseEvent); + }); } get focus(): Observable<boolean> { return this._focus.asObservable(); } + + get mouseUp(): Observable<Event> { + return this._mouseUp.asObservable(); + } } -- GitLab