scroll.js 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this
  3. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  4. "use strict";
  5. /**
  6. * Scroll the document so that the element "elem" appears in the viewport.
  7. *
  8. * @param {DOMNode} elem
  9. * The element that needs to appear in the viewport.
  10. * @param {Boolean} centered
  11. * true if you want it centered, false if you want it to appear on the
  12. * top of the viewport. It is true by default, and that is usually what
  13. * you want.
  14. */
  15. function scrollIntoViewIfNeeded(elem, centered = true) {
  16. let win = elem.ownerDocument.defaultView;
  17. let clientRect = elem.getBoundingClientRect();
  18. // The following are always from the {top, bottom}
  19. // of the viewport, to the {top, …} of the box.
  20. // Think of them as geometrical vectors, it helps.
  21. // The origin is at the top left.
  22. let topToBottom = clientRect.bottom;
  23. let bottomToTop = clientRect.top - win.innerHeight;
  24. // We allow one translation on the y axis.
  25. let yAllowed = true;
  26. // Whatever `centered` is, the behavior is the same if the box is
  27. // (even partially) visible.
  28. if ((topToBottom > 0 || !centered) && topToBottom <= elem.offsetHeight) {
  29. win.scrollBy(0, topToBottom - elem.offsetHeight);
  30. yAllowed = false;
  31. } else if ((bottomToTop < 0 || !centered) &&
  32. bottomToTop >= -elem.offsetHeight) {
  33. win.scrollBy(0, bottomToTop + elem.offsetHeight);
  34. yAllowed = false;
  35. }
  36. // If we want it centered, and the box is completely hidden,
  37. // then we center it explicitly.
  38. if (centered) {
  39. if (yAllowed && (topToBottom <= 0 || bottomToTop >= 0)) {
  40. win.scroll(win.scrollX,
  41. win.scrollY + clientRect.top
  42. - (win.innerHeight - elem.offsetHeight) / 2);
  43. }
  44. }
  45. }
  46. exports.scrollIntoViewIfNeeded = scrollIntoViewIfNeeded;