Ghost/ghost/admin/app/modifiers/scroll-into-view.js

55 lines
2.1 KiB
JavaScript
Raw Normal View History

import getScrollParent from 'ghost-admin/utils/get-scroll-parent';
import {modifier} from 'ember-modifier';
export default modifier((element, [shouldScroll = true], {offset = 0, useViewport = true}) => {
if (shouldScroll) {
const scrollParent = getScrollParent(element);
// scrolls so the element is visible on-screen
if (useViewport) {
const elementRect = element.getBoundingClientRect();
const scrollParentRect = scrollParent.getBoundingClientRect();
// TODO: ensure scroll parent is visible?
const isOffTop = elementRect.top < 0;
const isOffBottom = elementRect.bottom > scrollParentRect.bottom;
if (isOffTop) {
// TODO: implement me
}
if (isOffBottom) {
let adjustment = Math.abs(scrollParentRect.bottom - elementRect.bottom);
// keep top on screen
if (elementRect.top - adjustment < offset) {
const readjustment = Math.abs(elementRect.top - adjustment - (offset * 2));
adjustment -= readjustment;
}
const top = scrollParent.scrollTop + adjustment + offset;
scrollParent.scrollTo({top, behavior: 'smooth'});
}
}
// scrolls so the element is visible inside of the scroll parent's viewport,
// may not result in element being visible on-screen if scroll parent is cut off
if (!useViewport) {
const isOffTop = element.offsetTop < scrollParent.scrollTop;
const isOffBottom = scrollParent.scrollTop + scrollParent.offsetHeight < element.offsetTop + element.offsetHeight;
if (isOffTop) {
const top = element.offsetTop - offset;
scrollParent.scrollTo({top, behavior: 'smooth'});
}
if (isOffBottom) {
const top = element.offsetTop - scrollParent.offsetHeight + element.offsetHeight + offset;
scrollParent.scrollTo({top, behavior: 'smooth'});
}
}
}
}, {eager: false});