/* DokuWiki MoaiEditor Watcher.js file Version : 0.5a (May 6, 2026) Author : MoaiTools License : GPL 3 (http://www.gnu.org/licenses/gpl.html) */ /* This class watches for changes lines in the textarea contents. It detects deleted and inserted lines. An edited or replaced line is interpreted as a deletion folowed by an insertion. Handling textarea input events and toolbar button clicks might not be sufficient to detect changes. Javascript can change the text without generating any events, so unknown plugins might bypass this detection. This is why we also check regularly if the text has changed even if no user input event has been detected. This process is not very cpu intensive even when the page is huge (it takes less than 1 ms on a 400 Kb page, which is larger than the largest english wikipedia page). We have a timer class to make these background checks more often if the user has interacted recently and less often otherwise (to minimize CPU usage when there is no interaction). */ MoaiEditor.WatchTextChanges = class { constructor(outer) { // Arguments this.outer = outer; // Objects this.timer = new MoaiEditor.Timer(); // Intervals this.interval = setInterval(this.onInterval.bind(this), 200); } // ──────────────────────────────────── onInterval() { // Return if the parent is disabled if (!this.outer.enabled) return; // Return if not enough time has elapsed if (!this.timer.due()) return; // Return if the editor is not enabled and ready if (!moaiEditor.layoutReady) return; // Check for text changes this.checkTextChange(); // Optional debug actions this.debug(); } // ──────────────────────────────────── onInput() { this.timer.resetPeriod(); this.timer.restart(); this.checkTextChange(); } // ──────────────────────────────────── getTextLines() { return moaiEditor.layout.textarea.value.split("\n"); } // ──────────────────────────────────── checkTextChange() { // Init var i; const start = Date.now(); var previous = this.lines; var current = this.getTextLines(); // Get shift (delta) const shift = current.length - previous.length; // Walk lines form top to bottom for (i=0; i this.period) { this.restart(); return true; } return false; } set (period) { this.period = Math.round(period); } setMin (period) { this.minPeriod = Math.round(period); } setMax (period) { this.minPeriod = Math.round(period); } setInc (inc) { this.inc = inc; } resetPeriod () { this.period = this.minPeriod; } debug () { const line = document.querySelector("#moai__debug div:nth-child(1)"); if (!line) return; const elapsed = ''+(Date.now()-this.last).toString().padStart(4," ")+''; const text = "TIMER: "+elapsed+" period:"+this.period+" min:"+this.minPeriod+" max:"+this.maxPeriod; line.innerHTML = text; line.title = 'Texarea '; } }; // End Class