From 1a5fcb72d3f08acba0cc4b08fd20509f17fdbb8f Mon Sep 17 00:00:00 2001 From: Claas Augner Date: Wed, 28 Dec 2016 22:23:50 +0100 Subject: [PATCH] FEATURE: Preserve cursor in editor upload --- .../discourse/components/d-editor.js.es6 | 40 +++++++++++++++++-- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/app/assets/javascripts/discourse/components/d-editor.js.es6 b/app/assets/javascripts/discourse/components/d-editor.js.es6 index f9fc95e31fe..52e35b8b31e 100644 --- a/app/assets/javascripts/discourse/components/d-editor.js.es6 +++ b/app/assets/javascripts/discourse/components/d-editor.js.es6 @@ -525,11 +525,43 @@ export default Ember.Component.extend({ _replaceText(oldVal, newVal) { const val = this.get('value'); - const loc = val.indexOf(oldVal); - if (loc !== -1) { - this.set('value', val.replace(oldVal, newVal)); - this._selectText(loc + newVal.length, 0); + const needleStart = val.indexOf(oldVal); + + if (needleStart === -1) { + // Nothing to replace. + return; } + + const textarea = this.$('textarea.d-editor-input')[0]; + + // Remember cursor/selection. + const selectionStart = textarea.selectionStart; + const selectionEnd = textarea.selectionEnd; + const needleEnd = needleStart + oldValue.length; + const replacementEnd = needleStart + newVal.length; + + // Replace value (side effect: cursor at end). + this.set('value', val.replace(oldVal, newVal)); + + // Determine cursor/selection. + const newSelectionStart, newSelectionEnd; + if (selectionEnd <= needleEnd) { + // Selection before needle. + newSelectionStart = selectionStart; + newSelectionEnd = selectionEnd; + } else if (selectionStart < needleEnd) { + // Selection within needle. + newSelectionStart = replacementEnd; + newSelectionEnd = replacementEnd; + } else { + // Selection behind needle. + const lengthDiff = replacementEnd - needleStart; + newSelectionStart = selectionStart + lengthDiff; + newSelectionEnd = selectionEnd + lengthDiff; + } + + // Restore cursor. + this._selectText(newSelectionStart, newSelectionEnd - newSelectionStart); }, _addText(sel, text) {