/**
*@description:
*使用javascript模仿JSP的页面解析和运行,运行于客户端
*允许应用人员象开发JSP页面一样使用<%..%>
*允许页面动态包括子页面(同步读取页面)
*
**/
//@---------------------------------------------------------------------JSSP声明
varjssp=function(){};
/**
*页面缓存管理实例对象
*/
jssp.cacheInstance=null;
/**
*页面加载实例对象
*/
jssp.pageLoaderInstance=null;
/**
*在指定dom插入pagePath的执行后的页面内容
*/
jssp.render=function(pagePath,dom){
if(typeofdom=="string")dom=document.getElementById(dom);
varcontent=jssp.Core.run(pagePath);
dom.innerHTML=content;
}
//@------------------------------------------------------------------------JSSP运行配置
/**
*引擎运行全局配置
*/
jssp.Config={};
/**
*如果在客户端运行,是否缓存解析的页面
*/
jssp.Config.cachable=true;
/**
*当jssp.Config.cacheable为true且在
*/
jssp.Config.cacheClass="jssp.Cache.DefaultCache";
/**
*页面内容读取器
*/
jssp.Config.pageLoaderClass="jssp.Core.PageLoader.Ajax";
//@------------------------------------------------------------------------JSSP页面缓存类
/**
*页面缓存类
*/
jssp.Cache=function(){}
/**
*设置缓存
*/
jssp.Cache.prototype.set=function(key,cache){}
/**
*得到缓存
*/
jssp.Cache.prototype.get=function(key){}
/**
*默认的缓存实现类
*/
jssp.Cache.DefaultCache=function(){
this.caches={};
}
jssp.Cache.DefaultCache.prototype.set=function(key,cache){
this.caches[key]=cache;
}
jssp.Cache.DefaultCache.prototype.get=function(key){
returnthis.caches[key];
}
//@-----------------------------------------------------------------------JSSP运行上下文类
/**
*jssp页面的执行上下文对象
*@memberparams请求参数数组
*@membercookies操作cookies对象jssp.Cookies
*@memberout页面流输出对象jssp.Out
*@methodsetAttribute设置上下文参数
*@methodgetAttribute得到上下文参数
*@methodremoveAttribute删除上下文参数
*@methodinclude动态包含子页面
*@methodgetCookies,getParameter,getParameters,getOut
*@parampageUrl运行的上下文参数
*@paramcontext父页面的上下文对象
*/
jssp.Context=function(pageUrl,context){
this.params=this._resolveParam(pageUrl);
if(!context){
this.cookies=jssp.Cookies;
this.out=newjssp.Out();
this.attributes=[];
}else{
this.context=context;
this.isIncluded=true;
}
}
/**
*解析页面后缀参数
*/
jssp.Context.prototype._resolveParam=function(pageUrl){
vari1=pageUrl.indexOf("?");
if(i1<=0)return[];
pageUrl=pageUrl.substring(i1+1);
vars1=pageUrl.split("&");
varparams=[];
for(vari=0;i
varkey=s2[0];varvalue=s2[1];
varps=params[key];
if(!ps)ps=[];
ps[ps.length]=value;
params[key]=ps;
}
returnparams;
}
/**
*设置参数值
*/
jssp.Context.prototype.setAttribute=function(key,value){
if(!this.context)
this.attributes[key]=value;
else
this.context.setAttribute(key,value);
}
/**
*得到参数值
*/
jssp.Context.prototype.getAttribute=function(key){
if(!this.context)
returnthis.attributes[key];
else
returnthis.context.getAttribute(key);
}
/**
*删除指定键的参数值
*/
jssp.Context.prototype.removeAttribute=function(key){
if(!this.context)
this.attributes[key]=undefined;
else
this.context.removeAttribute(key);
}
/**
*得到请求参数值
*/
jssp.Context.prototype.getParameter=function(key){
varps=this.params[key];
if(!ps)returnthis.context?this.context.getParameter(key):undefined;
returnps.join(",");
}
/**
*得到有重复参数的值
*/
jssp.Context.prototype.getParameters=function(key){
varpss=this.params[key];
if(!pss)pss=this.context?this.context.getParameters(key):undefined;
returnpss;
}
/**
*得到cookies对象
*/
jssp.Context.prototype.getCookies=function(){
if(!this.context)
returnthis.cookies;
else
returnthis.context.getCookies();
}
/**
*得到输出流OUT对象
*/
jssp.Context.prototype.getOut=function(){
if(!this.context)
returnthis.out;
else
returnthis.context.getOut();
}
/**
*动态包含子页面
*/
jssp.Context.prototype.include=function(childPageUrl){
this.getOut().print(jssp.Core.run(childPageUrl,this));
}
jssp.Context.prototype.isIncluded=false;//判断当前页面是否被包含的
//@-----------------------------------------------------------------------JSSP运行cookies操作类
/**
*简单操纵cookies方法
*/
jssp.Cookies=function(){}
/**
*设置cookie项
*/
jssp.Cookies.set=function(key,value){
document.cookie=key+"="+escape(value)+";";
}
/**
*得到cookie项
*/
jssp.Cookies.get=function(key){
varaCookie=document.cookie.split(";");
for(vari=0;i
if(key==aCrumb[0])
returnunescape(aCrumb[1]);
}
}
/**
*删除cookies项
*/
jssp.Cookies.remove=function(key){
document.cookie=key+"=null;expires=Fri,31Dec199923:59:59GMT;";
}
//@------------------------------------------------------------------------JSSP页面运行输出流类
/**
*页面流输出对象
*/
jssp.Out=function(){
this.datas=[];//数据流片断
this._index=0;
}
/**
*把页面流片断放入缓冲区
*/
jssp.Out.prototype.print=function(s){
this.datas[this._index++]=s;
}
/**
*输出缓冲区里的数据
*/
jssp.Out.prototype.flush=function(){
vardata=this.datas.join("");
this.datas=[];this._index=0;
returndata;
}
//@--------------------------------------------------------------------------JSSP页面核心类声明
jssp.Core=function(){}
//@--------------------------------------------------------------------------JSSP页面解析实现类
/**
*页面解析
*@parampageContentJSSP页面内容
*/
jssp.Core.parse=function(pageContent){
varstrBuffer=[];//解析后文本存放的缓冲区
varpoint=0;//缓冲区指针
varlineNumber=1;//解析的当前行
try{
varbetweenPerc=false;
varisPrint=false;
strBuffer[point++]="function($context){n";
strBuffer[point++]="var$out=$context.getOut();n";
strBuffer[point++]="var$cookies=$context.getCookies();n";
strBuffer[point++]="try{n";
strBuffer[point++]="$out.print(unescape('";
varline="";
varvalue=pageContent;
varlen=value.length;
for(vari=0;i
if(i<=len-2)nextTwo=value.charAt(i)+value.charAt(i+1);
varnextThree="";
if(i<=len-3)nextThree=nextTwo+value.charAt(i+2);
if(nextTwo=="<%"&&nextThree!="<%="&&nextThree!="<%@"){
strBuffer[point++]="'));n";
betweenPerc=true;
i+=1;
}elseif(nextTwo=="<%"&&nextThree=="<%="&&nextThree!="<%@"){
strBuffer[point++]=escape(line)+"'));n";
line="";
strBuffer[point++]="$out.print(";
betweenPerc=true;
isPrint=true;
i+=2;
}elseif(nextTwo=="<%"&&nextThree!="<%="&&nextThree=="<%@"){
i+=3;
vardirective="";
while(nextTwo!="%>"){
directive+=value.charAt(i);
i++;
if(i<=value.length-2){
nextTwo=value.charAt(i)+value.charAt(i+1);
}
}
strBuffer[point++]=escape(line)+"'));n";
line="";
strBuffer[point++]=jssp.Core.parse._handleDirective(directive);
strBuffer[point++]="$out.print(unescape('";
i++;
}elseif(nextTwo=="%>"){
strBuffer[point++]=(isPrint?");":"")+"n$out.print(unescape('";
if(!betweenPerc)thrownewjssp.Core.parse.ParseException("解析错误","必须用'%>'作为结束标签");
betweenPerc=false;
isPrint=false;
i+=1;
}elseif(value.charAt(i)==String.fromCharCode(10)){
if(!betweenPerc){
strBuffer[point++]=escape(line)+"n'));n"+"$out.print(unescape('";
line="";
lineNumber++;
}
}elseif(value.charAt(i)==String.fromCharCode(13)){
if(betweenPerc)strBuffer[point++]="n";
}else{
if(betweenPerc)
strBuffer[point++]=value.charAt(i);
else
line+=value.charAt(i);
}
}
strBuffer[point++]=escape(line)+"'));n";
strBuffer[point++]="}catch(e){n";
strBuffer[point++]="return'"+"执行页面发生异常.异常类型:'+e.name+'.错误消息:'+e.message;n";
strBuffer[point++]="}n";
strBuffer[point++]="if(!$context.isIncluded)return$out.flush();n";
strBuffer[point++]="}n";
}catch(e){
point=0;
strBuffer=[];
strBuffer[point++]="function($context){n";
strBuffer[point++]="return""+"Anexceptionoccurredwhileparsingonline"+lineNumber+".Errortype:"+e.name+".Errormessage:"+e.message+"";";
strBuffer[point++]="}";
}
varout=strBuffer.join("");
returnout;
}
/**
*解析指示头
*/
jssp.Core.parse._handleDirective=function(directive){
vari=0;
vartolkenIndex=0;
vartolken=newArray();
//Skipfirstspaces;
while(directive.charAt(i)==''){
i++;
}
tolken[tolkenIndex]="";
while(directive.charAt(i)!=''&&i<=directive.length){
tolken[tolkenIndex]+=directive.charAt(i);
i++;
}
tolkenIndex++;
//Skipfirstspaces;
while(directive.charAt(i)==''){
i++;
}
tolken[tolkenIndex]="";
while(directive.charAt(i)!=''&&directive.charAt(i)!='='&&i<=directive.length){
tolken[tolkenIndex]+=directive.charAt(i);
i++;
}
tolkenIndex++;
//Skipfirstspaces;
while(directive.charAt(i)==''){
i++;
}
if(directive.charAt(i)!='=')
thrownewjssp.Core.parse.ParseException("Sintaxerror","Tolken=expectedattribute");
i++
//Skipfirstspaces;
while(directive.charAt(i)==''){
i++;
}
tolken[tolkenIndex]="";
while(directive.charAt(i)!=''&&i<=directive.length){
tolken[tolkenIndex]+=directive.charAt(i);
i++;
}
tolkenIndex++;
//Skipfirstspaces;
while(directive.charAt(i)==''&&i<=directive.length){
i++;
}
tolken[tolkenIndex]="";
while(directive.charAt(i)!=''&&directive.charAt(i)!='='&&i<=directive.length&&i<=directive.length){
tolken[tolkenIndex]+=directive.charAt(i);
i++;
}
tolkenIndex++;
if(directive.charAt(i)!='='&&i<=directive.length)
thrownewjssp.Core.parse.ParseException("Sintaxerror","Tolken=expectedafterattribute");
i++
tolken[tolkenIndex]="";
while(directive.charAt(i)!=''&&i<=directive.length&&i<=directive.length){
tolken[tolkenIndex]+=directive.charAt(i);
i++;
}
varfile="";
varcontext="";
if(tolken[0]!="include")
thrownewjssp.Core.parse.ParseException("Sintaxerror","Directive"+tolken[0]+"unknown.");
if(tolken[1]!="file")
thrownewjssp.Core.parse.ParseException("Sintaxerror","Attributefileexpectedafterinclude.");
elsefile=tolken[2];
if(tolken[3]!="context"&&tolken[3]!="")
thrownewjssp.Core.parse.ParseException("Sintaxerror","Attributecontextexpectedafterfile.");
elseif(tolken[3]=="context")
context=tolken[4]
else
context="$context";
varout="$context.include("+file+");n";
returnout;
}
/**
*解析异常
*/
jssp.Core.parse.ParseException=function(name,message){
this.name=name;
this.message=message;
}
//@--------------------------------------------------------------------------------页面内容加载接口定义
/**
*页面内容加载类接口定义
*/
jssp.Core.PageLoader=function(){}
/**
*读取页面文本
*/
jssp.Core.PageLoader.prototype.loadPage=function(pagePath){throw"不能直接调用接口或您还未实现此方法!";}
//@--------------------------------------------------------------------------------页面运行实现方法
/**
*@parampagePath加载页面
*@parmacontext上下文对象
*/
jssp.Core.run=function(pagePath,context){
if(!jssp.pageLoaderInstance){
//jssp引擎初始化
if(jssp.Config.cachable)jssp.cacheInstance=eval("new"+jssp.Config.cacheClass+"();");
jssp.pageLoaderInstance=eval("new"+jssp.Config.pageLoaderClass+"();");
}
varkey=pagePath;if(key.indexOf("?")>0)key=key.substring(0,key.indexOf("?"));
varprocesser=jssp.Config.cachable?jssp.cacheInstance.get(key):null;
if(!processer){
eval("processer="+jssp.Core.parse(jssp.pageLoaderInstance.loadPage(pagePath)));
if(jssp.Config.cachable)jssp.cacheInstance.set(key,processer);
}else{
//alert("cache")
}
if(!context)
context=newjssp.Context(pagePath);
else
context=newjssp.Context(pagePath,context);
returnprocesser(context);
}
//@-----------------------------------------------------------------------------------AJAX加载页面实现
jssp.Core.PageLoader.Ajax=function(){}
jssp.Core.PageLoader.Ajax.prototype.loadPage=function(pagePath){
varcontent=jssp.Ajax.send(pagePath,"GET",false);
if(!content){
alert("请求页面:"+pagePath+"返回为null!");returnnull;
}
returncontent;
}
//@-----------------------------------------------------------------------------------AJAX操作实现
jssp.Ajax=function(){}
/**
*建立HTTP连接
*/
jssp.Ajax.createHttpRequest=function(){
if(window.XMLHttpRequest)
returnnewXMLHttpRequest();
varrequest=null;
try{
request=newActiveXObject("Msxml2.XMLHTTP.4.0");
}catch(e){
try{
request=newActiveXObject("Msxml2.XMLHTTP");
}catch(e){
try{
request=newActiveXObject("microsoft.XMLHTTP");
}catch(e){
throw"XMLHTTPRequest组件客户端不支持!";
}
}
}
returnrequest;
}
/**
*发送AJAX请求
*@paramurl请求页面
*@parammethod请求方法getorpost
*@paramasync是否为异步调用
*@paramcallback回调函数
*@parampreHook调用前执行函数
*@parampostHook调用后请求返回执行函数
*/
jssp.Ajax.send=function(url,method,async,callback,preHook,postHook){
method=method.toUpperCase();
if(typeofpreHook=="function")preHook();
varrequest=jssp.Ajax.createHttpRequest();
request.open(method,url,async);
if(async){
if(typeofcallback!="function")throw"必须要设置回调函数";
request.onreadystatechange=function(){
jssp.Ajax.callback(request,callback,postHook);
};
}
request.send(null);
if(!async){
if(request.status==200||request.status==304)
returnjssp.Ajax._chartset(request);
else
returnnull;
}
}
/**
*接受响应,调用自定义回调函数
*/
jssp.Ajax.callback=function(response,callback,postHook){
if(response.readyState!=4)return;
vartext;
if(response.status==200||response.status==304){
text=jssp.Ajax._chartset(response);
}
callback(text);
if(typeofpostHook=="function")postHook();
}
/**
*中文乱码处理
*/
jssp.Ajax._chartset=function(r){
vart=bytes2BSTR(r.responseBody);
returnt;
}
jssp.Config.pageLoaderClass="jssp.Core.PageLoader.CustomerInput";//设置页面读取接口
jssp.Config.cachable=false;
jssp.Core.PageLoader.CustomerInput=function(){}
jssp.Core.PageLoader.CustomerInput.prototype.loadPage=function(pagePath){
if(pagePath.substring(0,10)!="hello.jssp")return"测试包含子页面,路径:"+pagePath;
returndocument.getElementById("pageContent").value;
}
functionshowPage(){
jssp.render("hello.jssp?name="+Math.random(),"pageArea");
}
输入JSSP脚本内容:
<%
varbeginTime=newDate();
for(vari=0;i<100;i++){
varcolor=i%2?"#eeeeee":"#aaaaaa";
%>
<%}%>
<%
window.alert("耗时:"+(newDate()-beginTime)+"ms");
%>