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:
committed by
Ian Storm Taylor
parent
c0daa27500
commit
92194f13e1
@@ -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
|
||||
|
Reference in New Issue
Block a user