1/* DokuWiki MoaiEditor Cm_scroll.js file 2 Version : 0.5 (May 5, 2026) 3 Author : MoaiTools <info@moaitools.org> 4 License : GPL 3 (http://www.gnu.org/licenses/gpl.html) */ 5 6/* This class implements the 'scroll.max', 'scroll.top' and 'scroll.smooth' 7 getters and setters required for every editor. 8 9 It also updates the vertical position of currently rendered lines to make 10 sure we work with precise values. We use an interval to throttle this process. 11 12 This is needed because CodeMirror will report inaccurate line positions when 13 they have not been rendered yet. So scrolling close to that part of the document 14 is required before an accurate value can be obtained. 15 16 If not corrected, this aproximation error adds up in large documents, which 17 results in a really bad scroll synchronization in lower parts of the page. 18*/ 19MoaiEditor.CodemirrorScroll = class { 20 21 constructor(outer) { 22 23 // Arguments 24 this.outer = outer; 25 26 // Variables 27 this.smoothvalue = false; 28 this.range = null; // {from, to} or null 29 30 // Interval 31 this.interval = setInterval(this.onInterval.bind(this), 250); 32 } 33 // ──────────────────────────────────── 34 get max() { 35 // Return the maximum scroll possible 36 const info = this.outer.editor.getScrollInfo(); 37 const height = info.height; // size of the scrollable area 38 const visHeight = info.clientHeight; // size of the visible area (minus scrollbars) 39 return Math.abs(height-visHeight); 40 } 41 get height() { 42 // Return the height of the scrollable area 43 return this.outer.editor.getScrollInfo().height; 44 } 45 // ──────────────────────────────────── 46 get top() { 47 return this.outer.editor.getScrollInfo().top; 48 } 49 set top(value) { 50 this.outer.scroller.scrollTop = value; 51 //this.outer.editor.scrollTo(null, value); 52 } 53 // ──────────────────────────────────── 54 get smooth() { 55 return this.smoothvalue; 56 } 57 set smooth(boolean) { 58 var value = 'auto'; 59 if (boolean) 60 value = 'smooth'; 61 this.smoothvalue = boolean; 62 this.outer.scroller.style.scrollBehavior = value; 63 } 64 // ──────────────────────────────────── 65 onScroll() { 66 const vp = this.outer.editor.getViewport(); 67 if (this.range === null) 68 this.range = {from: vp.from, to: vp.to}; 69 this.range.from = Math.min(this.range.from, vp.from); 70 this.range.to = Math.max(this.range.to, vp.to); 71 this.debugLine(); 72 } 73 onInterval() { 74 if (this.range !== null) 75 moaiEditor.matches.recalcScrollPoints(this.range); 76 this.range = null; 77 } 78 // ──────────────────────────────────── 79 debugLine() { 80 // Exit if debugline is not enabled 81 const line = document.querySelector("#moai__debug div:nth-child(2)"); 82 if (!line) return; 83 // Debug line 84 const info = this.outer.editor.getScrollInfo(); 85 const scroll = Math.floor(info.top); 86 const height = info.height; 87 const viewport = info.clientHeight; 88 const text = "scroll:"+scroll+" h:"+height+" vp:"+viewport+" max:"+this.max; 89 line.textContent = text; 90 } 91 92}; // End Class 93 94