From 0f4fd999ee974081eade8093aa7628edea2e1469 Mon Sep 17 00:00:00 2001 From: nightwing Date: Thu, 28 Mar 2013 14:10:12 +0400 Subject: [PATCH 1/3] allow delete command only after opening contextmenu this will break delete from browser edit menu, but it is not as important as ime textinput fixes #1325 --- lib/ace/keyboard/textinput.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/ace/keyboard/textinput.js b/lib/ace/keyboard/textinput.js index 049ddca4..6bb2469a 100644 --- a/lib/ace/keyboard/textinput.js +++ b/lib/ace/keyboard/textinput.js @@ -198,6 +198,7 @@ var TextInput = function(parentNode, host) { var inputHandler = null; this.setInputHandler = function(cb) {inputHandler = cb}; this.getInputHandler = function() {return inputHandler}; + var afterContextMenu = false; var sendText = function(data) { if (inputHandler) { @@ -210,7 +211,7 @@ var TextInput = function(parentNode, host) { host.onPaste(data); pasted = false; } else if (data == PLACEHOLDER[0]) { - if (Date.now() - lastCompositionTime > 100) + if (afterContextMenu) host.execCommand("del", {source: "ace"}); } else { if (data.substring(0, 2) == PLACEHOLDER) @@ -226,6 +227,8 @@ var TextInput = function(parentNode, host) { if (data) host.onTextInput(data); } + if (afterContextMenu) + afterContextMenu = false; }; var onInput = function(e) { if (inCompostion) @@ -356,11 +359,9 @@ var TextInput = function(parentNode, host) { host.onCompositionUpdate(text.value); }; - var lastCompositionTime = -1; var onCompositionEnd = function(e) { inCompostion = false; host.onCompositionEnd(); - lastCompositionTime = Date.now(); }; var syncComposition = lang.delayedCall(onCompositionUpdate, 50); @@ -378,6 +379,7 @@ var TextInput = function(parentNode, host) { }; this.onContextMenu = function(e) { + afterContextMenu = true; if (!tempStyle) tempStyle = text.style.cssText; From b0a43790b4589bdc00fc239a91ca7ebb57e41219 Mon Sep 17 00:00:00 2001 From: nightwing Date: Thu, 28 Mar 2013 21:06:48 +0400 Subject: [PATCH 2/3] do not overlay editor text when ime is active fixes #1112 --- lib/ace/css/editor.css | 5 ++- lib/ace/edit_session.js | 8 +++++ lib/ace/keyboard/textinput.js | 63 +++++++++++++++++++++++++++-------- lib/ace/virtual_renderer.js | 9 +++-- 4 files changed, 65 insertions(+), 20 deletions(-) diff --git a/lib/ace/css/editor.css b/lib/ace/css/editor.css index 81f8fbe6..834ca301 100644 --- a/lib/ace/css/editor.css +++ b/lib/ace/css/editor.css @@ -101,6 +101,8 @@ outline: none; overflow: hidden; font: inherit; + padding: 0 1px; + margin: 0 -1px; } .ace_text-input.ace_composition { @@ -108,9 +110,6 @@ color: #111; z-index: 1000; opacity: 1; - border: solid lightgray 1px; - margin: -1px; - padding: 0 1px; } .ace_layer { diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index f6744907..a58a8a5b 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -417,6 +417,14 @@ var EditSession = function(text, mode) { } }; + /** + * starts a new group in undo history + **/ + this.markUndoGroup = function() { + if (this.$syncInformUndoManager) + this.$syncInformUndoManager(); + }; + this.$defaultUndoManager = { undo: function() {}, redo: function() {}, diff --git a/lib/ace/keyboard/textinput.js b/lib/ace/keyboard/textinput.js index 6bb2469a..3f631001 100644 --- a/lib/ace/keyboard/textinput.js +++ b/lib/ace/keyboard/textinput.js @@ -59,7 +59,7 @@ var TextInput = function(parentNode, host) { var cut = false; var copied = false; var pasted = false; - var inCompostion = false; + var inComposition = false; var tempStyle = ''; var isSelectionEmpty = true; @@ -87,14 +87,14 @@ var TextInput = function(parentNode, host) { isFocused && resetSelection(isSelectionEmpty); }); var syncValue = lang.delayedCall(function() { - if (!inCompostion) { + if (!inComposition) { text.value = PLACEHOLDER; isFocused && resetSelection(); } }); function resetSelection(isEmpty) { - if (inCompostion) + if (inComposition) return; if (inputHandler) { selectionStart = 0; @@ -110,7 +110,7 @@ var TextInput = function(parentNode, host) { } function resetValue() { - if (inCompostion) + if (inComposition) return; text.value = PLACEHOLDER; //http://code.google.com/p/chromium/issues/detail?id=76516 @@ -156,7 +156,7 @@ var TextInput = function(parentNode, host) { if (inPropertyChange) return; var data = text.value; - if (inCompostion || !data || data == PLACEHOLDER) + if (inComposition || !data || data == PLACEHOLDER) return; // can happen either after delete or during insert operation if (e && data == PLACEHOLDER[0]) @@ -173,12 +173,12 @@ var TextInput = function(parentNode, host) { var keytable = { 13:1, 27:1 }; event.addListener(text, "keyup", function (e) { - if (inCompostion && (!text.value || keytable[e.keyCode])) + if (inComposition && (!text.value || keytable[e.keyCode])) setTimeout(onCompositionEnd, 0); if ((text.value.charCodeAt(0)||0) < 129) { return; } - inCompostion ? onCompositionUpdate() : onCompositionStart(); + inComposition ? onCompositionUpdate() : onCompositionStart(); }); } @@ -231,7 +231,7 @@ var TextInput = function(parentNode, host) { afterContextMenu = false; }; var onInput = function(e) { - if (inCompostion) + if (inComposition) return; var data = text.value; sendText(data); @@ -349,20 +349,55 @@ var TextInput = function(parentNode, host) { // COMPOSITION var onCompositionStart = function(e) { - inCompostion = true; + inComposition = {}; host.onCompositionStart(); setTimeout(onCompositionUpdate, 0); + host.on("mousedown", onCompositionEnd); + if (!host.selection.isEmpty()) { + host.insert(""); + host.session.markUndoGroup(); + host.selection.clearSelection(); + } + host.session.markUndoGroup(); }; var onCompositionUpdate = function() { - if (!inCompostion) return; + if (!inComposition) return; host.onCompositionUpdate(text.value); + if (inComposition.lastValue) + host.undo(); + inComposition.lastValue = text.value.replace(/\x01/g, "") + if (inComposition.lastValue) { + var r = host.selection.getRange(); + host.insert(inComposition.lastValue); + host.session.markUndoGroup(); + inComposition.range = host.selection.getRange(); + host.selection.setRange(r); + host.selection.clearSelection(); + } + }; + + var onCompositionEnd = function(e) { + var c = inComposition; + inComposition = false; + inputHandler = function compositionInputHandler(str) { + str = str.replace(/\x01/g, ""); + if (str == c.lastValue) + return ""; + if (!str) { + if (c.lastValue) + host.undo(); + } + return str; + } + host.onCompositionEnd(); + host.removeListener("mousedown", onCompositionEnd); + if (e.type == "compositionend") { + host.selection.setRange(c.range); + } }; - var onCompositionEnd = function(e) { - inCompostion = false; - host.onCompositionEnd(); - }; + var syncComposition = lang.delayedCall(onCompositionUpdate, 50); diff --git a/lib/ace/virtual_renderer.js b/lib/ace/virtual_renderer.js index a76ec222..f15afb3d 100644 --- a/lib/ace/virtual_renderer.js +++ b/lib/ace/virtual_renderer.js @@ -538,13 +538,16 @@ var VirtualRenderer = function(container, theme) { var posLeft = this.$cursorLayer.$pixelPos.left; posTop -= config.offset; - if (posTop < 0 || posTop > config.height - this.lineHeight) + var h = this.lineHeight; + if (posTop < 0 || posTop > config.height - h) return; var w = this.characterWidth; if (this.$composition) { var val = this.textarea.value.replace(/^\x01+/, ""); w *= this.session.$getStringScreenWidth(val)[0]; + h += 2; + posTop -= 1; } posLeft -= this.scrollLeft; if (posLeft > this.$size.scrollerWidth - w) @@ -552,10 +555,10 @@ var VirtualRenderer = function(container, theme) { posLeft -= this.scrollBar.width; - this.textarea.style.height = this.lineHeight + "px"; + this.textarea.style.height = h + "px"; this.textarea.style.width = w + "px"; this.textarea.style.right = Math.max(0, this.$size.scrollerWidth - posLeft - w) + "px"; - this.textarea.style.bottom = Math.max(0, this.$size.height - posTop - this.lineHeight) + "px"; + this.textarea.style.bottom = Math.max(0, this.$size.height - posTop - h) + "px"; }; /** From bf34500927a2a1c4a2c7593660a1d6a5581d7834 Mon Sep 17 00:00:00 2001 From: nightwing Date: Thu, 28 Mar 2013 21:24:52 +0400 Subject: [PATCH 3/3] fix #906 can't input chinese in ie9 --- lib/ace/keyboard/textinput.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/ace/keyboard/textinput.js b/lib/ace/keyboard/textinput.js index 3f631001..591c6e31 100644 --- a/lib/ace/keyboard/textinput.js +++ b/lib/ace/keyboard/textinput.js @@ -380,7 +380,13 @@ var TextInput = function(parentNode, host) { var onCompositionEnd = function(e) { var c = inComposition; inComposition = false; + var timer = setTimeout(function() { + var str = text.value.replace(/\x01/g, ""); + if (!inComposition && str == c.lastValue) + resetValue(); + }); inputHandler = function compositionInputHandler(str) { + clearTimeout(timer); str = str.replace(/\x01/g, ""); if (str == c.lastValue) return "";