对于网站中需要用到代码编写功能的童鞋,不放注意下CodeMirror,支持多重语言的自动联想,自动补全,很像我们熟悉的VS编辑器等。而且我们还能定义自己的联想关键字,这几天因为项目的需要,需要在文本域中实现联想补全功能。特意研究了CodeMirror。
对于网上CodeMirror的介绍很少,官网的英文看得让人头大,这两天项目中需要用到自动补全联想功能,就研究研究了CodeMirror,顺便记下来,让更多的人收益学习。
CodeMirror官网上下载压缩文件后,解压,看到好多文件,还有好多Deom有兴趣的可以多研究研究DEOM,而我们所需要的自动补全功能实际上只需要以下7个文件。
<link rel="stylesheet" href="../lib/codemirror.css"> <script src="../lib/codemirror.js"></script> <script src="../addon/hint/show-hint.js"></script> <script src="../addon/hint/javascript-hint.js"></script> <script src="../mode/javascript/javascript.js"></script> <link rel="stylesheet" href="../addon/hint/show-hint.css"> <link rel="stylesheet" href="../doc/docs.css">
(以JS代码的自动补全功能为例)引入的这些文件,只需要把这7个文件引入项目就行了,没必要把整个解压的文件引入。
<script src="../lib/codemirror.js"></script>这个是主文件,要想使用自动补全功能,就要首先引入这个文件 <script src="../addon/hint/javascript-hint.js"></script>这个文件是提示显示所有JS关键字, <script src="../mode/javascript/javascript.js"></script>
如果只需要文本域编辑器的主动补全功能, 这个文件是根据用户输入的内容,只搜索这个以用户输入的内容为开头的关键字显示出来,如果不引入这个文件,智能提示就不会提示以用户输入的内容为开头的关键字,而是系统所预设的全部关键字。所以要引入这个文件。
现在的问题:
1:在/addon/hint/javascript-hint.js文件中找出在哪里显示这些JS关键字。
2:在/mode/javascript/javascript.js文件中找到程序是怎样根据用户输入的内容,只搜索这个以用户输入的内容为开头的关键字显示出来
对于第一个问题,其实可以把这个/addon/hint/javascript-hint.js文件中的
function getCoffeeScriptToken(editor, cur) {
// This getToken, it is for coffeescript, imitates the behavior of
// getTokenAt method in javascript.js, that is, returning "property"
// type and treat "." as indepenent token.
var token = editor.getTokenAt(cur);
if (cur.ch == token.start + 1 && token.string.charAt(0) == '.') {
token.end = token.start;
token.string = '.';
token.type = "property";
}
else if (/^\.[\w$_]*$/.test(token.string)) {
token.type = "property";
token.start++;
token.string = token.string.replace(/\./, '');
}
return token;
}
CodeMirror.coffeescriptHint = function(editor, options) {
return scriptHint(editor, coffeescriptKeywords, getCoffeeScriptToken, options);
};
var stringProps = ("charAt charCodeAt indexOf lastIndexOf substring substr slice trim trimLeft trimRight " +
"toUpperCase toLowerCase split concat match replace search").split(" ");
var arrayProps = ("length concat join splice push pop shift unshift slice reverse sort indexOf " +
"lastIndexOf every some filter forEach map reduce reduceRight ").split(" ");
var funcProps = "prototype apply call bind".split(" "); var coffeescriptKeywords = ("and break catch class continue delete do else extends false finally for " +
"if in instanceof isnt new no not null of off on or return switch then throw true try typeof until void while with yes").split(" ");删除,没特殊的需求是不需要,这个默认的deom是以补全javascript为例子的,我们如果想改成自己的实例,就还需要修改一些地方:把
var javascriptKeywords = ("break case catch continue debugger default delete do else false finally for function "
+"if in instanceof new null return switch throw true try typeof var void while with").split(" ");修改成我自己的需求
var javascriptKeywords = ("薪资计算 社保计算 上月平均工资 养老保险 失业保险 sum abs qeens qees qwsa qxvc").split(" ");但是保存运行之后还是会出现JS中的关键字,默认函数之类的东西,又研究了研究,原来是:
if (context) {
// If this is a property, see if it belongs to some object we can
// find in the current environment.
var obj = context.pop(), base;
if (obj.type.indexOf("variable") === 0) {
if (options && options.additionalContext)
base = options.additionalContext[obj.string];
base = base || window[obj.string];
} else if (obj.type == "string") {
base = "";
} else if (obj.type == "atom") {
base = 1;
} else if (obj.type == "function") {
if (window.jQuery != null && (obj.string == '$' || obj.string == 'jQuery') &&
(typeof window.jQuery == 'function'))
base = window.jQuery();
else if (window._ != null && (obj.string == '_') && (typeof window._ == 'function'))
base = window._();
}
while (base != null && context.length)
base = base[context.pop().string];
if (base != null) gatherCompletions(base);
}
else {
// If not, just look in the window object and any local scope
// (reading into JS mode internals to get at the local and global variables)
for (var v = token.state.localVars; v; v = v.next) maybeAdd(v.name);
for (var v = token.state.globalVars; v; v = v.next) maybeAdd(v.name);
gatherCompletions(window);
forEach(keywords, maybeAdd);
} 这一段代码在做鬼,我就来个更直接,更暴力的办法:
直接改成这样:
if (context) {
// If this is a property, see if it belongs to some object we can
// find in the current environment.
var obj = context.pop(), base;
gatherCompletions(null);
}
else {
// If not, just look in the window object and any local scope
// (reading into JS mode internals to get at the local and global variables)
for (var v = token.state.localVars; v; v = v.next) maybeAdd(v.name);
for (var v = token.state.globalVars; v; v = v.next) maybeAdd(v.name);
gatherCompletions(null);
forEach(keywords, maybeAdd);
} 研究了一天也研究烦了,不要怪我哦!这样一试,果然是行了。
但是如果想要使用自己数据库中的关键字该怎么办呢?研究了一下想了想,也想到了一个解决办法:
在后台写一个方法也让数据库中的字段变成var javascriptKeywords = ("薪资计算 社保计算 上月平均工资 养老保险 失业保险 sum abs qeens qees qwsa qxvc").split(" ");即可,我的方法:
protected string GetDefaultValue()
{
DataTable dt = BDAContext.GetObject<ICNPRStructureConfigBLL>().GetAllObjectPropertyName();
string s = string.Empty;
if (dt.Rows.Count>0)
{
foreach (DataRow dr in dt.Rows)
{
s += dr["Name"] + " ";
}
}
return s;
} 在前台开始就写上 CodeMirror.javascriptKeywords = ('<%=GetDefaultValue()%>').split(" ");
但是所有的javascriptKeywords需要加上CodeMirror.,及我上面所写的。
所以我的aspx页面就是这样的:
<script type="text/javascript">
$(document).ready(function () {
CodeMirror.javascriptKeywords = ('<%=GetDefaultValue()%>').split(" ");
CodeMirror.commands.autocomplete = function (cm) {
CodeMirror.showHint(cm, CodeMirror.javascriptHint);
}
var editor = CodeMirror.fromTextArea(document.getElementById("txt_FunExp"), {
textWrapping: true,
lineWrapping: true,
lineNumbers: false,
extraKeys: { "Ctrl-Space": "autocomplete" }
});
});
</script> 但是又出现一个问题:输入中文时,不会智能提示出那个中文开头的短语或词组,也就是说不支持中文只能提示。又是个纠结的问题,还需要研究修改
/mode/javascript/javascript.js 文件的内容,一看,比刚才那个JS文件代码还多,我瞬间比这个文件的代码更凌乱了,没办法,慢慢研究研究吧!
也欢迎大牛们给出知道意见,看看怎么支持中文!不胜感激!
附上贴图:这是原DEOM中的实例,按下Ctrl-Space键之后,就会提示所有的JS关键字等,
任意按下一个字母,如m,再按Ctrl-Space键,就会提示出所有以m开头的单词
经本人修改后,成这样:
。
另外,需要提醒的是,使用快捷键显示的话注意最好不要跟其他应用程序的的热键冲突。