1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-23 07:22:55 +02:00

fix: account for container padding in scrollToSelection (#1462)

This commit is contained in:
Evan Henley
2017-12-11 12:35:02 -06:00
committed by Ian Storm Taylor
parent fafa607e54
commit a3d91b6daa

View File

@@ -65,8 +65,9 @@ function scrollToSelection(selection) {
const isWindow = scroller == window.document.body || scroller == window.document.documentElement const isWindow = scroller == window.document.body || scroller == window.document.documentElement
const backward = isBackward(selection) const backward = isBackward(selection)
const range = selection.getRangeAt(0) const range = selection.getRangeAt(0).cloneRange()
let selectionRect = range.getBoundingClientRect() range.collapse(backward)
let cursorRect = range.getBoundingClientRect()
// COMPAT: range.getBoundingClientRect() returns 0s in Safari when range is // COMPAT: range.getBoundingClientRect() returns 0s in Safari when range is
// collapsed. Expanding the range by 1 is a relatively effective workaround // collapsed. Expanding the range by 1 is a relatively effective workaround
@@ -74,18 +75,18 @@ function scrollToSelection(selection) {
// https://bugs.webkit.org/show_bug.cgi?id=138949 // https://bugs.webkit.org/show_bug.cgi?id=138949
// https://bugs.chromium.org/p/chromium/issues/detail?id=435438 // https://bugs.chromium.org/p/chromium/issues/detail?id=435438
if (IS_SAFARI) { if (IS_SAFARI) {
if (range.collapsed && selectionRect.top == 0 && selectionRect.height == 0) { if (range.collapsed && cursorRect.top == 0 && cursorRect.height == 0) {
if (range.startOffset == 0) { if (range.startOffset == 0) {
range.setEnd(range.endContainer, 1) range.setEnd(range.endContainer, 1)
} else { } else {
range.setStart(range.startContainer, range.startOffset - 1) range.setStart(range.startContainer, range.startOffset - 1)
} }
selectionRect = range.getBoundingClientRect() cursorRect = range.getBoundingClientRect()
if (selectionRect.top == 0 && selectionRect.height == 0) { if (cursorRect.top == 0 && cursorRect.height == 0) {
if (range.getClientRects().length) { if (range.getClientRects().length) {
selectionRect = range.getClientRects()[0] cursorRect = range.getClientRects()[0]
} }
} }
} }
@@ -99,6 +100,10 @@ function scrollToSelection(selection) {
let scrollerLeft = 0 let scrollerLeft = 0
let scrollerBordersY = 0 let scrollerBordersY = 0
let scrollerBordersX = 0 let scrollerBordersX = 0
let scrollerPaddingTop = 0
let scrollerPaddingBottom = 0
let scrollerPaddingLeft = 0
let scrollerPaddingRight = 0
if (isWindow) { if (isWindow) {
const { innerWidth, innerHeight, pageYOffset, pageXOffset } = window const { innerWidth, innerHeight, pageYOffset, pageXOffset } = window
@@ -113,6 +118,10 @@ function scrollToSelection(selection) {
borderBottomWidth, borderBottomWidth,
borderLeftWidth, borderLeftWidth,
borderRightWidth, borderRightWidth,
paddingTop,
paddingBottom,
paddingLeft,
paddingRight,
} = window.getComputedStyle(scroller) } = window.getComputedStyle(scroller)
const scrollerRect = scroller.getBoundingClientRect() const scrollerRect = scroller.getBoundingClientRect()
@@ -122,33 +131,34 @@ function scrollToSelection(selection) {
scrollerLeft = scrollerRect.left + parseInt(borderLeftWidth, 10) scrollerLeft = scrollerRect.left + parseInt(borderLeftWidth, 10)
scrollerBordersY = parseInt(borderTopWidth, 10) + parseInt(borderBottomWidth, 10) scrollerBordersY = parseInt(borderTopWidth, 10) + parseInt(borderBottomWidth, 10)
scrollerBordersX = parseInt(borderLeftWidth, 10) + parseInt(borderRightWidth, 10) scrollerBordersX = parseInt(borderLeftWidth, 10) + parseInt(borderRightWidth, 10)
scrollerPaddingTop = parseInt(paddingTop, 10)
scrollerPaddingBottom = parseInt(paddingBottom, 10)
scrollerPaddingLeft = parseInt(paddingLeft, 10)
scrollerPaddingRight = parseInt(paddingRight, 10)
yOffset = scrollTop yOffset = scrollTop
xOffset = scrollLeft xOffset = scrollLeft
} }
const selectionFocusTop = backward ? selectionRect.top : selectionRect.bottom const cursorTop = cursorRect.top + yOffset - scrollerTop
const selectionTop = selectionFocusTop + yOffset - scrollerTop const cursorLeft = cursorRect.left + xOffset - scrollerLeft
const selectionFocusLeft = backward ? selectionRect.left : selectionRect.right
const selectionLeft = selectionFocusLeft + xOffset - scrollerLeft
let x = xOffset let x = xOffset
let y = yOffset let y = yOffset
if (selectionLeft < xOffset) { if (cursorLeft < xOffset) {
// selection to the left of viewport // selection to the left of viewport
x = selectionLeft x = cursorLeft - scrollerPaddingLeft
} else if (selectionLeft + selectionRect.width + scrollerBordersX > xOffset + width) { } else if (cursorLeft + cursorRect.width + scrollerBordersX > xOffset + width) {
// selection to the right of viewport // selection to the right of viewport
x = selectionLeft + scrollerBordersX - width x = cursorLeft + scrollerBordersX + scrollerPaddingRight - width
} }
if (selectionTop < yOffset) { if (cursorTop < yOffset) {
// selection above viewport // selection above viewport
y = selectionTop y = cursorTop - scrollerPaddingTop
} else if (selectionTop + selectionRect.height + scrollerBordersY > yOffset + height) { } else if (cursorTop + cursorRect.height + scrollerBordersY > yOffset + height) {
// selection below viewport // selection below viewport
y = selectionTop + scrollerBordersY + selectionRect.height - height y = cursorTop + scrollerBordersY + scrollerPaddingBottom + cursorRect.height - height
} }