Javascript 编辑器(html版)

<html>
<head>
<title>Silverna Demo Ver 0.01</title>
<style>
div.editbox
{
margin
:0 0 0 0;
padding
:0 0 0 0;
font
:16/18px Arial;
border
:0px solid #000000;
}

p
{
margin
:0 0 0 0;
padding
:0 0 0 0;
}

</style>
</head>

<body style="margin:0 0 0 0;padding:0 0 0 0;word-break:break-all;overflow-x:hidden" onLoad="editbox.focus()">
<div id="editbox" class="editbox" style="99%;height:80%;" contentEditable="true" onkeyDown="return KeyDown()" onkeyUp="KeyUp()">
</div>
<select size="10" style="display:none;position:absolute" id="methods" onkeydown="SelectMethod()" onclick="SelMethod(this)" onClick="getCursorPosition()">
</select> 
<script language=Jscript>
var testArray = new Array();
var testDate = new Date();
var testString = "aaa";
var testVal = 1;
var testObj = new myObj;

function myObj()
{
    myObj.prototype.testFunc 
= function(){};
    
this.testProperty = "test";
}

function KeyDown()
{
    
////alert(event.altKey);
    if(event.keyCode == 9//TAB 键
    {
        clipboardData.setData('text',' ');
        event.srcElement.document.execCommand('paste');
        
return false
    }

    
if(event.keyCode == 8//Backspace 键
    {
        
var oSel = document.selection.createRange();
        
var offset = event.srcElement.document.selection.createRange();
        offset.moveToPoint(oSel.offsetLeft, oSel.offsetTop);
        offset.moveStart('character', 
-4);
        
if(offset.text.length < 4return true;
        
for (var i = 0; i < offset.text.length; i++)
        
{
            
if (offset.text.charAt(i) != " ")
        
{
        
return true;
        }

    }

    offset.select();
    event.srcElement.document.execCommand('Delete');
    
return false
    }

    
return true;
}

//
function KeyUp()
{
    
var oSel, offset;
    
if(event.keyCode == 13)
    
{
        testStr 
= event.srcElement.innerText.substring(0, getCursorPosition());
        
//alert(testStr);
        var space = "";
        
for (var i = testStr.length - 1; i >= 0; i--)
        
{
            
//alert(testStr.length+":"+testStr.charAt(i) + ":" + space.length);
            if (testStr.charAt(i) == "\n"break;
            
if (testStr.charAt(i) == " ")
            space 
+= " ";
            
else
            space 
= "";
        }

        
//alert(testStr);
        clipboardData.setData('text',space);
        event.srcElement.document.execCommand('paste');
    }

    oSel 
= document.selection.createRange();
    
var left = oSel.offsetLeft;
    
var top = oSel.offsetTop;
    
var token = getCurrentToken(event.srcElement);
    
var chars = getCursorPosition();
    
    parseSyntax(event.srcElement);
    offset 
= event.srcElement.document.selection.createRange();
    offset.moveToPoint(left, top);
    offset.select();
    
    
if(event.keyCode == 190//.键
    {
        setMethods(token.posTok.slice(
0-1));
    }

}

//
function parseSyntax(src) //解析当前文本

    
var text = src.innerHTML;
    text 
= text.replace(/<FONT[^<>]*>/gi, "").replace(/<\/FONT[^<>]*>/gi,"");
    text 
= text.replace(/<P>/gi, "\xfe").replace(/<\/P>/gi, "\xff");
    text 
= text.replace(/\&nbsp;/gi, "\xfd");
    text 
= text.replace(/\r\n/gi,"");
    
    
for (var i = 0; i <SyntaxSet.All.length; i++)
    
{
        
var syntaxes = SyntaxSet.All[i];
        
for (var j = 0; j < syntaxes.rules.All.length; j++)
        
{
            syntaxes.rules.All[j].color 
= syntaxes.color;
            syntaxes.rules.All[j].cons 
= syntaxes.cons;
            
            text 
= parseRule(text, syntaxes.rules.All[j]);
        }

    }

    
    src.innerHTML 
= text.replace(/\xfc/g,"'").replace(/\xfe/g,"<P>").replace(/\xff/g,"</P>").replace(/\xfd/g,"&nbsp;");
}

function parseRule(text, rule) //解析词法
{
    
//利用正则表达式
    var newText = "";
    
    
var idx = text.search(rule.expr);
    
    
while (idx != -1)
    
{
        
var remark = text.match(rule.expr);
        
//alert(text.substring(0, idx+remark[0].length));
        var subText = text.substring(0, idx + remark[0].length);
        
//        if(idx == 0 && rule.cons.test(text.charAt(idx-1)))// && (idx + remark[0].length >= text.length rule.cons.test(text.charAt(idx + remark[0].length))))
//
        {
//
            //alert(remark[0]);
//
            //alert(remark[0].replace(/<FONT[^<>]*>/gi, "").replace(/<\/FONT[^<>]*>/gi,""));
//
            subText = subText.replace(remark[0], "<FONT color=\xfc"+rule.color+"\xfc>" + remark[0].replace(/<FONT[^<>]*>/gi, "").replace(/<\/FONT[^<>]*>/gi,"") + "</FONT>");
//
            //alert(subText);
//
        }
        newText += subText;
        text 
= text.substring(idx + remark[0].length);
        idx 
= text.search(rule.expr);
    }

    newText 
+= text;
    
return newText;
}


function getCurrentToken(src)
{
    
var oSel = document.selection.createRange();
    
var offset = src.document.selection.createRange();
    offset.moveToPoint(oSel.offsetLeft, oSel.offsetTop);
    offset.moveStart(
"character"-99999);
    
    
var tokens = offset.text.split(/[\s\+\-\*\/]/); //token由连续字母数字、下划线、点号、括号、引号构成
    var currentToken = tokens[tokens.length - 1];
    
    
var idx = offset.text.length;
    
    
var fullToken = src.innerText.substring(idx);
    fullToken 
= fullToken.replace(/[\s\+\-\*\/]/,"@@@@");
    
    idx 
= fullToken.indexOf("@@@@");
    
if(idx != -1)
    fullToken 
= fullToken.substring(0, idx);
    
    
var token = new Array();
    
    token.currentToken 
= currentToken + fullToken;
    token.posTok 
= currentToken;
    
    
return token;
}

    Array.prototype.pushDistinct 
= function(obj)
    
{
    
for (var i = 0; i < this.length; i++)
    
{
    
if (this[i] == obj)
    
{
    
return null;
    }

    }

    
this.push(obj);
    
return obj;
}


function putMethods(methodList, obj, methods) //将方法添加到方法列表
{
    
var list = methods.split(",");
    
    
for (var i = 0; i < list.length; i++)
    
{
        
if (obj[list[i]] != null)
        
{
            methodList.pushDistinct(list[i]);
        }

    }

}

    
var now = new Date(); //测试用
    var a = 33.3333//测试用
    var __expr = new RegExp("tt"); //测试用
    function setMethods(objStr)
    
{
    
var oSel = document.selection.createRange();
    
    
try
    
{
    
if (objStr == "alert"return;
    
var methodList = new Array();
    
var obj = eval(objStr);
    
    
if (obj.prototype != null)
    
{
    methodList.pushDistinct(
"prototype");
    }

    
if (obj != null)
    
{
    
    
//基本Object方法
    putMethods(methodList, obj,"constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf");
    
    
//基本Array方法
    putMethods(methodList, obj,"concat,join,length,pop,push,reverse,shift,slice,sort,splice,unshift"); 
    
    
//基本Date方法
    putMethods(methodList,obj,"getDate,getUTCDate,getDay,getUTCDay,getFullYear,getUTCFullYear,getHours,getUTCHours,getMilliseconds,getUTCMilliseconds,getMinutes,getUTCMinutes,getMonth,getUTCMonth,getSeconds,getUTCSeconds,getTime,getTimezoneoffset,getYear");
    
    putMethods(methodList,obj,
"setDate,setUTCDate,setFullYear,setUTCFullYear,setHours,setUTCHours,setMilliseconds,setUTCMilliseconds,setMinutes,setUTCMinutes,setMonth,setUTCMonth,setSeconds,setUTCSeconds,setTime,setYear,toDateString,toGMTString,toLocaleDateString,toLocaleTimeString,toString,toTimeString,toUTCString,valueOf,parse,UTC");
    
    
//基本Math方法
    putMethods(methodList,obj,"E,LN10,LN2,LOG10E,LOG2E,PI,SQRT1_2,SQRT2");
    putMethods(methodList,obj,
"abs,acos,asin,atan,atan2,ceil,cos,exp,floor,log,max,min,pow,random,round,sin,sqrt,tan");
    
    
//基本Function方法
    putMethods(methodList,obj,"arguments,caller,length,prototype,apply,call,toString");
    
    
//基本Number方法
    putMethods(methodList,obj,"MAX_VALUE,MIN_VALUE,NaN,NEGATIVE_INFINITY,POSITIVE_INFINITY");
    putMethods(methodList,obj,
"toString,toLocalString,toFixed,toExponential,toPrecision");
    
    
//基本RegExp方法
    putMethods(methodList,obj,"global,ignoreCase,lastIndex,multiline,source,exec,test");
    
    
//基本String方法
    putMethods(methodList,obj,"charAt,charCodeAt,contact,indexOf,lastIndexOf,match,replace,search,slice,split,substring,substr,toLowerCase,toString,toUpperCase,valueOf,fromCharCode");
    putMethods(methodList,obj,
"anchor,big,blink,bold,fixed,fontcolor,fontsize,italics,link,small,strike,sub,sup");
    
    }

    
for (each in obj)
    
{
    methodList.pushDistinct(each);
    }

    methodList.sort();
    
    
if (methodList.length > 0)
    
{
    methods.options.length 
= 0;
    
for (var i = 0; i < methodList.length; i++)
    
{
    methods.options.add(
new Option(methodList[i])); 
    }

    
if (methods.options.length > 10)
    
{
    methods.size 
= 10;
    }

    
else
    
{
    methods.size 
= methods.options.length;
    }

    methods.style.top 
= oSel.offsetTop;
    methods.style.left 
= oSel.offsetLeft;
    methods.style.display 
= "";
    methods.options[
0].selected = true;
    methods.focus();
    }

    }

    
catch(e){}
}


function SelectMethod()
{
var src = event.srcElement;
if(event.keyCode == 13)
{
SelMethod(src);
}


if(event.keyCode == 27 && event.keyCode == 8 && event.keyCode == 32//---------------------------edit
{
src.style.display 
= "none";
editbox.focus();
}

}


function SelMethod(src)
{
clipboardData.setData('text',src.options[src.selectedIndex].text);
editbox.focus();
editbox.document.execCommand('paste');
src.style.display 
= "none";
getCursorPosition();
}

function getPos(text) //计算行数、列数
{
var rows = 1;
var cols = 1;
var idx = 0;
var subText = text;
while((idx = subText.indexOf("\n")) != -1)
{
subText 
= subText.substring(idx + 1);
rows
++;
}

return new Array(rows, subText.length + 1);
}

function getNullRows(src,oSel) //计算空行
{
var rows = 0;

var offsetEnd = src.document.selection.createRange();

var oldTop = 2;
var oldLeft = 2;

while(1)
{
offsetEnd.moveToPoint(oSel.offsetLeft, oSel.offsetTop);
offsetEnd.moveStart(
"character",-1-rows);

if (offsetEnd.text.length > 0 && offsetEnd.offsetTop == oldTop && offsetEnd.offsetLeft == oldLeft)
{
break;
}


rows 
++;
oldTop 
= offsetEnd.offsetTop;
oldLeft 
= offsetEnd.offsetLeft;
}


return rows;
}

function getCursorPosition()
{
var src = event.srcElement;
var offset = src.document.selection.createRange();
var oSel = document.selection.createRange();

var textLength = src.innerText.length;

offset.moveToPoint(oSel.offsetLeft, oSel.offsetTop);
offset.moveStart(
"character"-99999);
//src.document.execCommand("ForeColor",false,"#ff0000");
var rowSpans = offset.getClientRects();

var pos = getPos(offset.text);

var charCodes = offset.text.length; //字符总数
var chars = offset.text.replace(/\r\n/g,"").length + 1//字符

var extRows = getNullRows(src,oSel);
if(extRows > 0)
{
pos[
0+= extRows;
pos[
1= 1;
}

window.status 
= "行: " + pos[0+", 列: " + pos[1+ ", 第 " + chars + " 个字符" + " ("+ oSel.offsetTop +","+
oSel.offsetLeft 
+")";
return charCodes;
}



///词法解析过程..
//
/..
//
/..

var SyntaxSet = new Array(); //词法规则集合
SyntaxSet.All = new Array();

SyntaxSet.parse 
= function(token) //针对token返回rule
{
for (var i = 0; i < this.All.length; i++)
{
var syntaxes = this.All[i];
for (var j = 0; j < syntaxes.rules.All.length; j++)
{
if (syntaxes.rules.All[j].test(token))
{
syntaxes.rules.All[j].color 
= syntaxes.color;
return syntaxes.rules.All[j];
}

}

}


return null;
}


SyntaxSet.add 
= function(syntaxes)
{
if(this[syntaxes.name] != null)
return;
this[syntaxes.name] = syntaxes;
this.All.push(syntaxes);
}


function Syntaxes(name, color, cons) //词法规则组(同组规则用一种颜色标记)
{
this.name = name; //规则组名称
this.color = color; //标记该语法的颜色
this.rules = new Array(); //语法规则(以次序决定优先级)
this.rules.All = new Array();
this.cons = cons; //边界约束


Syntaxes.prototype.addRule 
= function(rule)
{
if(this.rules[rule.name] != null)
return;
this.rules[rule.name] = rule;
this.rules.All.push(rule);
}

}


function SyntaxRule(name, regExp) //词法规则
{
this.name = name; //规则名称
this.expr = regExp; //规则描述 (正则表达式)
SyntaxRule.prototype.test = function(token)
{
return this.expr.test(token);
}

}


function RegExprX(exprStr) //扩展正则表达式的功能,支持定义嵌套
{
this.expr = exprStr;
}

RegExprX.prototype.getPattern 
= function(tag) //获取正则表达式对象
{
if (tag == null)
return new RegExp(this.expr);
else
return new RegExp(this.expr, tag);
}

RegExprX.prototype.concat 
= function(expr, rule) //连接两个正则表达式串
{
if (rule == null)
this.expr += expr; //直接连接
else if (rule == "union"//联合
this.expr = "(" + this.expr + ")" + "" + "(" + expr + ")"
else if (rule == "cons"//约束
this.expr = this.expr + "(?=" + expr + ")";
return this.expr;
}


//为保证正确计算偏移量需要替换回车\n\r为\xff
SyntaxSet.add(new Syntaxes("keywords""#0000ff"/[\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",/(trycatchthrow)/));
SyntaxSet[
"keywords"].addRule(new SyntaxRule("Condition",/(ifelseswitch)/));
SyntaxSet[
"keywords"].addRule(new SyntaxRule("Cycle",/(forwhiledo)/));
SyntaxSet[
"keywords"].addRule(new SyntaxRule("Type",/(intdoublefloatvoidchar)/));
SyntaxSet[
"keywords"].addRule(new SyntaxRule("Right",/(publicprivateprotectedstatic)/));
SyntaxSet[
"keywords"].addRule(new SyntaxRule("Constant",/(nullundefinedNaNInfinity)/));
SyntaxSet[
"keywords"].addRule(new SyntaxRule("Construct",/(newdelete)/));

SyntaxSet.add(
new Syntaxes("objects""#FF0000"/[\s\.\xfe\xff\xfd\(\{\}\)\;\,]/)); //词法?对象?红色
SyntaxSet["objects"].addRule(new SyntaxRule("Object",/(ArrayargumentsBooleanDateErrorFunctionObjectNumberMathRegExpString)/));

SyntaxSet.add(
new Syntaxes("global""#800000"/[\s\.\xfe\xff\xfd\(\{\}\)\;\,]/)); //词法?系统函数?红色
SyntaxSet["global"].addRule(new SyntaxRule("SystemFunc",/(alertparseFloatparseIntevaldecodeURIdecodeURIComponentencodeURIencodeURIComponentescapeevalisFiniteisNaNunescape)/));

SyntaxSet.add(
new Syntaxes("String""#ff00ff"/[\s\.\xfe\xff\xfd\(\{\}\)\;\,\+\-\*\/]/)); //词法?字符串?粉色
SyntaxSet["String"].addRule(new SyntaxRule("String",
/('((\\\')[^\xff\'])*([^\\\'](\\\'))')("((\\\")[^\xff\"])*([^\\\"](\\\"))")/));

SyntaxSet.add(
new Syntaxes("remarks""#008000")); //词法?注释?绿色
SyntaxSet["remarks"].addRule(new SyntaxRule("ShortRemark",/\/\/[^\xff]*/));
SyntaxSet[
"remarks"].addRule(new SyntaxRule("LongRemark",/\/\*((.*\*\/)(.*$))/));

function Grammars() //语法规则
{
}

</script>
</body>
</html>


原文地址:https://www.cnblogs.com/shengshuai/p/jseditor.html