http://bbs.51js.com/thread-65160-1-1.html <html xmlns="http://www.w3.org/1999/xht... <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> <title>jssp演示</title> <script language="javascript"> /** * @description: * 使用javascript模仿JSP的页面解析和运行,运行于客户端 * 允许应用人员象开发JSP页面一样使用<%..%> * 允许页面动态包括子页面(同步读取页面) * **/ //@--------------------------------------------------------------------- JSSP声明 var jssp=function(){}; /** * 页面缓存管理实例对象 */ jssp.cacheInstance=null; /** * 页面加载实例对象 */ jssp.pageLoaderInstance=null; /** * 在指定dom插入pagePath的执行后的页面内容 */ jssp.render=function(pagePath,dom){ if(typeof dom=="string") dom=document.getElementById(dom); var content=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){ return this.caches[key]; } //@----------------------------------------------------------------------- JSSP运行上下文类 /** * jssp页面的执行上下文对象 * @member params 请求参数数组 * @member cookies 操作cookies对象 jssp.Cookies * @member out 页面流输出对象 jssp.Out * @method setAttribute 设置上下文参数 * @method getAttribute 得到上下文参数 * @method removeAttribute 删除上下文参数 * @method include 动态包含子页面 * @method getCookies,getParameter,getParameters,getOut * @param pageUrl 运行的上下文参数 * @param context 父页面的上下文对象 */ jssp.Context=function(pageUrl,context){ this.params=this._resolveParam(pageUrl); if(!context){ this.cookies=jssp.Cookies; this.out=new jssp.Out(); this.attributes=[]; }else{ this.context=context; this.isIncluded=true; } } /** * 解析页面后缀参数 */ jssp.Context.prototype._resolveParam=function(pageUrl){ var i1=pageUrl.indexOf("?"); if(i1<=0) return []; pageUrl=pageUrl.substring(i1+1); var s1=pageUrl.split("&"); var params=[]; for(var i=0;i<s1.length;i++){ var s2=s1[i].split("="); var key=s2[0];var value=s2[1]; var ps=params[key]; if(!ps) ps=[]; ps[ps.length]=value; params[key]=ps; } return params; } /** * 设置参数值 */ 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) return this.attributes[key]; else return this.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){ var ps=this.params[key]; if(!ps) return this.context?this.context.getParameter(key):undefined; return ps.join(","); } /** * 得到有重复参数的值 */ jssp.Context.prototype.getParameters=function(key){ var pss=this.params[key]; if(!pss) pss=this.context?this.context.getParameters(key):undefined; return pss; } /** * 得到cookies对象 */ jssp.Context.prototype.getCookies=function(){ if(!this.context) return this.cookies; else return this.context.getCookies(); } /** * 得到输出流OUT对象 */ jssp.Context.prototype.getOut=function(){ if(!this.context) return this.out; else return this.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){ var aCookie=document.cookie.split("; "); for(var i=0;i<aCookie.length;i++){ var aCrumb=aCookie[i].split("="); if(key==aCrumb[0]) return unescape(aCrumb[1]); } } /** * 删除cookies项 */ jssp.Cookies.remove=function(key){ document.cookie=key+"=null; expires=Fri, 31 Dec 1999 23:59:59 GMT;"; } //@------------------------------------------------------------------------ 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(){ var data=this.datas.join(""); this.datas=[];this._index=0; return data; } //@--------------------------------------------------------------------------JSSP页面核心类声明 jssp.Core=function(){} //@--------------------------------------------------------------------------JSSP页面解析实现类 /** * 页面解析 * @param pageContent JSSP页面内容 */ jssp.Core.parse=function(pageContent){ var strBuffer=[];//解析后文本存放的缓冲区 var point=0;//缓冲区指针 var lineNumber=1;//解析的当前行 try{ var betweenPerc=false; var isPrint=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('"; var line=""; var value=pageContent; var len=value.length; for(var i=0;i<len;i++){ var nextTwo=""; if(i<=len-2) nextTwo=value.charAt(i)+value.charAt(i+1); var nextThree=""; if(i<=len-3) nextThree=nextTwo+value.charAt(i+2); if(nextTwo=="<%"&&nextThree!="<%="&&nextThree!="<%@"){ strBuffer[point++]="'));n"; betweenPerc=true; i+=1; }else if(nextTwo=="<%"&&nextThree=="<%="&&nextThree!="<%@"){ strBuffer[point++]=escape(line)+"'));n"; line=""; strBuffer[point++]=" $out.print( "; betweenPerc=true; isPrint=true; i+=2; }else if(nextTwo=="<%"&&nextThree!="<%="&&nextThree=="<%@"){ i+=3; var directive=""; 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++; }else if(nextTwo=="%>"){ strBuffer[point++]=(isPrint?");":"")+"n $out.print(unescape('"; if(!betweenPerc) throw new jssp.Core.parse.ParseException("解析错误","必须用'%>'作为结束标签"); betweenPerc=false; isPrint=false; i+=1; }else if(value.charAt(i)==String.fromCharCode(10)){ if(!betweenPerc){ strBuffer[point++]=escape(line)+"\n'));n"+" $out.print(unescape('"; line=""; lineNumber++; } }else if(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 ""+"An exception occurred while parsing on line "+lineNumber+". Error type: "+e.name+". Error message: "+e.message+"";"; strBuffer[point++]="}"; } var out=strBuffer.join(""); return out; } /** * 解析指示头 */ jssp.Core.parse._handleDirective=function(directive){ var i = 0; var tolkenIndex = 0; var tolken = new Array(); //Skip first spaces; while ( directive.charAt(i) == ' ' ) { i++; } tolken[tolkenIndex] = ""; while ( directive.charAt(i) != ' ' && i <= directive.length ) { tolken[tolkenIndex] += directive.charAt(i); i++; } tolkenIndex++; //Skip first spaces; while ( directive.charAt(i) == ' ' ) { i++; } tolken[tolkenIndex] = ""; while ( directive.charAt(i) != ' ' && directive.charAt(i) != '=' && i <= directive.length ) { tolken[tolkenIndex] += directive.charAt(i); i++; } tolkenIndex++; //Skip first spaces; while ( directive.charAt(i) == ' ' ) { i++; } if( directive.charAt(i) != '=' ) throw new jssp.Core.parse.ParseException("Sintax error", "Tolken = expected attribute"); i++ //Skip first spaces; while ( directive.charAt(i) == ' ' ) { i++; } tolken[tolkenIndex] = ""; while ( directive.charAt(i) != ' ' && i <= directive.length ) { tolken[tolkenIndex] += directive.charAt(i); i++; } tolkenIndex++; //Skip first spaces; 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 ) throw new jssp.Core.parse.ParseException("Sintax error", "Tolken = expected after attribute" ); i++ tolken[tolkenIndex] = ""; while ( directive.charAt(i) != ' ' && i <= directive.length && i <= directive.length ) { tolken[tolkenIndex] += directive.charAt(i); i++; } var file = ""; var context = ""; if ( tolken[0] != "include" ) throw new jssp.Core.parse.ParseException("Sintax error","Directive " + tolken[0] + " unknown.") ; if ( tolken[1] != "file" ) throw new jssp.Core.parse.ParseException("Sintax error", "Attribute file expected after include." ); else file = tolken[2]; if ( tolken[3] != "context" && tolken[3] != "" ) throw new jssp.Core.parse.ParseException( "Sintax error", "Attribute context expected after file."); else if ( tolken[3] == "context" ) context = tolken[4] else context = "$context"; var out = "$context.include(" + file + ");n"; return out; } /** * 解析异常 */ 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 "不能直接调用接口或您还未实现此方法!";} //@--------------------------------------------------------------------------------页面运行实现方法 /** * @param pagePath 加载页面 * @parma context 上下文对象 */ 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+"();"); } var key=pagePath;if(key.indexOf("?")>0) key=key.substring(0,key.indexOf("?")); var processer=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=new jssp.Context(pagePath); else context=new jssp.Context(pagePath,context); return processer(context); } //@-----------------------------------------------------------------------------------AJAX加载页面实现 jssp.Core.PageLoader.Ajax=function(){} jssp.Core.PageLoader.Ajax.prototype.loadPage=function(pagePath){ var content=jssp.Ajax.send(pagePath,"GET",false); if(!content) { alert("请求页面:"+pagePath+" 返回为null!");return null; } return content; } //@-----------------------------------------------------------------------------------AJAX操作实现 jssp.Ajax=function(){} /** * 建立HTTP连接 */ jssp.Ajax.createHttpRequest=function(){ if(window.XMLHttpRequest) return new XMLHttpRequest(); var request=null; try{ request=new ActiveXObject("Msxml2.XMLHTTP.4.0"); }catch(e){ try{ request=new ActiveXObject("Msxml2.XMLHTTP"); }catch(e){ try{ request=new ActiveXObject("microsoft.XMLHTTP"); }catch(e){ throw "XMLHTTPRequest组件客户端不支持!"; } } } return request; } /** * 发送AJAX请求 * @param url 请求页面 * @param method 请求方法 get or post * @param async 是否为异步调用 * @param callback 回调函数 * @param preHook 调用前执行函数 * @param postHook 调用后请求返回执行函数 */ jssp.Ajax.send=function(url,method,async,callback,preHook,postHook){ method=method.toUpperCase(); if(typeof preHook=="function") preHook(); var request=jssp.Ajax.createHttpRequest(); request.open(method,url,async); if(async){ if(typeof callback!="function") throw "必须要设置回调函数"; request.onreadystatechange=function(){ jssp.Ajax.callback(request,callback,postHook); }; } request.send(null); if(!async) { if(request.status==200||request.status==304) return jssp.Ajax._chartset(request); else return null; } } /** * 接受响应,调用自定义回调函数 */ jssp.Ajax.callback=function(response,callback,postHook){ if(response.readyState!=4) return; var text; if(response.status==200||response.status==304){ text=jssp.Ajax._chartset(response); } callback(text); if(typeof postHook=="function") postHook(); } /** * 中文乱码处理 */ jssp.Ajax._chartset=function(r){ var t=bytes2BSTR(r.responseBody); return t; } </script> <script language="javascript"> 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; return document.getElementById("pageContent").value; } function showPage(){ jssp.render("hello.jssp?name="+Math.random(),"pageArea"); } </script> <style type="text/css"> <!-- .STYLE1 {color: #FFFFFF} --> </style> </head> <body> 输入JSSP脚本内容: <textarea id="pageContent" style="width:100%;" rows="15"> <table width="100%" border="0" align="center" cellpadding="4" cellspacing="2"> <tr> <td align="center" valign="middle" bgcolor="#666699"><span class="STYLE1">order</span></td> <td align="center" valign="middle" bgcolor="#666699"><span class="STYLE1">number1</span></td> <td align="center" valign="middle" bgcolor="#666699"><span class="STYLE1">number2</span></td> <td align="center" valign="middle" bgcolor="#666699"><span class="STYLE1">number3</span></td> </tr> <% var beginTime=new Date(); for(var i=0;i<100;i++){ var color=i%2?"#eeeeee":"#aaaaaa"; %> <tr bgcolor="<%=color%>"> <td align="center" valign="middle" ><%=i%></td> <td align="center" valign="middle" ><%=Math.random()%></td> <td align="center" valign="middle" ><%=Math.random()%></td> <td align="center" valign="middle" ><%=Math.random()%></td> </tr> <%}%> </table> <% window.alert("耗时:"+(new Date()-beginTime)+"ms"); %> </textarea> <button onClick="showPage()">显示内容</button> <hr> <div id="pageArea"></div> </hr> </body> </html>
推荐阅读
javascript生成/解析dom的CDATA类型的字段的代码
两段demo代码如下(for ie only): <script type="text/javascript"> //demo1 var xmlDoc = new ActiveXObject("Msxml2.DOMDocument"); var root; var CDATASection; xmlDoc.async = false; xmlD>>>详细阅读
本文标题:仿服务器端脚本方式的JS模板实现方法
地址:http://www.17bianji.com/kaifa2/JS/30532.html
1/2 1