1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-31 10:51:44 +02:00

Fix jumpy scroll behaviour (#607)

* Fix jumpy scroll behaviour

I'm not sure if this is the best fix for the issue (I would have liked it to allow the browser to deal with moving the cursor into view.) but for now I think this is better than what it was before. I tried to imitate what chrome was doing when the cursor was out of view. (Except when it was partially in view but I decided to just keep it simple) 

This basically checks the cursor's position and if it isn't in view it'll move the cursor into the middle of the view. 

Fixes #279
Fixes #589

* Subtract Height
This commit is contained in:
Kenneth Truong
2017-02-23 15:02:10 -08:00
committed by Ian Storm Taylor
parent c0daa27500
commit 92194f13e1

View File

@@ -1,67 +1,58 @@
/**
* Copied from `element-scroll-to`, but edited to account for `window` being
* inside of iframes.
*
* https://github.com/webmodules/element-scroll-to
* Helps scroll the cursor into the middle of view if it isn't in view
*/
import getWindow from 'get-window'
function scrollWrapperElements(element, options) {
let window = getWindow(element)
let elementRect = element.getBoundingClientRect()
let wrapper = element.parentNode
while (wrapper != window.document.body) {
let wrapperRect = wrapper.getBoundingClientRect()
let margin = options.margin
let deltaX = 0
let deltaY = 0
if (elementRect.top < wrapperRect.top + margin) {
deltaY = elementRect.top - wrapperRect.top - margin
} else if (elementRect.bottom > wrapperRect.bottom - margin) {
deltaY = elementRect.bottom - wrapperRect.bottom + margin
}
if (elementRect.left < wrapperRect.left + margin) {
deltaX = elementRect.left - wrapperRect.left - margin
} else if (elementRect.right > wrapperRect.right - margin) {
deltaX = elementRect.right - wrapperRect.right + margin
}
wrapper.scrollTop += deltaY
wrapper.scrollLeft += deltaX
wrapper = wrapper.parentNode
}
return elementRect
}
function scrollWindow(element, options, elementRect) {
let window = getWindow(element)
let margin = options.margin
function scrollWindow(window, cursorTop, cursorLeft, cursorHeight) {
let deltaX = 0
let deltaY = 0
let cursorBottom = cursorTop + cursorHeight
if (elementRect.top < 0 + margin) {
deltaY = elementRect.top - margin
} else if (elementRect.bottom > window.innerHeight - margin) {
deltaY = elementRect.bottom - window.innerHeight + margin
if (cursorTop < 0 || cursorBottom > window.innerHeight) {
deltaY = cursorTop - window.scrollY + window.innerHeight / 2 - cursorHeight / 2
}
if (elementRect.left < 0 + margin) {
deltaX = elementRect.left - margin
} else if (elementRect.right > window.innerWidth - margin) {
deltaX = elementRect.right - window.innerWidth + margin
if (cursorLeft < 0 || cursorLeft > window.innerWidth) {
deltaX = cursorLeft - window.scrollX + window.innerWidth / 2
}
window.scrollBy(deltaX, deltaY)
}
function scrollTo(element, options) {
options = options || {}
options.margin = options.margin || 0
let rect = scrollWrapperElements(element, options)
scrollWindow(element, options, rect)
function scrollTo(element) {
let window = getWindow(element)
let s = window.getSelection()
if (s.rangeCount > 0) {
let selectionRect = s.getRangeAt(0).getBoundingClientRect()
let innerRect = selectionRect
let wrapper = element
let cursorHeight = innerRect.height
let cursorTop = innerRect.top
let cursorLeft = innerRect.left
while (wrapper != window.document.body) {
let wrapperRect = wrapper.getBoundingClientRect()
let currentY = cursorTop
let cursorBottom = cursorTop + cursorHeight
if (cursorTop < wrapperRect.top || cursorBottom > wrapperRect.bottom) {
cursorTop = wrapperRect.top + wrapperRect.height / 2 - cursorHeight / 2
wrapper.scrollTop += currentY - cursorTop
}
let currentLeft = cursorLeft
if (cursorLeft < wrapperRect.left || cursorLeft > wrapperRect.right) {
cursorLeft = wrapperRect.left + wrapperRect.width / 2
wrapper.scrollLeft += currentLeft - cursorLeft
}
innerRect = wrapperRect
wrapper = wrapper.parentNode
}
scrollWindow(window, cursorTop, cursorLeft, cursorHeight)
}
}
export default scrollTo