Newer
Older
import { ApplicationRef, createComponent, Renderer2 } from '@angular/core';
import { TextComponent } from 'common/components/text/text.component';
import { Markable, MarkablesContainer } from 'player/src/app/models/markable.interface';
import {
MarkablesContainerComponent
} from 'player/src/app/components/elements/markables-container/markables-container.component';
export class MarkableSupport {
private renderer: Renderer2;
private applicationRef: ApplicationRef;
markables: Markable[] = [];
static wordsWithWhitespace: RegExp = /(\s*\S+\s*)|(s+\S*\s*)|(s*\S*\s+)/g;
static prefix: RegExp = /\W+(?=\w+)/u;
static word: RegExp = /\w+/u;
static suffix: RegExp = /\W+$/u;
renderer: Renderer2,
applicationRef: ApplicationRef
) {
this.renderer = renderer;
this.applicationRef = applicationRef;
}
createMarkables(savedMarks: string[], elementComponent: TextComponent): void {
const nodes = MarkableSupport.findNodes(elementComponent.textContainerRef.nativeElement.childNodes);
const markablesContainers = MarkableSupport.getMarkablesContainers(nodes, savedMarks);
this.markables = markablesContainers
.flatMap((markablesContainer: MarkablesContainer) => markablesContainer.markables);
this.createComponents(markablesContainers, elementComponent);
private createComponents(markablesContainers: MarkablesContainer[], elementComponent: TextComponent): void {
markablesContainers.forEach((markablesContainer: MarkablesContainer) => {
const node = markablesContainer.node;
const markableContainerElement = this.renderer.createElement('markable-container');
node.parentNode?.replaceChild(markableContainerElement, node);
const environmentInjector = this.applicationRef.injector;
const componentRef = createComponent(MarkablesContainerComponent, {
environmentInjector,
hostElement: markableContainerElement
});
componentRef.instance.markables = markablesContainer.markables;
componentRef.instance.selectedColor = elementComponent.selectedColor;
componentRef.instance.markablesChange.subscribe(() => {
elementComponent.elementValueChanged.emit(
value: this.markables
this.applicationRef.attachView(componentRef.hostView);
});
}
private static getMarkablesContainers(nodes: Node[], savedMarks: string[]): MarkablesContainer[] {
const markablesContainers: MarkablesContainer[] = [];
let wordsCount = 0;
nodes.forEach((node: Node) => {
const currentNodes = MarkableSupport.getMarkablesContainer(node, wordsCount, savedMarks);
wordsCount += currentNodes.markables.length;
markablesContainers.push(currentNodes);
});
return markablesContainers;
}
private static getMarkablesContainer(node: Node, wordsCount: number, savedMarks: string[]): MarkablesContainer {
markables: MarkableSupport.getMarkables(node.textContent || '', wordsCount, savedMarks)
private static getMarkables(text: string, startIndex: number, savedMarks: string[]): Markable[] {
const wordsWithWhitespace = text?.match(MarkableSupport.wordsWithWhitespace);
wordsWithWhitespace?.forEach((wordWithWhitespace: string, index: number) => {
const prefix = wordWithWhitespace.match(MarkableSupport.prefix);
const word = wordWithWhitespace.match(MarkableSupport.word);
const suffix = wordWithWhitespace.match(MarkableSupport.suffix);
const color = MarkableSupport.getColorValueById(id, savedMarks);
prefix: prefix ? prefix[0] : '',
word: word ? word[0] : '',
isActive: !!(word && word[0].length),
private static findNodes(childList: Node[] | NodeListOf<ChildNode>): Node[] {
const nodes: Node[] = [];
childList.forEach((node: Node) => {
if (node.nodeType === Node.TEXT_NODE && !nodes.includes(node) && node.textContent) {
nodes.push(node);
}
if (node.nodeType === Node.ELEMENT_NODE) {
if (node.childNodes.length) {
nodes.push(...MarkableSupport.findNodes(node.childNodes));
private static getColorValueById(id: number, savedMarks: string[]): string | null {
const savedMarkById = savedMarks.map(savedMark => savedMark.split('-'))
.find(mark => mark[0] === id.toString());
return savedMarkById ? savedMarkById[2] : null;