最近一段時間忽然想到用javascript理論上可以實現一個復雜的在線編輯器完全能夠支持詞法語法方面的功能於是試驗了一下效率和簡易程度還是令人吃驚的看來javascript比想象的還要強大
<html>
<head>
<title>Silverna Demo Ver </title>
<style>
diveditbox{
margin: ;
padding: ;
font:/px Arial;
border:px solid #;
}
p{
margin: ;
padding: ;
}
</style>
</head>
<body onload=editboxfocus()>
<div id=editbox class=editbox contentEditable=true onkeyDown=return KeyDown() onkeyUp=KeyUp() onclick=getCursorPosition()>
</div>
<select size= id=methods onkeydown=SelectMethod() onclick=SelMethod(this)>
</body>
</html>
</select>
<script language=JScript>
var testArray = new Array();
var testDate = new Date();
var testString = aaa;
var testVal = ;
var testObj = new myObj;
function myObj()
{
myObjprototypetestFunc = function(){};
thistestProperty = test;
}
function KeyDown()
{
//alert(eventaltKey);
if(eventkeyCode == ) //TAB 鍵
{
clipboardDatasetData(text );
eventsrcElementdocumentexecCommand(paste);
return false;
}
if(eventkeyCode == ) //Backspace 鍵
{
var oSel = documentselectioncreateRange();
var offset = eventsrcElementdocumentselectioncreateRange();
offsetmoveToPoint(oSeloffsetLeft oSeloffsetTop);
offsetmoveStart(character );
if(offsettextlength < ) return true;
for (var i = ; i < offsettextlength; i++)
{
if (offsettextcharAt(i) != )
{
return true;
}
}
offsetselect();
eventsrcElementdocumentexecCommand(Delete);
return false;
}
return true;
}
function KeyUp()
{
var oSel offset;
if(eventkeyCode == )
{
testStr = eventsrcElementinnerTextsubstring( getCursorPosition());
//alert(testStr);
var space = ;
for (var i = testStrlength ; i >= ; i)
{
//alert(testStrlength+:+testStrcharAt(i) + : + spacelength);
if (testStrcharAt(i) == \n) break;
if (testStrcharAt(i) == )
space += ;
else
space = ;
}
//alert(testStr);
clipboardDatasetData(textspace);
eventsrcElementdocumentexecCommand(paste);
}
oSel = documentselectioncreateRange();
var left = oSeloffsetLeft;
var top = oSeloffsetTop;
var token = getCurrentToken(eventsrcElement);
var chars = getCursorPosition();
parseSyntax(eventsrcElement);
offset = eventsrcElementdocumentselectioncreateRange();
offsetmoveToPoint(left top);
offsetselect();
if(eventkeyCode == ) //鍵
{
setMethods(tokenposTokslice( ));
}
}
function parseSyntax(src) //解析當前文本
{
var text = srcinnerHTML;
text = textreplace(/<FONT[^<>]*>/gi )replace(/<\/FONT[^<>]*>/gi);
text = textreplace(/<P>/gi \xfe)replace(/<\/P>/gi \xff);
text = textreplace(/\ /gi \xfd);
text = textreplace(/\r\n/gi);
for (var i = ; i <SyntaxSetAlllength; i++)
{
var syntaxes = SyntaxSetAll[i];
for (var j = ; j < syntaxesrulesAlllength; j++)
{
syntaxesrulesAll[lor = lor;
syntaxesrulesAll[ns = ns;
text = parseRule(text syntaxesrulesAll[j]);
}
}
srcinnerHTML = textreplace(/\xfc/g)replace(/\xfe/g<P>)replace(/\xff/g</P>)replace(/\xfd/g );
}
function parseRule(text rule) //解析詞法
{
//利用正則表達式
var newText = ;
var idx = textsearch(ruleexpr);
while (idx != )
{
var remark = textmatch(ruleexpr);
//alert(textsubstring( idx+remark[]length));
var subText = textsubstring( idx + remark[]length);
if(ns == null || (idx == || nstest(textcharAt(idx))) && (idx + remark[]length >= textlength || nstest(textcharAt(idx + remark[]length))))
{
//alert(remark[]);
//alert(remark[]replace(/<FONT[^<>]*>/gi )replace(/<\/FONT[^<>]*>/gi));
subText = subTextreplace(remark[] <FONT color=\xfc+lor+\xfc> + remark[]replace(/<FONT[^<>]*>/gi )replace(/<\/FONT[^<>]*>/gi) + </FONT>);
//alert(subText);
}
newText += subText;
text = textsubstring(idx + remark[]length);
idx = textsearch(ruleexpr);
}
newText += text;
return newText;
}
function getCurrentToken(src)
{
var oSel = documentselectioncreateRange();
var offset = srcdocumentselectioncreateRange();
offsetmoveToPoint(oSeloffsetLeft oSeloffsetTop);
offsetmoveStart(character );
var tokens = offsettextsplit(/[\s\+\\*\/]/); //token由連續字母數字下劃線點號括號引號構成
var currentToken = tokens[tokenslength ];
var idx = offsettextlength;
var fullToken = srcinnerTextsubstring(idx);
fullToken = fullTokenreplace(/[\s\+\\*\/]/@@@@);
idx = fullTokenindexOf(@@@@);
if(idx != )
fullToken = fullTokensubstring( idx);
var token = new Array();
tokencurrentToken = currentToken + fullToken;
tokenposTok = currentToken;
return token;
}
ArrayprototypepushDistinct = function(obj)
{
for (var i = ; i < thislength; i++)
{
if (this[i] == obj)
{
return null;
}
}
thispush(obj);
return obj;
}
function putMethods(methodList obj methods) //將方法添加到方法列表
{
var list = methodssplit();
for (var i = ; i < listlength; i++)
{
if (obj[list[i]] != null)
{
methodListpushDistinct(list[i]);
}
}
}
var now = new Date(); //測試用
var a = ; //測試用
var __expr = new RegExp(tt); //測試用
function setMethods(objStr)
{
var oSel = documentselectioncreateRange();
try
{
if (objStr == alert) return;
var methodList = new Array();
var obj = eval(objStr);
if (objprototype != null)
{
methodListpushDistinct(prototype);
}
if (obj != null)
{
//基本Object方法
putMethods(methodList objconstructorhasOwnPropertyisPrototypeOfpropertyIsEnumerabletoLocaleStringtoStringvalueOf);
//基本Array方法
putMethods(methodList objconcatjoinlengthpoppushreverseshiftslicesortspliceunshift);
//基本Date方法
putMethods(methodListobjgetDategetUTCDategetDaygetUTCDaygetFullYeargetUTCFullYeargetHoursgetUTCHoursgetMillisecondsgetUTCMillisecondsgetMinutesgetUTCMinutesgetMonthgetUTCMonthgetSecondsgetUTCSecondsgetTimegetTimezoneoffsetgetYear);
putMethods(methodListobjsetDatesetUTCDatesetFullYearsetUTCFullYearsetHourssetUTCHourssetMillisecondssetUTCMillisecondssetMinutessetUTCMinutessetMonthsetUTCMonthsetSecondssetUTCSecondssetTimesetYeartoDateStringtoGMTStringtoLocaleDateStringtoLocaleTimeStringtoStringtoTimeStringtoUTCStringvalueOfparseUTC);
//基本Math方法
putMethods(methodListobjELNLNLOGELOGEPISQRT_SQRT);
putMethods(methodListobjabsacosasinatanatanceilcosexpfloorlogmaxminpowrandomroundsinsqrttan);
//基本Function方法
putMethods(methodListobjargumentscallerlengthprototypeapplycalltoString);
//基本Number方法
putMethods(methodListobjMAX_VALUEMIN_VALUENaNNEGATIVE_INFINITYPOSITIVE_INFINITY);
putMethods(methodListobjtoStringtoLocalStringtoFixedtoExponentialtoPrecision);
//基本RegExp方法
putMethods(methodListobjglobalignoreCaselastIndexmultilinesourceexectest);
//基本String方法
putMethods(methodListobjcharAtcharCodeAtcontactindexOflastIndexOfmatchreplacesearchslicesplitsubstringsubstrtoLowerCasetoStringtoUpperCasevalueOffromCharCode);
putMethods(methodListobjanchorbigblinkboldfixedfontcolorfontsizeitalicslinksmallstrikesubsup);
}
for (each in obj)
{
methodListpushDistinct(each);
}
methodListsort();
if (methodListlength > )
{
methodsoptionslength = ;
for (var i = ; i < methodListlength; i++)
{
methodsoptionsadd(new Option(methodList[i]));
}
if (methodsoptionslength > )
{
methodssize = ;
}
else
{
methodssize = methodsoptionslength;
}
methodsstyletop = oSeloffsetTop;
methodsstyleleft = oSeloffsetLeft;
methodsstyledisplay = ;
methodsoptions[]selected = true;
methodsfocus();
}
}
catch(e){}
}
function SelectMethod()
{
var src = eventsrcElement;
if(eventkeyCode == )
{
SelMethod(src);
}
if(eventkeyCode == || eventkeyCode == || eventkeyCode == )
{
srcstyledisplay = none;
editboxfocus();
}
}
function SelMethod(src)
{
clipboardDatasetData(textsrcoptions[srcselectedIndex]text);
editboxfocus();
editboxdocumentexecCommand(paste);
srcstyledisplay = none;
getCursorPosition();
}
function getPos(text) //計算行數列數
{
var rows = ;
var cols = ;
var idx = ;
var subText = text;
while((idx = subTextindexOf(\n)) != )
{
subText = subTextsubstring(idx + );
rows++;
}
return new Array(rows subTextlength + );
}
function getNullRows(srcoSel) //計算空行
{
var rows = ;
var offsetEnd = srcdocumentselectioncreateRange();
var oldTop = ;
var oldLeft = ;
while()
{
offsetEndmoveToPoint(oSeloffsetLeft oSeloffsetTop);
offsetEndmoveStart(characterrows);
if (offsetEndtextlength > || offsetEndoffsetTop == oldTop && offsetEndoffsetLeft == oldLeft)
{
break;
}
rows ++;
oldTop = offsetEndoffsetTop;
oldLeft = offsetEndoffsetLeft;
}
return rows;
}
function getCursorPosition()
{
var src = eventsrcElement;
var offset = srcdocumentselectioncreateRange();
var oSel = documentselectioncreateRange();
var textLength = srcinnerTextlength;
offsetmoveToPoint(oSeloffsetLeft oSeloffsetTop);
offsetmoveStart(character );
//srcdocumentexecCommand(ForeColorfalse#ff);
var rowSpans = offsetgetClientRects();
var pos = getPos(offsettext);
var charCodes = offsettextlength; //字符總數
var chars = offsettextreplace(/\r\n/g)length + ; //字符
var extRows = getNullRows(srcoSel);
if(extRows > )
{
pos[] += extRows;
pos[] = ;
}
windowstatus = 行: + pos[] + 列: + pos[] + 第 + chars + 個字符 + (+ oSeloffsetTop ++
oSeloffsetLeft +);
return charCodes;
}
///詞法解析過程
///
///
var SyntaxSet = new Array(); //詞法規則集合
SyntaxSetAll = new Array();
SyntaxSetparse = function(token) //針對token返回rule
{
for (var i = ; i < thisAlllength; i++)
{
var syntaxes = thisAll[i];
for (var j = ; j < syntaxesrulesAlllength; j++)
{
if (syntaxesrulesAll[j]test(token))
{
syntaxesrulesAll[lor = lor;
return syntaxesrulesAll[j];
}
}
}
return null;
}
SyntaxSetadd = function(syntaxes)
{
if(this[syntaxesname] != null)
return;
this[syntaxesname] = syntaxes;
thisAllpush(syntaxes);
}
function Syntaxes(name color cons) //詞法規則組(同組規則用一種顏色標記)
{
thisname = name; //規則組名稱
lor = color; //標記該語法的顏色
thisrules = new Array(); //語法規則(以次序決定優先級)
thisrulesAll = new Array();
ns = cons; //邊界約束
SyntaxesprototypeaddRule = function(rule)
{
if(thisrules[rulename] != null)
return;
thisrules[rulename] = rule;
thisrulesAllpush(rule);
}
}
function SyntaxRule(name regExp) //詞法規則
{
thisname = name; //規則名稱
thisexpr = regExp; //規則描述 (正則表達式)
SyntaxRuleprototypetest = function(token)
{
return thisexprtest(token);
}
}
function RegExprX(exprStr) //擴展正則表達式的功能支持定義嵌套
{
thisexpr = exprStr;
}
RegExprXprototypegetPattern = function(tag) //獲取正則表達式對象
{
if (tag == null)
return new RegExp(thisexpr);
else
return new RegExp(thisexpr tag);
}
Rencat = function(expr rule) //連接兩個正則表達式串
{
if (rule == null)
thisexpr += expr; //直接連接
else if (rule == union) //聯合
thisexpr = ( + thisexpr + ) + | + ( + expr + );
else if (rule == cons) //約束
thisexpr = thisexpr + (?= + expr + );
return thisexpr;
}
//為保證正確計算偏移量需要替換回車\n\r為\xff
SyntaxSetadd(new Syntaxes(keywords #ff /[\s\\xfe\xff\xfd\(\{\}\)\;\]/)); //詞法?關鍵詞?藍色
SyntaxSet[keywords]addRule(new SyntaxRule(Function/function/));
SyntaxSet[keywords]addRule(new SyntaxRule(Variable/var/));
SyntaxSet[keywords]addRule(new SyntaxRule(Return/return/));
SyntaxSet[keywords]addRule(new SyntaxRule(Exception/(try|catch|throw)/));
SyntaxSet[keywords]addRule(new SyntaxRule(Condition/(if|else|switch)/));
SyntaxSet[keywords]addRule(new SyntaxRule(Cycle/(for|while|do)/));
SyntaxSet[keywords]addRule(new SyntaxRule(Type/(int|double|float|void|char)/));
SyntaxSet[keywords]addRule(new SyntaxRule(Right/(public|private|protected|static)/));
SyntaxSet[keywords]addRule(new SyntaxRule(Constant/(null|undefined|NaN|Infinity)/));
SyntaxSet[keywords]addRule(new SyntaxRule(Construct/(new|delete)/));
SyntaxSetadd(new Syntaxes(objects #FF /[\s\\xfe\xff\xfd\(\{\}\)\;\]/)); //詞法?對象?紅色
SyntaxSet[objects]addRule(new SyntaxRule(Object/(Array|arguments|Boolean|Date|Error|Function|Object|Number|Math|RegExp|String)/));
SyntaxSetadd(new Syntaxes(global # /[\s\\xfe\xff\xfd\(\{\}\)\;\]/)); //詞法?系統函數?紅色
SyntaxSet[global]addRule(new SyntaxRule(SystemFunc/(alert|parseFloat|parseInt|eval|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|escape|eval|isFinite|isNaN|unescape)/));
SyntaxSetadd(new Syntaxes(String #ffff /[\s\\xfe\xff\xfd\(\{\}\)\;\\+\\*\/]/)); //詞法?字符串?粉色
SyntaxSet[String]addRule(new SyntaxRule(String
/(((\\\)|[^\xff\])*([^\\\]|(\\\)))|(((\\\)|[^\xff\])*([^\\\]|(\\\)))/));
SyntaxSetadd(new Syntaxes(remarks #)); //詞法?注釋?綠色
SyntaxSet[remarks]addRule(new SyntaxRule(ShortRemark/\/\/[^\xff]*/));
SyntaxSet[remarks]addRule(new SyntaxRule(LongRemark/\/\*((*\*\/)|(*$))/));
function Grammars() //語法規則
{
}
</script>
From:http://tw.wingwit.com/Article/program/Java/JSP/201311/19446.html