Ghost/ghost/admin/app/modifiers/scroll-into-view.js
Kevin Ansfield 9223d0237c Added scroll-into-view behavior when opening gif selector
refs https://github.com/TryGhost/Team/issues/1225

When the gif selector is activated we want to scroll as much of the picker into view as possible.

- updated `scroll-into-view` modifier so it can work on bounding rects as well as offsets for those situations where a scroll parent is not the offset parent
  - only implemented "off bottom" behavior for now as that's all we need for this use-case
  - if the scroll adjustment would mean the top is cut off we readjust so that the top of the element is always visible
2021-11-30 12:51:56 +00:00

55 lines
2.1 KiB
JavaScript

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'});
}
}
}
});