CodeMirror sql部分智能提示关键字,老板希望可以自己加提示,还能支持 库.表.字段 下面我就说下我具体的做法:
看这个很容易看出点啥,codemirror.js 主要是框架和配置类,show-hint.js 主要是显示提示框的类;
剩下的sql.js是规定了一些常用关键字,好吧其实我们可以在这里改,做下扩展嘛。我选择的是下一个sql-hint.js
/** * 2016/03/22 yc 重写sql-hint.js * @param {Object} mod */ (function(mod) { if (typeof exports == "object" && typeof module == "object") // CommonJS mod(require("../../lib/codemirror"), require("../../mode/sql/sql")); else if (typeof define == "function" && define.amd) // AMD define(["../../lib/codemirror", "../../mode/sql/sql"], mod); else // Plain browser env mod(CodeMirror); })(function(CodeMirror) { "use strict"; var Pos = CodeMirror.Pos; /** * 从sql.js里获取keyword数组 * @param {Object} editor */ function getKeywords(editor) { var mode = editor.doc.modeOption; if (mode === "sql") mode = "text/x-sql"; return CodeMirror.resolveMode(mode).keywords; }; /** * 判断元素item是否存在数组arr中 * @param {Object} arr * @param {Object} item */ function arrayContains(arr, item) { // 判断元素item是否存在数组arr中 if (!Array.prototype.indexOf) { var i = arr.length; while (i--) { if (arr[i] === item) { return true; } } return false; } return arr.indexOf(item) != -1; }; function hintSql(editor, keywords, tableKeywords, getToken, options) { // 处理hint的核心函数,改名为velocityHint(也可以不做修改) // Find the token at the cursor,获取当前光标指定的字符串 var cur = editor.getCursor(), token = getToken(editor, cur), tprop = token; return { list: getCompletions(token, keywords, tableKeywords, options), from: Pos(cur.line, fetchStartPoint(token)), // 字符串拼接的初始位置,这个很重要 to: Pos(cur.line, token.end) }; }; /** * 字符拼接位置 * @param {Object} token */ function fetchStartPoint(token) { var index = token.string.lastIndexOf("\."); if (index < 0) { return token.start; } else { return token.start + index + 1; } // return token.start; }; function sqlHint(editor, options) { var keywords = wordToString(getKeywords(editor)) + CodeMirror.keywords; return hintSql(editor, keywords, CodeMirror.tableKeywords, function(e, cur) { return e.getTokenAt(cur); }, options); }; CodeMirror.registerHelper("hint", "sql", sqlHint); /** * 得到匹配的关键字数组 * @param {Object} token * @param {Object} keywords * @param {Object} tableKeywords * @param {Object} options */ function getCompletions(token, keywords, tableKeywords, options) { var found = [], start, pointCount, content = getWord(token.str.string, token.str.end); // found为匹配的数组 if (content && content.length) { start = token.string.charAt(0); //字符串首字母 content = content.trim().substring(0, content.lenght); //除首字母外的截取 pointCount = (start == '\.') ? true : false; //判断最后一个字符是否是. } var result = null; if (start && start.trim() != '') { // 必须以$开头,这里暂时不解析${} var regexp = new RegExp("\\b" + content + "\\w+\\.?\\b", "gi"); if (pointCount && tableKeywords) { result = tableKeywords.match(regexp); } else { result = keywords.match(regexp); } console.log('result = ' + result); } if (result && result.length) { for (var i = 0; i < result.length; i++) { if (!arrayContains(found, result[i]) && content.length <= result[i].length && pointCount) { if (result[i].charAt(result[i].length-1) == '.') { //如果最后一位是'.' found.push(result[i].substring(content.lastIndexOf("\.") + 1, result[i].length - 1)); } else { found.push(result[i].substring(content.lastIndexOf("\.") + 1, result[i].length)); } } else { found.push(result[i]); } } } return found; }; /** * 获取当前字符串 * @param {Object} str 当前行字符串 * @param {Object} end 结束位置 */ function getWord(str, end) { return str.substring(str.lastIndexOf(' '), end); }; /** * 将wordlist拼成字符串 * @param {Object} wordlist */ function wordToString(wordlist) { var str = ''; for (var word in wordlist) { str += word + ' '; } return str; }; });
注释还好啦,你比对下原来的js就会发现实现方法。其实我就是定义了外部变量然后通过赋值拓展的方式实现的。
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> </head> <script type="text/javascript" src="js/jquery-1.7.1.js"></script> <link rel="stylesheet" href="js/codemirror-5.2/theme/3024-day.css"> <link type="text/css" rel="stylesheet" href="js/codemirror-5.2/lib/codemirror.css" /> <link type="text/css" rel="stylesheet" href="js/codemirror-5.2/addon/hint/show-hint.css" /> <script type="text/javascript" src="js/codemirror-5.2/lib/codemirror.js"></script> <script type="text/javascript" src="js/codemirror-5.2/mode/sql/sql.js"></script> <script type="text/javascript" src="js/codemirror-5.2/addon/hint/show-hint.js"></script> <script type="text/javascript" src="js/sql-hint.js"></script> <style> .CodeMirror { border: 1px solid black; } </style> <body> <h2>SQL编辑器</h2> <form> <textarea id="code" name="code"></textarea> </form> <script> CodeMirror.keywords = "server software "; CodeMirror.tableKeywords = "server.ip server.cache software.conf software.version software.tags.count "; var editor = CodeMirror.fromTextArea(document.getElementById("code"), { lineNumbers: true, extraKeys: { "Ctrl": "autocomplete" }, //输入s然后ctrl就可以弹出选择项 mode: { name: "text/x-mysql" }, theme: "3024-day" //主题 }); editor.on('change', function() { editor.showHint(); //满足自动触发自动联想功能 }); </script> </body> </html>