lint: scroll.js

This commit is contained in:
John McLear 2020-12-26 20:39:37 +00:00
parent b760e699c6
commit e051f2f2f7

View file

@ -1,3 +1,5 @@
'use strict';
/* /*
This file handles scroll on edition or when user presses arrow keys. This file handles scroll on edition or when user presses arrow keys.
In this file we have two representations of line (browser and rep line). In this file we have two representations of line (browser and rep line).
@ -17,23 +19,26 @@ function Scroll(outerWin) {
this.rootDocument = parent.parent.document; this.rootDocument = parent.parent.document;
} }
Scroll.prototype.scrollWhenCaretIsInTheLastLineOfViewportWhenNecessary = function (rep, isScrollableEvent, innerHeight) { Scroll.prototype.scrollWhenCaretIsInTheLastLineOfViewportWhenNecessary =
function (rep, isScrollableEvent, innerHeight) {
// are we placing the caret on the line at the bottom of viewport? // are we placing the caret on the line at the bottom of viewport?
// And if so, do we need to scroll the editor, as defined on the settings.json? // And if so, do we need to scroll the editor, as defined on the settings.json?
const shouldScrollWhenCaretIsAtBottomOfViewport = this.scrollSettings.scrollWhenCaretIsInTheLastLineOfViewport; const shouldScrollWhenCaretIsAtBottomOfViewport =
if (shouldScrollWhenCaretIsAtBottomOfViewport) { this.scrollSettings.scrollWhenCaretIsInTheLastLineOfViewport;
// avoid scrolling when selection includes multiple lines -- user can potentially be selecting more lines if (shouldScrollWhenCaretIsAtBottomOfViewport) {
// than it fits on viewport // avoid scrolling when selection includes multiple lines --
const multipleLinesSelected = rep.selStart[0] !== rep.selEnd[0]; // user can potentially be selecting more lines
// than it fits on viewport
const multipleLinesSelected = rep.selStart[0] !== rep.selEnd[0];
// avoid scrolling when pad loads // avoid scrolling when pad loads
if (isScrollableEvent && !multipleLinesSelected && this._isCaretAtTheBottomOfViewport(rep)) { if (isScrollableEvent && !multipleLinesSelected && this._isCaretAtTheBottomOfViewport(rep)) {
// when scrollWhenFocusLineIsOutOfViewport.percentage is 0, pixelsToScroll is 0 // when scrollWhenFocusLineIsOutOfViewport.percentage is 0, pixelsToScroll is 0
const pixelsToScroll = this._getPixelsRelativeToPercentageOfViewport(innerHeight); const pixelsToScroll = this._getPixelsRelativeToPercentageOfViewport(innerHeight);
this._scrollYPage(pixelsToScroll); this._scrollYPage(pixelsToScroll);
}
} }
} };
};
Scroll.prototype.scrollWhenPressArrowKeys = function (arrowUp, rep, innerHeight) { Scroll.prototype.scrollWhenPressArrowKeys = function (arrowUp, rep, innerHeight) {
// if percentageScrollArrowUp is 0, let the scroll to be handled as default, put the previous // if percentageScrollArrowUp is 0, let the scroll to be handled as default, put the previous
@ -60,8 +65,10 @@ Scroll.prototype._isCaretAtTheBottomOfViewport = function (rep) {
const caretLine = rep.selStart[0]; const caretLine = rep.selStart[0];
const lineAfterCaretLine = caretLine + 1; const lineAfterCaretLine = caretLine + 1;
const firstLineVisibleAfterCaretLine = caretPosition.getNextVisibleLine(lineAfterCaretLine, rep); const firstLineVisibleAfterCaretLine = caretPosition.getNextVisibleLine(lineAfterCaretLine, rep);
const caretLineIsPartiallyVisibleOnViewport = this._isLinePartiallyVisibleOnViewport(caretLine, rep); const caretLineIsPartiallyVisibleOnViewport =
const lineAfterCaretLineIsPartiallyVisibleOnViewport = this._isLinePartiallyVisibleOnViewport(firstLineVisibleAfterCaretLine, rep); this._isLinePartiallyVisibleOnViewport(caretLine, rep);
const lineAfterCaretLineIsPartiallyVisibleOnViewport =
this._isLinePartiallyVisibleOnViewport(firstLineVisibleAfterCaretLine, rep);
if (caretLineIsPartiallyVisibleOnViewport || lineAfterCaretLineIsPartiallyVisibleOnViewport) { if (caretLineIsPartiallyVisibleOnViewport || lineAfterCaretLineIsPartiallyVisibleOnViewport) {
// check if the caret is in the bottom of the viewport // check if the caret is in the bottom of the viewport
const caretLinePosition = caretPosition.getPosition(); const caretLinePosition = caretPosition.getPosition();
@ -99,9 +106,11 @@ Scroll.prototype._getViewPortTopBottom = function () {
const doc = this.doc; const doc = this.doc;
const height = doc.documentElement.clientHeight; // includes padding const height = doc.documentElement.clientHeight; // includes padding
// we have to get the exactly height of the viewport. So it has to subtract all the values which changes // we have to get the exactly height of the viewport.
// So it has to subtract all the values which changes
// the viewport height (E.g. padding, position top) // the viewport height (E.g. padding, position top)
const viewportExtraSpacesAndPosition = this._getEditorPositionTop() + this._getPaddingTopAddedWhenPageViewIsEnable(); const viewportExtraSpacesAndPosition =
this._getEditorPositionTop() + this._getPaddingTopAddedWhenPageViewIsEnable();
return { return {
top: theTop, top: theTop,
bottom: (theTop + height - viewportExtraSpacesAndPosition), bottom: (theTop + height - viewportExtraSpacesAndPosition),
@ -162,9 +171,12 @@ Scroll.prototype.setScrollXY = function (x, y) {
Scroll.prototype._isCaretAtTheTopOfViewport = function (rep) { Scroll.prototype._isCaretAtTheTopOfViewport = function (rep) {
const caretLine = rep.selStart[0]; const caretLine = rep.selStart[0];
const linePrevCaretLine = caretLine - 1; const linePrevCaretLine = caretLine - 1;
const firstLineVisibleBeforeCaretLine = caretPosition.getPreviousVisibleLine(linePrevCaretLine, rep); const firstLineVisibleBeforeCaretLine =
const caretLineIsPartiallyVisibleOnViewport = this._isLinePartiallyVisibleOnViewport(caretLine, rep); caretPosition.getPreviousVisibleLine(linePrevCaretLine, rep);
const lineBeforeCaretLineIsPartiallyVisibleOnViewport = this._isLinePartiallyVisibleOnViewport(firstLineVisibleBeforeCaretLine, rep); const caretLineIsPartiallyVisibleOnViewport =
this._isLinePartiallyVisibleOnViewport(caretLine, rep);
const lineBeforeCaretLineIsPartiallyVisibleOnViewport =
this._isLinePartiallyVisibleOnViewport(firstLineVisibleBeforeCaretLine, rep);
if (caretLineIsPartiallyVisibleOnViewport || lineBeforeCaretLineIsPartiallyVisibleOnViewport) { if (caretLineIsPartiallyVisibleOnViewport || lineBeforeCaretLineIsPartiallyVisibleOnViewport) {
const caretLinePosition = caretPosition.getPosition(); // get the position of the browser line const caretLinePosition = caretPosition.getPosition(); // get the position of the browser line
const viewportPosition = this._getViewPortTopBottom(); const viewportPosition = this._getViewPortTopBottom();
@ -172,7 +184,8 @@ Scroll.prototype._isCaretAtTheTopOfViewport = function (rep) {
const viewportBottom = viewportPosition.bottom; const viewportBottom = viewportPosition.bottom;
const caretLineIsBelowViewportTop = caretLinePosition.bottom >= viewportTop; const caretLineIsBelowViewportTop = caretLinePosition.bottom >= viewportTop;
const caretLineIsAboveViewportBottom = caretLinePosition.top < viewportBottom; const caretLineIsAboveViewportBottom = caretLinePosition.top < viewportBottom;
const caretLineIsInsideOfViewport = caretLineIsBelowViewportTop && caretLineIsAboveViewportBottom; const caretLineIsInsideOfViewport =
caretLineIsBelowViewportTop && caretLineIsAboveViewportBottom;
if (caretLineIsInsideOfViewport) { if (caretLineIsInsideOfViewport) {
const prevLineTop = caretPosition.getPositionTopOfPreviousBrowserLine(caretLinePosition, rep); const prevLineTop = caretPosition.getPositionTopOfPreviousBrowserLine(caretLinePosition, rep);
const previousLineIsAboveViewportTop = prevLineTop < viewportTop; const previousLineIsAboveViewportTop = prevLineTop < viewportTop;
@ -185,14 +198,15 @@ Scroll.prototype._isCaretAtTheTopOfViewport = function (rep) {
// By default, when user makes an edition in a line out of viewport, this line goes // By default, when user makes an edition in a line out of viewport, this line goes
// to the edge of viewport. This function gets the extra pixels necessary to get the // to the edge of viewport. This function gets the extra pixels necessary to get the
// caret line in a position X relative to Y% viewport. // caret line in a position X relative to Y% viewport.
Scroll.prototype._getPixelsRelativeToPercentageOfViewport = function (innerHeight, aboveOfViewport) { Scroll.prototype._getPixelsRelativeToPercentageOfViewport =
let pixels = 0; function (innerHeight, aboveOfViewport) {
const scrollPercentageRelativeToViewport = this._getPercentageToScroll(aboveOfViewport); let pixels = 0;
if (scrollPercentageRelativeToViewport > 0 && scrollPercentageRelativeToViewport <= 1) { const scrollPercentageRelativeToViewport = this._getPercentageToScroll(aboveOfViewport);
pixels = parseInt(innerHeight * scrollPercentageRelativeToViewport); if (scrollPercentageRelativeToViewport > 0 && scrollPercentageRelativeToViewport <= 1) {
} pixels = parseInt(innerHeight * scrollPercentageRelativeToViewport);
return pixels; }
}; return pixels;
};
// we use different percentages when change selection. It depends on if it is // we use different percentages when change selection. It depends on if it is
// either above the top or below the bottom of the page // either above the top or below the bottom of the page
@ -226,30 +240,34 @@ Scroll.prototype._scrollYPageWithoutAnimation = function (pixelsToScroll) {
this.outerWin.scrollBy(0, pixelsToScroll); this.outerWin.scrollBy(0, pixelsToScroll);
}; };
Scroll.prototype._scrollYPageWithAnimation = function (pixelsToScroll, durationOfAnimationToShowFocusline) { Scroll.prototype._scrollYPageWithAnimation =
const outerDocBody = this.doc.getElementById('outerdocbody'); function (pixelsToScroll, durationOfAnimationToShowFocusline) {
const outerDocBody = this.doc.getElementById('outerdocbody');
// it works on later versions of Chrome // it works on later versions of Chrome
const $outerDocBody = $(outerDocBody); const $outerDocBody = $(outerDocBody);
this._triggerScrollWithAnimation($outerDocBody, pixelsToScroll, durationOfAnimationToShowFocusline); this._triggerScrollWithAnimation(
$outerDocBody, pixelsToScroll, durationOfAnimationToShowFocusline);
// it works on Firefox and earlier versions of Chrome // it works on Firefox and earlier versions of Chrome
const $outerDocBodyParent = $outerDocBody.parent(); const $outerDocBodyParent = $outerDocBody.parent();
this._triggerScrollWithAnimation($outerDocBodyParent, pixelsToScroll, durationOfAnimationToShowFocusline); this._triggerScrollWithAnimation(
}; $outerDocBodyParent, pixelsToScroll, durationOfAnimationToShowFocusline);
};
// using a custom queue and clearing it, we avoid creating a queue of scroll animations. So if this function // using a custom queue and clearing it, we avoid creating a queue of scroll animations.
// is called twice quickly, only the last one runs. // So if this function is called twice quickly, only the last one runs.
Scroll.prototype._triggerScrollWithAnimation = function ($elem, pixelsToScroll, durationOfAnimationToShowFocusline) { Scroll.prototype._triggerScrollWithAnimation =
// clear the queue of animation function ($elem, pixelsToScroll, durationOfAnimationToShowFocusline) {
$elem.stop('scrollanimation'); // clear the queue of animation
$elem.animate({ $elem.stop('scrollanimation');
scrollTop: `+=${pixelsToScroll}`, $elem.animate({
}, { scrollTop: `+=${pixelsToScroll}`,
duration: durationOfAnimationToShowFocusline, }, {
queue: 'scrollanimation', duration: durationOfAnimationToShowFocusline,
}).dequeue('scrollanimation'); queue: 'scrollanimation',
}; }).dequeue('scrollanimation');
};
// scrollAmountWhenFocusLineIsOutOfViewport is set to 0 (default), scroll it the minimum distance // scrollAmountWhenFocusLineIsOutOfViewport is set to 0 (default), scroll it the minimum distance
// needed to be completely in view. If the value is greater than 0 and less than or equal to 1, // needed to be completely in view. If the value is greater than 0 and less than or equal to 1,
@ -257,7 +275,6 @@ Scroll.prototype._triggerScrollWithAnimation = function ($elem, pixelsToScroll,
// (viewport height * scrollAmountWhenFocusLineIsOutOfViewport) pixels // (viewport height * scrollAmountWhenFocusLineIsOutOfViewport) pixels
Scroll.prototype.scrollNodeVerticallyIntoView = function (rep, innerHeight) { Scroll.prototype.scrollNodeVerticallyIntoView = function (rep, innerHeight) {
const viewport = this._getViewPortTopBottom(); const viewport = this._getViewPortTopBottom();
const isPartOfRepLineOutOfViewport = this._partOfRepLineIsOutOfViewport(viewport, rep);
// when the selection changes outside of the viewport the browser automatically scrolls the line // when the selection changes outside of the viewport the browser automatically scrolls the line
// to inside of the viewport. Tested on IE, Firefox, Chrome in releases from 2015 until now // to inside of the viewport. Tested on IE, Firefox, Chrome in releases from 2015 until now
@ -269,10 +286,12 @@ Scroll.prototype.scrollNodeVerticallyIntoView = function (rep, innerHeight) {
const caretIsAboveOfViewport = distanceOfTopOfViewport < 0; const caretIsAboveOfViewport = distanceOfTopOfViewport < 0;
const caretIsBelowOfViewport = distanceOfBottomOfViewport < 0; const caretIsBelowOfViewport = distanceOfBottomOfViewport < 0;
if (caretIsAboveOfViewport) { if (caretIsAboveOfViewport) {
var pixelsToScroll = distanceOfTopOfViewport - this._getPixelsRelativeToPercentageOfViewport(innerHeight, true); const pixelsToScroll =
distanceOfTopOfViewport - this._getPixelsRelativeToPercentageOfViewport(innerHeight, true);
this._scrollYPage(pixelsToScroll); this._scrollYPage(pixelsToScroll);
} else if (caretIsBelowOfViewport) { } else if (caretIsBelowOfViewport) {
var pixelsToScroll = -distanceOfBottomOfViewport + this._getPixelsRelativeToPercentageOfViewport(innerHeight); const pixelsToScroll = -distanceOfBottomOfViewport +
this._getPixelsRelativeToPercentageOfViewport(innerHeight);
this._scrollYPage(pixelsToScroll); this._scrollYPage(pixelsToScroll);
} else { } else {
this.scrollWhenCaretIsInTheLastLineOfViewportWhenNecessary(rep, true, innerHeight); this.scrollWhenCaretIsInTheLastLineOfViewportWhenNecessary(rep, true, innerHeight);
@ -311,12 +330,10 @@ Scroll.prototype.getVisibleLineRange = function (rep) {
const obj = {}; const obj = {};
const self = this; const self = this;
const start = rep.lines.search((e) => self._getLineEntryTopBottom(e, obj).bottom > viewport.top); const start = rep.lines.search((e) => self._getLineEntryTopBottom(e, obj).bottom > viewport.top);
let end = rep.lines.search((e) => // return the first line that the top position is greater or equal than
// return the first line that the top position is greater or equal than // the viewport. That is the first line that is below the viewport bottom.
// the viewport. That is the first line that is below the viewport bottom. // So the line that is in the bottom of the viewport is the very previous one.
// So the line that is in the bottom of the viewport is the very previous one. let end = rep.lines.search((e) => self._getLineEntryTopBottom(e, obj).top >= viewport.bottom);
self._getLineEntryTopBottom(e, obj).top >= viewport.bottom
);
if (end < start) end = start; // unlikely if (end < start) end = start; // unlikely
// top.console.log(start+","+(end -1)); // top.console.log(start+","+(end -1));
return [start, end - 1]; return [start, end - 1];
@ -327,6 +344,4 @@ Scroll.prototype.getVisibleCharRange = function (rep) {
return [rep.lines.offsetOfIndex(lineRange[0]), rep.lines.offsetOfIndex(lineRange[1])]; return [rep.lines.offsetOfIndex(lineRange[0]), rep.lines.offsetOfIndex(lineRange[1])];
}; };
exports.init = function (outerWin) { exports.init = (outerWin) => new Scroll(outerWin);
return new Scroll(outerWin);
};