Merge pull request #1288 from ajaxorg/spellcheck

Add extension for enabling spellchecking from contextmenu
This commit is contained in:
Lennart Kats 2013-03-12 08:35:29 -07:00
commit 505d089767
4 changed files with 100 additions and 18 deletions

View file

@ -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);
});
};

68
lib/ace/ext/spellcheck.js Normal file
View file

@ -0,0 +1,68 @@
define(function(require, exports, module) {
"use strict";
var event = require("../lib/event");
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);
var afterKeydown = false;
event.addListener(text, "keydown", function onKeydown() {
event.removeListener(text, "keydown", onKeydown);
afterKeydown = true;
});
host.textInput.setInputHandler(function(newVal) {
console.log(newVal , value, text.selectionStart, text.selectionEnd)
if (newVal == value)
return '';
if (newVal.lastIndexOf(value, 0) === 0)
return newVal.slice(value.length);
if (newVal.substr(text.selectionEnd) == value)
return newVal.slice(0, -value.length);
if (newVal.slice(-2) == PLACEHOLDER) {
var val = newVal.slice(0, -2);
if (val.slice(-1) == " ") {
if (afterKeydown)
return val.substring(0, text.selectionEnd);
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
}
});
});

View file

@ -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 ? 0 : text.value.length - 1;
} else {
var selectionStart = isEmpty ? 2 : 1;
var selectionEnd = 2;
}
// on firefox this throws if textarea is hidden
try {
text.setSelectionRange(selectionStart, selectionEnd);
@ -180,26 +185,33 @@ 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(host.selection.isEmpty());
}
};
var inputHandler = null;
this.setInputHandler = function(cb) {inputHandler = cb};
this.getInputHandler = function() {return inputHandler};
var sendText = function(data) {
if (inputHandler) {
data = inputHandler(data);
inputHandler = null;
}
if (pasted) {
resetSelection();
if (data)
host.onPaste(data);
pasted = false;
} else if (data == PLACEHOLDER[0]) {
host.execCommand("del", {source: "ace"});
if (Date.now() - lastCompositionTime > 100)
host.execCommand("del", {source: "ace"});
} else {
if (data.substring(0, 2) == PLACEHOLDER)
data = data.substr(2);
@ -219,9 +231,8 @@ var TextInput = function(parentNode, host) {
if (inCompostion)
return;
var data = text.value;
resetValue();
sendText(data);
resetValue();
};
var onCut = function(e) {
@ -344,10 +355,12 @@ var TextInput = function(parentNode, host) {
if (!inCompostion) return;
host.onCompositionUpdate(text.value);
};
var lastCompositionTime = -1;
var onCompositionEnd = function(e) {
inCompostion = false;
host.onCompositionEnd();
lastCompositionTime = Date.now();
};
var syncComposition = lang.delayedCall(onCompositionUpdate, 50);
@ -377,10 +390,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")

View file

@ -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";
};
/**