Skip to content

Commit bf1dc23

Browse files
committed
Add support of sync scrolling to edit area
1 parent f3418a6 commit bf1dc23

2 files changed

Lines changed: 81 additions & 35 deletions

File tree

public/js/index.js

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -743,6 +743,7 @@ function windowResizeInner(callback) {
743743
if (editor.getOption('scrollbarStyle') === 'native') {
744744
clearMap();
745745
syncScrollToView();
746+
syncScrollToEdit();
746747
updateScrollspy();
747748
if (callback && typeof callback === 'function')
748749
callback();
@@ -752,6 +753,7 @@ function windowResizeInner(callback) {
752753
setTimeout(function () {
753754
clearMap();
754755
syncScrollToView();
756+
syncScrollToEdit();
755757
editor.setOption('viewportMargin', viewportMargin);
756758
//add or update user cursors
757759
for (var i = 0; i < onlineUsers.length; i++) {
@@ -822,7 +824,6 @@ function checkEditorScrollbar() {
822824
// workaround simple scroll bar knob
823825
// will get wrong position when editor height changed
824826
var scrollInfo = editor.getScrollInfo();
825-
if (!preventSyncScroll) preventSyncScroll = true;
826827
editor.scrollTo(null, scrollInfo.top - 1);
827828
editor.scrollTo(null, scrollInfo.top);
828829
}
@@ -1027,15 +1028,6 @@ var unlockNavbar = _.debounce(function () {
10271028
$('.navbar').removeClass('locked');
10281029
}, 200);
10291030

1030-
function syncScrollToEdit() {
1031-
if (!scrollMap || !lineHeightMap)
1032-
buildMapInner();
1033-
var scrollMapNearest = closestIndex(scrollMap, lastInfo.view.scroll.top);
1034-
var lineHeightMapNearest = closestIndex(lineHeightMap, scrollMapNearest);
1035-
var height = lineHeightMapNearest * defaultTextHeight;
1036-
editor.scrollTo(null, height);
1037-
}
1038-
10391031
function closestIndex(arr, closestTo) {
10401032
var closest = Math.max.apply(null, arr); //Get the highest number in arr in case it match nothing.
10411033
var index = 0;
@@ -2422,11 +2414,9 @@ editor.on('beforeChange', function (cm, change) {
24222414
cmClient.editorAdapter.ignoreNextChange = true;
24232415
});
24242416
editor.on('cut', function () {
2425-
preventSyncScroll = 3;
24262417
windowResize(); //workaround for scrollMap
24272418
});
24282419
editor.on('paste', function () {
2429-
preventSyncScroll = 3;
24302420
windowResize(); //workaround for scrollMap
24312421
});
24322422
editor.on('changes', function (cm, changes) {
@@ -2596,6 +2586,8 @@ function updateViewInner() {
25962586
clearMap();
25972587
//buildMap();
25982588
updateTitleReminder();
2589+
syncScrollToView();
2590+
syncScrollToEdit();
25992591
}
26002592

26012593
var updateHistoryDebounce = 600;

public/js/syncscroll.js

Lines changed: 77 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -107,28 +107,89 @@ md.use(window.markdownitContainer, 'danger', { render: renderContainer });
107107

108108
var preventSyncScroll = false;
109109

110-
//var editorScrollThrottle = 100;
110+
var editScrollThrottle = 1;
111+
var viewScrollThrottle = 20;
111112
var buildMapThrottle = 100;
112113

113114
var viewScrolling = false;
114115
var viewScrollingDelay = 200;
115116
var viewScrollingTimer = null;
116117

117-
//editor.on('scroll', _.throttle(syncScrollToView, editorScrollThrottle));
118+
var editScrolling = false;
119+
var editScrollingDelay = 100;
120+
var editScrollingTimer = null;
121+
118122
if (editor.getOption('scrollbarStyle') === 'native') {
119-
ui.area.codemirrorScroll.on('scroll', syncScrollToView);
123+
ui.area.codemirrorScroll.on('scroll', _.throttle(syncScrollToView, editScrollThrottle));
120124
} else {
121-
editor.on('scroll', syncScrollToView);
125+
editor.on('scroll', _.throttle(syncScrollToView, editScrollThrottle));
122126
}
123-
ui.area.view.on('scroll', function () {
127+
ui.area.view.on('scroll', _.throttle(syncScrollToEdit, viewScrollThrottle));
128+
129+
var preventViewScroll = false;
130+
131+
function syncScrollToEdit(e) {
132+
if (currentMode != modeType.both) return;
133+
if (preventViewScroll) {
134+
if (typeof preventViewScroll === 'number') {
135+
preventViewScroll--;
136+
} else {
137+
preventViewScroll = false;
138+
}
139+
return;
140+
}
141+
if (!scrollMap || !lineHeightMap) {
142+
buildMap(true);
143+
return;
144+
}
145+
if (editScrolling) return;
146+
var scrollTop = ui.area.view[0].scrollTop;
147+
var lineIndex = 0;
148+
for (var i = 0, l = scrollMap.length; i < l; i++) {
149+
if (scrollMap[i] > scrollTop) {
150+
break;
151+
} else {
152+
lineIndex = i;
153+
}
154+
}
155+
var lineNo = 0;
156+
var lineDiff = 0;
157+
for (var i = 0, l = lineHeightMap.length; i < l; i++) {
158+
if (lineHeightMap[i] > lineIndex) {
159+
break;
160+
} else {
161+
lineNo = lineHeightMap[i];
162+
lineDiff = lineHeightMap[i + 1] - lineNo;
163+
}
164+
}
165+
166+
var scrollInfo = editor.getScrollInfo();
167+
var textHeight = editor.defaultTextHeight();
168+
var posTo = 0;
169+
var topDiffPercent = 0;
170+
var posToNextDiff = 0;
171+
var preLastLineHeight = scrollInfo.height - scrollInfo.clientHeight - textHeight;
172+
var preLastLineNo = Math.round(preLastLineHeight / textHeight);
173+
174+
if (scrollInfo.height > scrollInfo.clientHeight && lineNo >= preLastLineNo) {
175+
posTo = preLastLineHeight;
176+
topDiffPercent = (scrollTop - scrollMap[preLastLineNo]) / (viewBottom - scrollMap[preLastLineNo]);
177+
posToNextDiff = Math.ceil(textHeight * topDiffPercent);
178+
} else {
179+
posTo = lineNo * textHeight;
180+
topDiffPercent = (scrollTop - scrollMap[lineNo]) / (scrollMap[lineNo + lineDiff] - scrollMap[lineNo]);
181+
posToNextDiff = Math.ceil(textHeight * lineDiff * topDiffPercent);
182+
}
183+
184+
editor.scrollTo(0, posTo + posToNextDiff);
185+
preventSyncScroll = true;
186+
124187
viewScrolling = true;
125188
clearTimeout(viewScrollingTimer);
126189
viewScrollingTimer = setTimeout(function () {
127190
viewScrolling = false;
128191
}, viewScrollingDelay);
129-
});
130-
//editor.on('scroll', _.debounce(syncScrollToView, syncScrollDelay));
131-
//ui.area.view.on('scroll', _.debounce(syncScrollToEdit, 50));
192+
}
132193

133194
var scrollMap, lineHeightMap, viewTop, viewBottom;
134195

@@ -291,19 +352,12 @@ function syncScrollToView(event, _lineNo) {
291352
if (viewScrolling) return;
292353
posTo = scrollMap[lineHeightMap[_lineNo]];
293354
}
294-
var posDiff = Math.abs(ui.area.view.scrollTop() - posTo);
295-
var duration = posDiff / 50;
296-
ui.area.view.stop(true, true).animate({
297-
scrollTop: posTo
298-
}, duration >= 100 ? duration : 100, "linear");
299-
/*
300-
if (posDiff > scrollInfo.clientHeight / 5) {
301-
var duration = posDiff / 50;
302-
ui.area.view.stop(true, true).animate({
303-
scrollTop: posTo
304-
}, duration >= 100 ? duration : 100, "linear");
305-
} else {
306-
ui.area.view.stop(true, true).scrollTop(posTo);
307-
}
308-
*/
355+
ui.area.view.stop(true, true).scrollTop(posTo);
356+
preventViewScroll = true;
357+
358+
editScrolling = true;
359+
clearTimeout(editScrollingTimer);
360+
editScrollingTimer = setTimeout(function () {
361+
editScrolling = false;
362+
}, editScrollingDelay);
309363
}

0 commit comments

Comments
 (0)