Update to improve sync scroll to edit performance and fix sync scroll behavior on many situations
This commit is contained in:
parent
954137b760
commit
e9b0ce8e04
2 changed files with 70 additions and 33 deletions
|
@ -722,8 +722,11 @@ function windowResizeInner(callback) {
|
||||||
if (loaded) {
|
if (loaded) {
|
||||||
if (editor.getOption('scrollbarStyle') === 'native') {
|
if (editor.getOption('scrollbarStyle') === 'native') {
|
||||||
clearMap();
|
clearMap();
|
||||||
|
if (editorHasFocus()) {
|
||||||
syncScrollToView();
|
syncScrollToView();
|
||||||
|
} else {
|
||||||
syncScrollToEdit();
|
syncScrollToEdit();
|
||||||
|
}
|
||||||
updateScrollspy();
|
updateScrollspy();
|
||||||
if (callback && typeof callback === 'function')
|
if (callback && typeof callback === 'function')
|
||||||
callback();
|
callback();
|
||||||
|
@ -732,8 +735,11 @@ function windowResizeInner(callback) {
|
||||||
editor.setOption('viewportMargin', Infinity);
|
editor.setOption('viewportMargin', Infinity);
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
clearMap();
|
clearMap();
|
||||||
|
if (editorHasFocus()) {
|
||||||
syncScrollToView();
|
syncScrollToView();
|
||||||
|
} else {
|
||||||
syncScrollToEdit();
|
syncScrollToEdit();
|
||||||
|
}
|
||||||
editor.setOption('viewportMargin', viewportMargin);
|
editor.setOption('viewportMargin', viewportMargin);
|
||||||
//add or update user cursors
|
//add or update user cursors
|
||||||
for (var i = 0; i < onlineUsers.length; i++) {
|
for (var i = 0; i < onlineUsers.length; i++) {
|
||||||
|
@ -774,6 +780,7 @@ function checkResponsive() {
|
||||||
}
|
}
|
||||||
|
|
||||||
var lastEditorWidth = 0;
|
var lastEditorWidth = 0;
|
||||||
|
var previousFocusOnEditor = null;
|
||||||
|
|
||||||
function checkEditorStyle() {
|
function checkEditorStyle() {
|
||||||
var desireHeight = statusBar ? (ui.area.edit.height() - statusBar.outerHeight()) : ui.area.edit.height();
|
var desireHeight = statusBar ? (ui.area.edit.height() - statusBar.outerHeight()) : ui.area.edit.height();
|
||||||
|
@ -806,6 +813,11 @@ function checkEditorStyle() {
|
||||||
}
|
}
|
||||||
if (!ui.area.resize.syncToggle.length) {
|
if (!ui.area.resize.syncToggle.length) {
|
||||||
ui.area.resize.syncToggle = $('<button class="btn btn-lg btn-default ui-sync-toggle" title="Toggle sync scrolling"><i class="fa fa-link fa-fw"></i></button>');
|
ui.area.resize.syncToggle = $('<button class="btn btn-lg btn-default ui-sync-toggle" title="Toggle sync scrolling"><i class="fa fa-link fa-fw"></i></button>');
|
||||||
|
ui.area.resize.syncToggle.hover(function () {
|
||||||
|
previousFocusOnEditor = editorHasFocus();
|
||||||
|
}, function () {
|
||||||
|
previousFocusOnEditor = null;
|
||||||
|
});
|
||||||
ui.area.resize.syncToggle.click(function () {
|
ui.area.resize.syncToggle.click(function () {
|
||||||
syncscroll = !syncscroll;
|
syncscroll = !syncscroll;
|
||||||
checkSyncToggle();
|
checkSyncToggle();
|
||||||
|
@ -822,6 +834,13 @@ function checkEditorStyle() {
|
||||||
|
|
||||||
function checkSyncToggle() {
|
function checkSyncToggle() {
|
||||||
if (syncscroll) {
|
if (syncscroll) {
|
||||||
|
if (previousFocusOnEditor) {
|
||||||
|
preventSyncScrollToView = false;
|
||||||
|
syncScrollToView();
|
||||||
|
} else {
|
||||||
|
preventSyncScrollToEdit = false;
|
||||||
|
syncScrollToEdit();
|
||||||
|
}
|
||||||
ui.area.resize.syncToggle.find('i').removeClass('fa-unlink').addClass('fa-link');
|
ui.area.resize.syncToggle.find('i').removeClass('fa-unlink').addClass('fa-link');
|
||||||
} else {
|
} else {
|
||||||
ui.area.resize.syncToggle.find('i').removeClass('fa-link').addClass('fa-unlink');
|
ui.area.resize.syncToggle.find('i').removeClass('fa-link').addClass('fa-unlink');
|
||||||
|
@ -1003,10 +1022,15 @@ function changeMode(type) {
|
||||||
restoreInfo();
|
restoreInfo();
|
||||||
|
|
||||||
if (lastMode == modeType.view && currentMode == modeType.both) {
|
if (lastMode == modeType.view && currentMode == modeType.both) {
|
||||||
preventSyncScrollToView = true;
|
preventSyncScrollToView = 2;
|
||||||
syncScrollToEdit();
|
syncScrollToEdit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lastMode == modeType.edit && currentMode == modeType.both) {
|
||||||
|
preventSyncScrollToEdit = 2;
|
||||||
|
syncScrollToView();
|
||||||
|
}
|
||||||
|
|
||||||
if (lastMode != modeType.edit && currentMode == modeType.edit) {
|
if (lastMode != modeType.edit && currentMode == modeType.edit) {
|
||||||
editor.refresh();
|
editor.refresh();
|
||||||
}
|
}
|
||||||
|
@ -2595,8 +2619,11 @@ function updateViewInner() {
|
||||||
clearMap();
|
clearMap();
|
||||||
//buildMap();
|
//buildMap();
|
||||||
updateTitleReminder();
|
updateTitleReminder();
|
||||||
|
if (editorHasFocus()) {
|
||||||
syncScrollToView();
|
syncScrollToView();
|
||||||
|
} else {
|
||||||
syncScrollToEdit();
|
syncScrollToEdit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var updateHistoryDebounce = 600;
|
var updateHistoryDebounce = 600;
|
||||||
|
|
|
@ -110,17 +110,15 @@ var syncscroll = true;
|
||||||
var preventSyncScrollToEdit = false;
|
var preventSyncScrollToEdit = false;
|
||||||
var preventSyncScrollToView = false;
|
var preventSyncScrollToView = false;
|
||||||
|
|
||||||
var editScrollThrottle = 1;
|
var editScrollThrottle = 2;
|
||||||
var viewScrollThrottle = 10;
|
var viewScrollThrottle = 10;
|
||||||
var buildMapThrottle = 100;
|
var buildMapThrottle = 100;
|
||||||
|
|
||||||
var viewScrolling = false;
|
var viewScrolling = false;
|
||||||
var viewScrollingDelay = 200;
|
var viewScrollingDebounce = 200;
|
||||||
var viewScrollingTimer = null;
|
|
||||||
|
|
||||||
var editScrolling = false;
|
var editScrolling = false;
|
||||||
var editScrollingDelay = 100;
|
var editScrollingDebounce = 200;
|
||||||
var editScrollingTimer = null;
|
|
||||||
|
|
||||||
if (editor.getOption('scrollbarStyle') === 'native') {
|
if (editor.getOption('scrollbarStyle') === 'native') {
|
||||||
ui.area.codemirrorScroll.on('scroll', _.throttle(syncScrollToView, editScrollThrottle));
|
ui.area.codemirrorScroll.on('scroll', _.throttle(syncScrollToView, editScrollThrottle));
|
||||||
|
@ -145,7 +143,7 @@ var buildMap = _.throttle(buildMapInner, buildMapThrottle);
|
||||||
// Build offsets for each line (lines can be wrapped)
|
// Build offsets for each line (lines can be wrapped)
|
||||||
// That's a bit dirty to process each line everytime, but ok for demo.
|
// That's a bit dirty to process each line everytime, but ok for demo.
|
||||||
// Optimizations are required only for big texts.
|
// Optimizations are required only for big texts.
|
||||||
function buildMapInner(syncBack) {
|
function buildMapInner(callback) {
|
||||||
var i, offset, nonEmptyList, pos, a, b, _lineHeightMap, linesCount,
|
var i, offset, nonEmptyList, pos, a, b, _lineHeightMap, linesCount,
|
||||||
acc, _scrollMap;
|
acc, _scrollMap;
|
||||||
|
|
||||||
|
@ -217,12 +215,15 @@ function buildMapInner(syncBack) {
|
||||||
scrollMap = _scrollMap;
|
scrollMap = _scrollMap;
|
||||||
lineHeightMap = _lineHeightMap;
|
lineHeightMap = _lineHeightMap;
|
||||||
|
|
||||||
if (loaded && syncBack) {
|
if (loaded && callback) callback();
|
||||||
syncScrollToView();
|
|
||||||
syncScrollToEdit();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sync view scroll progress to edit
|
||||||
|
var viewScrollingTimeout = _.debounce(viewScrollingTimeoutInner, viewScrollingDebounce);
|
||||||
|
|
||||||
|
function viewScrollingTimeoutInner() {
|
||||||
|
viewScrolling = false;
|
||||||
|
}
|
||||||
|
|
||||||
function syncScrollToEdit(e) {
|
function syncScrollToEdit(e) {
|
||||||
if (currentMode != modeType.both || !syncscroll) return;
|
if (currentMode != modeType.both || !syncscroll) return;
|
||||||
|
@ -235,7 +236,7 @@ function syncScrollToEdit(e) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!scrollMap || !lineHeightMap) {
|
if (!scrollMap || !lineHeightMap) {
|
||||||
buildMap(true);
|
buildMap(syncScrollToEdit);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (editScrolling) return;
|
if (editScrolling) return;
|
||||||
|
@ -272,21 +273,30 @@ function syncScrollToEdit(e) {
|
||||||
if (scrollInfo.height > scrollInfo.clientHeight && scrollTop >= preLastLinePos) {
|
if (scrollInfo.height > scrollInfo.clientHeight && scrollTop >= preLastLinePos) {
|
||||||
posTo = preLastLineHeight;
|
posTo = preLastLineHeight;
|
||||||
topDiffPercent = (scrollTop - preLastLinePos) / (viewBottom - preLastLinePos);
|
topDiffPercent = (scrollTop - preLastLinePos) / (viewBottom - preLastLinePos);
|
||||||
posToNextDiff = Math.ceil(textHeight * topDiffPercent);
|
posToNextDiff = textHeight * topDiffPercent;
|
||||||
|
posTo += Math.floor(posToNextDiff);
|
||||||
} else {
|
} else {
|
||||||
posTo = lineNo * textHeight;
|
posTo = lineNo * textHeight;
|
||||||
topDiffPercent = (scrollTop - scrollMap[lineNo]) / (scrollMap[lineNo + lineDiff] - scrollMap[lineNo]);
|
topDiffPercent = (scrollTop - scrollMap[lineNo]) / (scrollMap[lineNo + lineDiff] - scrollMap[lineNo]);
|
||||||
posToNextDiff = Math.ceil(textHeight * lineDiff * topDiffPercent);
|
posToNextDiff = textHeight * lineDiff * topDiffPercent;
|
||||||
|
posTo += Math.floor(posToNextDiff);
|
||||||
}
|
}
|
||||||
|
|
||||||
editor.scrollTo(0, posTo + posToNextDiff);
|
var posDiff = Math.abs(scrollInfo.top - posTo);
|
||||||
preventSyncScrollToView = true;
|
var duration = posDiff / 50;
|
||||||
|
ui.area.codemirrorScroll.stop(true, true).animate({
|
||||||
|
scrollTop: posTo
|
||||||
|
}, duration >= 100 ? duration : 100, "linear");
|
||||||
|
|
||||||
viewScrolling = true;
|
viewScrolling = true;
|
||||||
clearTimeout(viewScrollingTimer);
|
viewScrollingTimeout();
|
||||||
viewScrollingTimer = setTimeout(function () {
|
}
|
||||||
viewScrolling = false;
|
|
||||||
}, viewScrollingDelay);
|
// sync edit scroll progress to view
|
||||||
|
var editScrollingTimeout = _.debounce(editScrollingTimeoutInner, editScrollingDebounce);
|
||||||
|
|
||||||
|
function editScrollingTimeoutInner() {
|
||||||
|
editScrolling = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function syncScrollToView(event, _lineNo) {
|
function syncScrollToView(event, _lineNo) {
|
||||||
|
@ -300,7 +310,7 @@ function syncScrollToView(event, _lineNo) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!scrollMap || !lineHeightMap) {
|
if (!scrollMap || !lineHeightMap) {
|
||||||
buildMap(true);
|
buildMap(syncScrollToView);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (viewScrolling) return;
|
if (viewScrolling) return;
|
||||||
|
@ -328,12 +338,12 @@ function syncScrollToView(event, _lineNo) {
|
||||||
posTo = scrollMap[lineHeightMap[_lineNo]];
|
posTo = scrollMap[lineHeightMap[_lineNo]];
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.area.view.stop(true, true).scrollTop(posTo);
|
var posDiff = Math.abs(ui.area.view.scrollTop() - posTo);
|
||||||
preventSyncScrollToEdit = true;
|
var duration = posDiff / 50;
|
||||||
|
ui.area.view.stop(true, true).animate({
|
||||||
|
scrollTop: posTo
|
||||||
|
}, duration >= 100 ? duration : 100, "linear");
|
||||||
|
|
||||||
editScrolling = true;
|
editScrolling = true;
|
||||||
clearTimeout(editScrollingTimer);
|
editScrollingTimeout();
|
||||||
editScrollingTimer = setTimeout(function () {
|
|
||||||
editScrolling = false;
|
|
||||||
}, editScrollingDelay);
|
|
||||||
}
|
}
|
Loading…
Reference in a new issue