Skip to content

Conversation

@oleksandr-danylchenko
Copy link
Contributor

@oleksandr-danylchenko oleksandr-danylchenko commented Jul 24, 2024

Issue

To position the popup, we used the range.getBoundingClientRect/getClientRects methods, which are performant and correct in cases when the annotatable DOM is stable and static. However, when the DOM elements captured within the range mutate - it collapses and loses its dimensions. That leads to losing the anchoring position for the popup or any other element that depends on that range.

Changes Made

As we can't rely on the mutable range instance, instead we can use the cached rects persisted in the spatialTree! They are resilient to the underlying DOM mutations and can be manually recalculated on demand. Also, during the recalculation, the ranges can be automatically revived:

const toItems = (target: TextAnnotationTarget, offset: DOMRect): IndexedHighlightRect[] => {
const rects = target.selector.flatMap(s => {
const revivedRange = isRevived([s]) ? s.range : reviveSelector(s, container).range;
return isFirefox ?
getClientRectsPonyfill(revivedRange) :
Array.from(revivedRange.getClientRects());
});

Real-life example

I faced that challenge while integrating the annotator alongside the Speechstream library. The latter highlights the text word-by-word and announces it to the users, working as an a11y/convenience tool. However, its highlighting is implemented in a pretty disruptive way, where the announced paragraphs are constantly being mutated!

Step View
Before announcement image
After the announcement starts (The highlighted sentence replaces the paragraph) image
Content is placed back (The annotation range reference is lost, it became collapsed) image
Further steps where it goes through the sentences word by word image image ...

Because of the mutation, the range persisted by the annotation was constantly getting collapsed, making it impossible to position related elements by it:

Text replacement function Range collapsing
image image

# Conflicts:
#	packages/text-annotator/src/utils/index.ts
# Conflicts:
#	packages/text-annotator/src/utils/mergeClientRects.ts
# Conflicts:
#	packages/text-annotator/src/state/spatialTree.ts
# Conflicts:
#	packages/text-annotator-react/src/TextAnnotatorPopup.tsx
#	packages/text-annotator/src/utils/index.ts
# Conflicts:
#	packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx
# Conflicts:
#	packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx
#	packages/text-annotator/src/utils/index.ts
# Conflicts:
#	packages/text-annotator-react/src/TextAnnotatorPopup/TextAnnotatorPopup.tsx
# Conflicts:
#	packages/text-annotator-react/src/TextAnnotationPopup/TextAnnotationPopup.tsx
@rsimon rsimon merged commit 20c4d20 into recogito:main Nov 21, 2024
@rsimon
Copy link
Member

rsimon commented Nov 21, 2024

Finally got a chance to review & test this, because we ran into a different but connected problem ourselves. This is great, many thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants