doccano/v-annotator

Annotate across line breaks on FF, if there are other elements in between

leonardlin opened this issue ยท 0 comments

See comment thread here
doccano/doccano#1863

on Firefox
labeling across lines breaks when there is another element in between:
image

  • In the example I try to label: "very loud.\nThe ๐Ÿณ๏ธโ€๐ŸŒˆ car"
  • This does not work on Firefox but does work in Chrome.

As comment thread suggests it happens in the method: TextSelectionHandler.getRange()

Do you think this method works before I create a PR?

private getRange(): [number, number] {
    const selection = window.getSelection();
    // get elements.
    const startElement = selection!.anchorNode!.parentNode;
    const endElement = selection!.focusNode!.parentNode;

    // Get TextLine objects.
    // This depends on BaseText.vue component.
    // See the component in detail.
    const startLine = (
      startElement as unknown as { annotatorElement: TextLine }
    ).annotatorElement;
    const endLine = (endElement as unknown as { annotatorElement: TextLine })
      .annotatorElement;

    let startOffset = 0;
    let endOffset = 0;
    if(startLine === undefined) {
      // alternative method

      const altStartElement = (startElement?.firstChild as SVGTextElement);
      const altStartLine = (
        altStartElement as unknown as { annotatorElement: TextLine }
      ).annotatorElement;
      const altStartLineText = altStartElement.innerHTML;

      const selectionTexts = selection!.toString().split(/\r\n|\r|\n/);
      const altSelectionAnchorStart = altStartLineText.lastIndexOf(selectionTexts[0]);
      
      startOffset = altStartLine.startOffset + altSelectionAnchorStart;
      endOffset = endLine.startOffset + selection!.focusOffset;
    } else {
      // get offsets.
      startOffset = startLine.startOffset + selection!.anchorOffset;
      endOffset = endLine.startOffset + selection!.focusOffset;
    }

    selection?.removeAllRanges();
    if (startOffset > endOffset) {
      return [endOffset, startOffset];
    } else {
      return [startOffset, endOffset];
    }
  }