Page MenuHomePhabricator

VisualEditor: ve.ce.Surface.getSelectionRect() throws errors in Opera
Closed, ResolvedPublic

Description

ve.ce.Surface.getSelectionRect() throws errors in Opera. I think this is the root cause of bug 37861 and likely various other issues.

It seems that rangySel.get{Start,End}DocumentPos consistently fails in Opera, because nativeRange.getClientRects() inside of the private createClientBoundaryPosGetter() function returns an empty collection. This causes the "Cannot get position for range ..." error to be thrown.

I'm still investigating the why, I'm just putting this here. Changing getSelectionRect() to just always return some static value seems to work (or at least not fail miserably anymore).


Version: unspecified
Severity: normal

Details

Reference
bz47772

Event Timeline

So, what happens is that in Opera, for zero-length ranges (ie, just a caret, no selection):

  • .getSelection().getRangeAt(0) returns a Range
  • but then .getClientRects() returns an empty ClientRectList
  • and .getBoundingClientRect() returns a rectangle with all values being 0

This seems to work:

range = document.getSelection().getRangeAt(0)

Range

span = document.createElement('span')

<span/>

range.getClientRects()

ClientRectList []

range.surroundContents(span)

undefined

$(span).offset()

{ left: 352, top: 1025 }

Now we just have to substract window.scrollY from the 'top' value and remove the <span> from the DOM again. (And don't call .getClientRects() on that Range again, as it returns a completely bonkers huge list of values.)

Related URL: https://gerrit.wikimedia.org/r/61190 (Gerrit Change I4bad882d1d6fb83bcdcfd0de3bfc9af52960c2ff)

Hmm, apparently this also happens for non-empty selections in some cases. We're gonna need a larger workaround...

The fix is merged now. Marking as fixed.