From f51433072941d6c35916c60414037d9d1582aa6a Mon Sep 17 00:00:00 2001 From: nightwing Date: Sat, 2 Mar 2013 17:54:21 +0400 Subject: [PATCH] add extension for enabling spellchecking from contextmenu --- lib/ace/config.js | 4 +-- lib/ace/ext/spellcheck.js | 58 +++++++++++++++++++++++++++++++++++ lib/ace/keyboard/textinput.js | 32 +++++++++++++------ lib/ace/virtual_renderer.js | 4 +-- 4 files changed, 84 insertions(+), 14 deletions(-) create mode 100644 lib/ace/ext/spellcheck.js diff --git a/lib/ace/config.js b/lib/ace/config.js index c617959d..4a7dc286 100644 --- a/lib/ace/config.js +++ b/lib/ace/config.js @@ -103,12 +103,12 @@ exports.loadModule = function(moduleName, onLoad) { module = require(moduleName); } catch (e) {}; if (module) - return onLoad(module); + return onLoad && onLoad(module); var afterLoad = function() { require([moduleName], function(module) { exports._emit("load.module", {name: moduleName, module: module}); - onLoad(module); + onLoad && onLoad(module); }); }; diff --git a/lib/ace/ext/spellcheck.js b/lib/ace/ext/spellcheck.js new file mode 100644 index 00000000..23ac3c31 --- /dev/null +++ b/lib/ace/ext/spellcheck.js @@ -0,0 +1,58 @@ +define(function(require, exports, module) { +"use strict"; + +exports.contextMenuHandler = function(e){ + var host = e.target; + var text = host.textInput.getElement(); + if (!host.selection.isEmpty()) + return; + var c = host.getCursorPosition(); + var r = host.session.getWordRange(c.row, c.column); + var w = host.session.getTextRange(r); + + host.session.tokenRe.lastIndex = 0; + if (!host.session.tokenRe.test(w)) + return; + var PLACEHOLDER = "\x01\x01"; + var value = w + " " + PLACEHOLDER; + text.value = value; + text.setSelectionRange(w.length + 1, w.length + 1); + text.setSelectionRange(0, 0); + + host.textInput.setInputHandler(function(newVal) { + if (newVal == value) + return ''; + if (newVal.lastIndexOf(value) == newVal.length - value.length) + return newVal.slice(0, -value.length); + if (newVal.indexOf(value) === 0) + return newVal.slice(value.length); + if (newVal.slice(-2) == PLACEHOLDER) { + var val = newVal.slice(0, -2); + if (val.slice(-1) == " ") { + val = val.slice(0, -1); + host.session.replace(r, val); + return ""; + } + } + + return newVal; + }); +}; +// todo support highlighting with typo.js +var Editor = require("../editor").Editor; +require("../config").defineOptions(Editor.prototype, "editor", { + spellcheck: { + set: function(val) { + var text = this.textInput.getElement(); + text.spellcheck = !!val; + if (!val) + this.removeListener("nativecontextmenu", exports.contextMenuHandler); + else + this.on("nativecontextmenu", exports.contextMenuHandler); + }, + value: true + } +}); + +}); + diff --git a/lib/ace/keyboard/textinput.js b/lib/ace/keyboard/textinput.js index 397a0917..e8f3ed29 100644 --- a/lib/ace/keyboard/textinput.js +++ b/lib/ace/keyboard/textinput.js @@ -96,8 +96,13 @@ var TextInput = function(parentNode, host) { function resetSelection(isEmpty) { if (inCompostion) return; - var selectionStart = isEmpty ? 2 : 1; - var selectionEnd = 2; + if (inputHandler) { + selectionStart = 0 + selectionEnd = isEmpty == false ? text.value.length - 1 : 0; + } else { + var selectionStart = isEmpty ? 2 : 1; + var selectionEnd = 2; + } // on firefox this throws if textarea is hidden try { text.setSelectionRange(selectionStart, selectionEnd); @@ -180,19 +185,25 @@ var TextInput = function(parentNode, host) { var onSelect = function(e) { if (cut) { cut = false; - return; - } - if (copied) { + } else if (copied) { copied = false; - return; - } - if (isAllSelected(text)) { + } else if (isAllSelected(text)) { host.selectAll(); resetSelection(); + } else if (inputHandler) { + resetSelection(); } }; + var inputHandler = null; + this.setInputHandler = function(onInput) {inputHandler = onInput}; + this.getInputHandler = function() {return inputHandler}; + var sendText = function(data) { + if (inputHandler) { + data = inputHandler(data); + inputHandler = null; + } if (pasted) { resetSelection(); if (data) @@ -377,10 +388,11 @@ var TextInput = function(parentNode, host) { var style = dom.computedStyle(host.container); var top = rect.top + (parseInt(style.borderTopWidth) || 0); var left = rect.left + (parseInt(rect.borderLeftWidth) || 0); + var maxTop = rect.bottom - top - text.clientHeight; var move = function(e) { text.style.left = e.clientX - left - 2 + "px"; - text.style.top = e.clientY - top - 2 + "px"; - }; + text.style.top = Math.min(e.clientY - top - 2, maxTop) + "px"; + }; move(e); if (e.type != "mousedown") diff --git a/lib/ace/virtual_renderer.js b/lib/ace/virtual_renderer.js index 719df69a..0de955cb 100644 --- a/lib/ace/virtual_renderer.js +++ b/lib/ace/virtual_renderer.js @@ -549,8 +549,8 @@ var VirtualRenderer = function(container, theme) { this.textarea.style.height = this.lineHeight + "px"; this.textarea.style.width = w + "px"; - this.textarea.style.right = this.$size.scrollerWidth - posLeft - w + "px"; - this.textarea.style.bottom = this.$size.height - posTop - this.lineHeight + "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"; }; /**