lint: scroll.js
This commit is contained in:
parent
b760e699c6
commit
e051f2f2f7
1 changed files with 77 additions and 62 deletions
|
@ -1,3 +1,5 @@
|
|||
'use strict';
|
||||
|
||||
/*
|
||||
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).
|
||||
|
@ -17,23 +19,26 @@ function Scroll(outerWin) {
|
|||
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?
|
||||
// And if so, do we need to scroll the editor, as defined on the settings.json?
|
||||
const shouldScrollWhenCaretIsAtBottomOfViewport = this.scrollSettings.scrollWhenCaretIsInTheLastLineOfViewport;
|
||||
if (shouldScrollWhenCaretIsAtBottomOfViewport) {
|
||||
// avoid scrolling when selection includes multiple lines -- user can potentially be selecting more lines
|
||||
// than it fits on viewport
|
||||
const multipleLinesSelected = rep.selStart[0] !== rep.selEnd[0];
|
||||
const shouldScrollWhenCaretIsAtBottomOfViewport =
|
||||
this.scrollSettings.scrollWhenCaretIsInTheLastLineOfViewport;
|
||||
if (shouldScrollWhenCaretIsAtBottomOfViewport) {
|
||||
// avoid scrolling when selection includes multiple lines --
|
||||
// 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
|
||||
if (isScrollableEvent && !multipleLinesSelected && this._isCaretAtTheBottomOfViewport(rep)) {
|
||||
// when scrollWhenFocusLineIsOutOfViewport.percentage is 0, pixelsToScroll is 0
|
||||
const pixelsToScroll = this._getPixelsRelativeToPercentageOfViewport(innerHeight);
|
||||
this._scrollYPage(pixelsToScroll);
|
||||
// avoid scrolling when pad loads
|
||||
if (isScrollableEvent && !multipleLinesSelected && this._isCaretAtTheBottomOfViewport(rep)) {
|
||||
// when scrollWhenFocusLineIsOutOfViewport.percentage is 0, pixelsToScroll is 0
|
||||
const pixelsToScroll = this._getPixelsRelativeToPercentageOfViewport(innerHeight);
|
||||
this._scrollYPage(pixelsToScroll);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
Scroll.prototype.scrollWhenPressArrowKeys = function (arrowUp, rep, innerHeight) {
|
||||
// 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 lineAfterCaretLine = caretLine + 1;
|
||||
const firstLineVisibleAfterCaretLine = caretPosition.getNextVisibleLine(lineAfterCaretLine, rep);
|
||||
const caretLineIsPartiallyVisibleOnViewport = this._isLinePartiallyVisibleOnViewport(caretLine, rep);
|
||||
const lineAfterCaretLineIsPartiallyVisibleOnViewport = this._isLinePartiallyVisibleOnViewport(firstLineVisibleAfterCaretLine, rep);
|
||||
const caretLineIsPartiallyVisibleOnViewport =
|
||||
this._isLinePartiallyVisibleOnViewport(caretLine, rep);
|
||||
const lineAfterCaretLineIsPartiallyVisibleOnViewport =
|
||||
this._isLinePartiallyVisibleOnViewport(firstLineVisibleAfterCaretLine, rep);
|
||||
if (caretLineIsPartiallyVisibleOnViewport || lineAfterCaretLineIsPartiallyVisibleOnViewport) {
|
||||
// check if the caret is in the bottom of the viewport
|
||||
const caretLinePosition = caretPosition.getPosition();
|
||||
|
@ -99,9 +106,11 @@ Scroll.prototype._getViewPortTopBottom = function () {
|
|||
const doc = this.doc;
|
||||
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)
|
||||
const viewportExtraSpacesAndPosition = this._getEditorPositionTop() + this._getPaddingTopAddedWhenPageViewIsEnable();
|
||||
const viewportExtraSpacesAndPosition =
|
||||
this._getEditorPositionTop() + this._getPaddingTopAddedWhenPageViewIsEnable();
|
||||
return {
|
||||
top: theTop,
|
||||
bottom: (theTop + height - viewportExtraSpacesAndPosition),
|
||||
|
@ -162,9 +171,12 @@ Scroll.prototype.setScrollXY = function (x, y) {
|
|||
Scroll.prototype._isCaretAtTheTopOfViewport = function (rep) {
|
||||
const caretLine = rep.selStart[0];
|
||||
const linePrevCaretLine = caretLine - 1;
|
||||
const firstLineVisibleBeforeCaretLine = caretPosition.getPreviousVisibleLine(linePrevCaretLine, rep);
|
||||
const caretLineIsPartiallyVisibleOnViewport = this._isLinePartiallyVisibleOnViewport(caretLine, rep);
|
||||
const lineBeforeCaretLineIsPartiallyVisibleOnViewport = this._isLinePartiallyVisibleOnViewport(firstLineVisibleBeforeCaretLine, rep);
|
||||
const firstLineVisibleBeforeCaretLine =
|
||||
caretPosition.getPreviousVisibleLine(linePrevCaretLine, rep);
|
||||
const caretLineIsPartiallyVisibleOnViewport =
|
||||
this._isLinePartiallyVisibleOnViewport(caretLine, rep);
|
||||
const lineBeforeCaretLineIsPartiallyVisibleOnViewport =
|
||||
this._isLinePartiallyVisibleOnViewport(firstLineVisibleBeforeCaretLine, rep);
|
||||
if (caretLineIsPartiallyVisibleOnViewport || lineBeforeCaretLineIsPartiallyVisibleOnViewport) {
|
||||
const caretLinePosition = caretPosition.getPosition(); // get the position of the browser line
|
||||
const viewportPosition = this._getViewPortTopBottom();
|
||||
|
@ -172,7 +184,8 @@ Scroll.prototype._isCaretAtTheTopOfViewport = function (rep) {
|
|||
const viewportBottom = viewportPosition.bottom;
|
||||
const caretLineIsBelowViewportTop = caretLinePosition.bottom >= viewportTop;
|
||||
const caretLineIsAboveViewportBottom = caretLinePosition.top < viewportBottom;
|
||||
const caretLineIsInsideOfViewport = caretLineIsBelowViewportTop && caretLineIsAboveViewportBottom;
|
||||
const caretLineIsInsideOfViewport =
|
||||
caretLineIsBelowViewportTop && caretLineIsAboveViewportBottom;
|
||||
if (caretLineIsInsideOfViewport) {
|
||||
const prevLineTop = caretPosition.getPositionTopOfPreviousBrowserLine(caretLinePosition, rep);
|
||||
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
|
||||
// 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.
|
||||
Scroll.prototype._getPixelsRelativeToPercentageOfViewport = function (innerHeight, aboveOfViewport) {
|
||||
let pixels = 0;
|
||||
const scrollPercentageRelativeToViewport = this._getPercentageToScroll(aboveOfViewport);
|
||||
if (scrollPercentageRelativeToViewport > 0 && scrollPercentageRelativeToViewport <= 1) {
|
||||
pixels = parseInt(innerHeight * scrollPercentageRelativeToViewport);
|
||||
}
|
||||
return pixels;
|
||||
};
|
||||
Scroll.prototype._getPixelsRelativeToPercentageOfViewport =
|
||||
function (innerHeight, aboveOfViewport) {
|
||||
let pixels = 0;
|
||||
const scrollPercentageRelativeToViewport = this._getPercentageToScroll(aboveOfViewport);
|
||||
if (scrollPercentageRelativeToViewport > 0 && scrollPercentageRelativeToViewport <= 1) {
|
||||
pixels = parseInt(innerHeight * scrollPercentageRelativeToViewport);
|
||||
}
|
||||
return pixels;
|
||||
};
|
||||
|
||||
// we use different percentages when change selection. It depends on if it is
|
||||
// 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);
|
||||
};
|
||||
|
||||
Scroll.prototype._scrollYPageWithAnimation = function (pixelsToScroll, durationOfAnimationToShowFocusline) {
|
||||
const outerDocBody = this.doc.getElementById('outerdocbody');
|
||||
Scroll.prototype._scrollYPageWithAnimation =
|
||||
function (pixelsToScroll, durationOfAnimationToShowFocusline) {
|
||||
const outerDocBody = this.doc.getElementById('outerdocbody');
|
||||
|
||||
// it works on later versions of Chrome
|
||||
const $outerDocBody = $(outerDocBody);
|
||||
this._triggerScrollWithAnimation($outerDocBody, pixelsToScroll, durationOfAnimationToShowFocusline);
|
||||
// it works on later versions of Chrome
|
||||
const $outerDocBody = $(outerDocBody);
|
||||
this._triggerScrollWithAnimation(
|
||||
$outerDocBody, pixelsToScroll, durationOfAnimationToShowFocusline);
|
||||
|
||||
// it works on Firefox and earlier versions of Chrome
|
||||
const $outerDocBodyParent = $outerDocBody.parent();
|
||||
this._triggerScrollWithAnimation($outerDocBodyParent, pixelsToScroll, durationOfAnimationToShowFocusline);
|
||||
};
|
||||
// it works on Firefox and earlier versions of Chrome
|
||||
const $outerDocBodyParent = $outerDocBody.parent();
|
||||
this._triggerScrollWithAnimation(
|
||||
$outerDocBodyParent, pixelsToScroll, durationOfAnimationToShowFocusline);
|
||||
};
|
||||
|
||||
// using a custom queue and clearing it, we avoid creating a queue of scroll animations. So if this function
|
||||
// is called twice quickly, only the last one runs.
|
||||
Scroll.prototype._triggerScrollWithAnimation = function ($elem, pixelsToScroll, durationOfAnimationToShowFocusline) {
|
||||
// clear the queue of animation
|
||||
$elem.stop('scrollanimation');
|
||||
$elem.animate({
|
||||
scrollTop: `+=${pixelsToScroll}`,
|
||||
}, {
|
||||
duration: durationOfAnimationToShowFocusline,
|
||||
queue: 'scrollanimation',
|
||||
}).dequeue('scrollanimation');
|
||||
};
|
||||
// using a custom queue and clearing it, we avoid creating a queue of scroll animations.
|
||||
// So if this function is called twice quickly, only the last one runs.
|
||||
Scroll.prototype._triggerScrollWithAnimation =
|
||||
function ($elem, pixelsToScroll, durationOfAnimationToShowFocusline) {
|
||||
// clear the queue of animation
|
||||
$elem.stop('scrollanimation');
|
||||
$elem.animate({
|
||||
scrollTop: `+=${pixelsToScroll}`,
|
||||
}, {
|
||||
duration: durationOfAnimationToShowFocusline,
|
||||
queue: 'scrollanimation',
|
||||
}).dequeue('scrollanimation');
|
||||
};
|
||||
|
||||
// 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,
|
||||
|
@ -257,7 +275,6 @@ Scroll.prototype._triggerScrollWithAnimation = function ($elem, pixelsToScroll,
|
|||
// (viewport height * scrollAmountWhenFocusLineIsOutOfViewport) pixels
|
||||
Scroll.prototype.scrollNodeVerticallyIntoView = function (rep, innerHeight) {
|
||||
const viewport = this._getViewPortTopBottom();
|
||||
const isPartOfRepLineOutOfViewport = this._partOfRepLineIsOutOfViewport(viewport, rep);
|
||||
|
||||
// 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
|
||||
|
@ -269,10 +286,12 @@ Scroll.prototype.scrollNodeVerticallyIntoView = function (rep, innerHeight) {
|
|||
const caretIsAboveOfViewport = distanceOfTopOfViewport < 0;
|
||||
const caretIsBelowOfViewport = distanceOfBottomOfViewport < 0;
|
||||
if (caretIsAboveOfViewport) {
|
||||
var pixelsToScroll = distanceOfTopOfViewport - this._getPixelsRelativeToPercentageOfViewport(innerHeight, true);
|
||||
const pixelsToScroll =
|
||||
distanceOfTopOfViewport - this._getPixelsRelativeToPercentageOfViewport(innerHeight, true);
|
||||
this._scrollYPage(pixelsToScroll);
|
||||
} else if (caretIsBelowOfViewport) {
|
||||
var pixelsToScroll = -distanceOfBottomOfViewport + this._getPixelsRelativeToPercentageOfViewport(innerHeight);
|
||||
const pixelsToScroll = -distanceOfBottomOfViewport +
|
||||
this._getPixelsRelativeToPercentageOfViewport(innerHeight);
|
||||
this._scrollYPage(pixelsToScroll);
|
||||
} else {
|
||||
this.scrollWhenCaretIsInTheLastLineOfViewportWhenNecessary(rep, true, innerHeight);
|
||||
|
@ -311,12 +330,10 @@ Scroll.prototype.getVisibleLineRange = function (rep) {
|
|||
const obj = {};
|
||||
const self = this;
|
||||
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
|
||||
// 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.
|
||||
self._getLineEntryTopBottom(e, obj).top >= viewport.bottom
|
||||
);
|
||||
// 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.
|
||||
// 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);
|
||||
if (end < start) end = start; // unlikely
|
||||
// top.console.log(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])];
|
||||
};
|
||||
|
||||
exports.init = function (outerWin) {
|
||||
return new Scroll(outerWin);
|
||||
};
|
||||
exports.init = (outerWin) => new Scroll(outerWin);
|
||||
|
|
Loading…
Reference in a new issue