Skip to content

The mergeClientRects resolution of the block-contains & block-is-contained edge case #189

@oleksandr-danylchenko

Description

@oleksandr-danylchenko

TL;DR;

When the content contains elements with the vertical-align style - the mergeClientRects can unexpectedly preserve selection only over it, ignoring everything before.

Interactive playground

Skip to the question

App:

selection_dismissed_bug.mp4

@recogito/text-annotator sandbox:

selection_bug.mp4

Issue

I tracked down that the "dismissal" of the content before the "super" element happens in the mergeClientRects function.

It establishes the block-is-contained relation between the "super" element rect and the rects on the left:

Rects Relation
Image Image

} else if (a.top >= b.top && a.bottom <= b.bottom) {
if (a.left >= b.left && a.right <= b.right) {
return 'block-is-contained';
}

After, that the merging code picks the rect with the smaller width:

Image

So the whole left part rect gets replaced with the "super" element rect!

} else if (relation === 'block-contains' || relation === 'block-is-contained') {
// Block containment - keep the element with smaller width
if (rectA.width < rectB.width) {
next = next.map(r => r === rectB ? rectA : r);
}
wasMerged = true;
break;
}

Reproduction

The issue can be reproduced in the @recogito/text-annotator sandbox (Interactive playground):

<p>In 2020, the U.S. unemployment rate rose from a longtime record low of 3.5 percent in February to 14.7 percent in April. This represents a loss of 30 million jobs or about 18 percent of the labor force prior to the COVID-19 
<span class="footnote-ref-tail">pandemic.
	<a class="footnote-ref" name="footnote-ref-1" href="#footnote-1">1</a>
</span> To put this total in context
</p>
.footnote-ref-tail {
  white-space: nowrap;
}

.footnote-ref {
  display: inline-block;
  min-width: 20px;
  background-clip: content-box;
  vertical-align: super;
  color: #5f01df;
  font-size: 14px;
  font-style: normal;
  font-weight: bold;
  line-height: 17px;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  position: relative;
  top: 5px;
}

.footnote-ref::before {
  content: '[';
}
.footnote-ref::after {
  content: ']';
}

Question

Should we consider using the wider rect instead of the smaller one as a replacement target? That way we'll pick the container rect instead of the one that's being contained. It sounds like a more sensible approach to me 🤔

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions