$package('com.trs.ajaxframe'); $import('com.trs.util.JSON'); $import('com.trs.util.XML'); $import('com.trs.ajaxframe.DataSource'); $import('com.trs.ajaxframe.TrsAjaxElement'); $import('com.trs.ajaxframe.DataSourcePool'); $import('com.trs.ajaxframe.Navigate'); $import('com.trs.ajaxframe.Action'); $import('com.trs.ajaxframe.Service'); $import('com.trs.ajaxframe.DataHelper'); $import('com.trs.ajaxframe.PostData'); $import('com.trs.ajaxframe.Instances'); $import('com.trs.log.Logger'); $import('com.trs.ajaxframe.Implements'); $import('com.trs.ajax.Request'); $import('com.trs.dialog.Dialog'); /** * 置标解析类 * @author TRS WCM */ com.trs.ajaxframe.TagParser = Class.create('ajaxframe.TagParser'); com.trs.ajaxframe.TagParser.prototype = { /**命名空间*/ nameSpace : 'TRS', /**数据源池*/ dataSourcePool : null, /**URL参数*/ urlQuery : null, /**缓存的页面AJAX DOM*/ pageTrsAjaxDoms : null, /**页面级的事件监听器*/ listeners : null, /**缺省的onCreate方法*/ onCreate : null, /**缺省的onSuccess方法*/ onSuccess : null, /**缺省的on500方法*/ on500 : null, /**缺省的onFailure方法*/ onFailure : null, /** * 构造函数 * @param _sNameSpace 命名空间 */ initialize : function(_sNameSpace) { this.nameSpace = _sNameSpace; this.dataSourcePool = $dataSourcePool; var urlQuery = location.search.replace(/\?/g,'').parseQuery(); this.urlQuery = {}; for(var param in urlQuery){ this.urlQuery['$'+param.toUpperCase()] = urlQuery[param]; } delete urlQuery; this.pageTrsAjaxDoms = {}; this.listeners = {}; this._func_onload = this.onload.bind(this); this.enableAutoLoad(); this.onCreate = Prototype.emptyFunction; this.onSuccess = Prototype.emptyFunction; this.on500 = Prototype.emptyFunction; this.onFailure = Prototype.emptyFunction; Event.observe(window, 'unload',this.destroy.bind(this)); }, /** * 开启自动加载功能 */ enableAutoLoad : function(){ Event.observe(window, 'load',this._func_onload, false); }, /** * 关闭自动加载功能 */ disableAutoLoad : function(){ Event.stopObserving(window, 'load',this._func_onload, false); }, /** * 注册数据源置标上的事件监听器 * @param _sDatonId 数据源置标id * @param _sEvent 事件名 * @param _fObserver 事件监听方法 */ observe : function(_sDatonId,_sEvent,_fObserver){ if(typeof _sDatonId != 'string'){ _sDatonId = _sDatonId.id; } if(!this.listeners[_sDatonId]){ this.listeners[_sDatonId] = {}; } this.listeners[_sDatonId][_sEvent] = _fObserver; }, /** * 取消注册数据源置标上的事件监听器 * @param _sDatonId 数据源置标id * @param _sEvent 事件名 */ unobserve : function(_sDatonId,_sEvent){ if(typeof _sDatonId != 'string'){ _sDatonId = _sDatonId.id; } if(this.listeners[_sDatonId]){ this.listeners[_sDatonId][_sEvent] = null; } }, /** * 私有方法 * 页面数据源的TrsAjaxDom数据 * @param _sDsId 数据源置标id */ _TrsAjaxDom:function(_sDsId){ return this.pageTrsAjaxDoms[_sDsId]; }, /** * 页面加载时初始化所有的数据源置标并加载数据源置标 */ onload : function(){ // $log().info('onload'); var vTagNames=this.dataSourcePool.tagNames; var elDatons=[]; for(var i=0;i * $开头的,从_oParams中取值,包括优先从URL参数中取值
* #开头的,从_oJson中取值,数据域将附加上_sSelection前缀
* @param _sSource 字符串文本 * @param _oJson 存储XML数据的JS对象 * @param _oParams 存储特殊参数的对象 * @param _sSelection 当前数据域的前缀 * @return 数据填充成功的值 */ _fillValue : function(_sSource , _oJson , _oParams ,_sSelection){ try{ if(typeof _sSource!='string'){ _sSource = ''; // throw new Error('非字符串不能进行转换:'+_sSource); } _oParams = _oParams || {}; _oJson = _oJson || {}; var pattern = '\\{\\$+[^\\}]{0,100}\\}|\\{#[^\\}]{0,100}\\}'; var regExp = new RegExp(pattern,'ig'); var vReturn = ''; var aCaptures = null; var sCapture = null; var sParam = null; var sSelection = null; var sValue = ''; var sDefault = ''; var sCmd = ''; var lastIndex = 0; while((aCaptures = regExp.exec(_sSource))!=null){ vReturn += _sSource.substring(lastIndex,aCaptures.index); sCapture = aCaptures[0]; if(sCapture.startsWith('{$')){//param sParam = sCapture.substring(1 , sCapture.length-1); var aAction = sParam.split(','); sParam = aAction[0].toUpperCase(); sDefault = aAction[1] || ''; sValue = this.urlQuery[sParam] || _oParams[sParam]; if(sValue==null || sValue==''){ sValue = sDefault; } sCmd = aAction[2]; if(sCmd){ try{ sValue = sValue.replace(/([\\\'\"])/g,"\\$1").replace(/\n(\r)?/g,""); sValue = eval(sCmd+'("'+sValue+'")'); sValue = sValue.replace(//g,'\n'); }catch(err){ throw new Error('error occurs when eval \''+sCmd+'("'+sValue+'")'+'\''); } } } else if(sCapture.startsWith('{#')){//selection sSelection = sCapture.substring(2 , sCapture.length-1); if(_sSelection){ sSelection = _sSelection + '.' + sSelection; } var aAction = sSelection.split(','); sSelection = aAction[0].toUpperCase(); sDefault = aAction[1] || ''; sValue = com.trs.ajaxframe.TagHelper.value(sSelection , _oJson); if(sValue==null || sValue==''){ sValue = sDefault; } sCmd = aAction[2]; if(sCmd){ try{ sValue = sValue.replace(/([\\\'\"])/g,"\\$1").replace(/\n(\r)?/g,""); sValue = eval(sCmd+'("'+sValue+'")'); sValue = sValue.replace(//g,'\n'); }catch(err){ throw new Error('error occurs when eval \''+sCmd+'("'+sValue+'")'+'\''); } } } vReturn += sValue; lastIndex = aCaptures.index + aCaptures[0].length; } vReturn += _sSource.substring(lastIndex); return vReturn; }catch(err){ $log().error(err.message); } }, /** * 转换成AJAX DOM对象的递归方法
* ------------------------------------
* 根据不同的节点名,返回不同的AJAX DOM实例:
* DS ==> com.trs.ajaxframe.TrsAjax.Ds
* DATASOURCE ==> com.trs.ajaxframe.TrsAjax.InnerDs
* FOR ==> com.trs.ajaxframe.TrsAjax.FOR
* PARAM ==> com.trs.ajaxframe.TrsAjax.PARAM
* VALUE ==> com.trs.ajaxframe.TrsAjax.VALUE
* IF ==> com.trs.ajaxframe.TrsAjax.IF
* RECORD ==> com.trs.ajaxframe.TrsAjax.RECORD
* NAVIGATE ==> com.trs.ajaxframe.TrsAjax.NAVIGATE
* others ==> com.trs.ajaxframe.TrsAjax.Element
* -------------------------------------
* 根据特殊的条件,子节点进行不同的处理:
* nodeName=='#TEXT' || nodeName=='SCRIPT' ==> 子节点直接返回 com.trs.ajaxframe.TrsAjax.Element
* nodeName=='#COMMENT'==> 过滤
* 属于扩展置标More Custom Tag ==> 子节点直接返回 com.trs.ajaxframe.TrsAjax.Element
* 含有justReplace==true属性 ==> 子节点直接返回 com.trs.ajaxframe.TrsAjax.Element
* otherwise ==> 递归调用本方法返回DOM实例
* --------------------------------------
* @param _sNodeName 当前置标节点名 * @param _eElement 当前置标Element对象 * @param _eParent 当前置标的Parent Element对象 * @return AJAX DOM对象 */ toTrsAjaxDom:function(_sNodeName , _eElement , _eParent){ var trsAjaxElement = null; switch(_sNodeName){ case 'DS': trsAjaxElement = new com.trs.ajaxframe.TrsAjax.Ds(_sNodeName , _eElement , _eParent); break; case 'DATASOURCE': trsAjaxElement = new com.trs.ajaxframe.TrsAjax.InnerDs(_sNodeName , _eElement , _eParent); break; case 'FOR': trsAjaxElement = new com.trs.ajaxframe.TrsAjax.For(_sNodeName , _eElement , _eParent); break; case 'PARAM': trsAjaxElement = new com.trs.ajaxframe.TrsAjax.Param(_sNodeName , _eElement , _eParent); return trsAjaxElement; case 'VALUE': trsAjaxElement = new com.trs.ajaxframe.TrsAjax.Value(_sNodeName , _eElement , _eParent); return trsAjaxElement; case 'IF': trsAjaxElement = new com.trs.ajaxframe.TrsAjax.If(_sNodeName , _eElement , _eParent); break; case 'RECORD': trsAjaxElement = new com.trs.ajaxframe.TrsAjax.Record(_sNodeName , _eElement , _eParent); break; case 'NAVIGATE': trsAjaxElement = new com.trs.ajaxframe.TrsAjax.Nav(_sNodeName , _eElement , _eParent); break; default: trsAjaxElement = new com.trs.ajaxframe.TrsAjax.Element(_sNodeName , _eElement , _eParent); } var childTrsAjaxElement = null; for(;_eElement.childNodes.length>0;) { var currChildElement = _eElement.childNodes[0]; currChildElement = _eElement.removeChild(currChildElement); var nodeName = currChildElement.nodeName.toUpperCase(); if(!_IE){ nodeName = nodeName.replace(new RegExp(this.nameSpace+':','i'),''); } if(this.dataSourcePool.tagNames.include(nodeName)){ nodeName = 'DATASOURCE'; } if(nodeName=='#TEXT'){ childTrsAjaxElement = new com.trs.ajaxframe.TrsAjax.Element('#TEXT' , currChildElement , trsAjaxElement); } else if(nodeName=='#COMMENT'){ continue; } else if(currChildElement.getAttribute('justReplace')){ childTrsAjaxElement = new com.trs.ajaxframe.TrsAjax.Element(nodeName , currChildElement , trsAjaxElement); } else if(this['_parse_'+nodeName]){//More Custom Tag childTrsAjaxElement = new com.trs.ajaxframe.TrsAjax.Element(nodeName , currChildElement , trsAjaxElement); } else if(nodeName=='SCRIPT'){ childTrsAjaxElement = new com.trs.ajaxframe.TrsAjax.Element(nodeName , currChildElement , trsAjaxElement); } else{ childTrsAjaxElement = this.toTrsAjaxDom(nodeName , currChildElement , trsAjaxElement); } trsAjaxElement.pushChild(childTrsAjaxElement); } return trsAjaxElement; }, /** * 分页导航 * @param _sDatonId 数据源置标的Id * @param _iPage 欲跳转的分页数 */ go:function(_sDatonId,_iPage){ var trsAjaxDom = this._preLoadData(_sDatonId , null); var elDaton = trsAjaxDom.element; var dsParams = elDaton.getAttribute('params'); dsParams = (dsParams)?dsParams.trim():''; elDaton.setAttribute('currentPage',_iPage||1); this._loadData( trsAjaxDom , dsParams , null , _iPage||1 ); }, /** * 私有方法 * 数据源置标监听器响应事件 * @param _eDaton 数据源置标对象 * @param _oTransport 传递的参数1 * @param _oJson 传递的参数2 * @param _sEvent 事件名 */ _fireEvent : function(_eDaton , _oTransport , _oJson ,_sEvent){ // $log().info("_fireEvent:"+_sEvent); var sDatonid = _eDaton.id; try{ if(this.listeners[sDatonid]){ if(this.listeners[sDatonid][_sEvent]){ (this.listeners[sDatonid][_sEvent]).call($(sDatonid),_oTransport, _oJson); } } }catch(err){ $log().error('error occurs when TagParser Datasource _fireEvent "'+_sEvent+'":\n'+err.message); } }, /** * 私有方法 * 数据源置标监听器响应事件(create) * @see _fireEvent */ _onCreate : function(_eDaton , _oTransport , _oJson){ this._fireEvent(_eDaton , _oTransport , _oJson , 'create'); }, /** * 私有方法 * 数据源置标监听器响应事件(success) * @see _fireEvent */ _onSuccess:function(_eDaton , _oTransport , _oJson){ this._fireEvent(_eDaton , _oTransport , _oJson , 'success'); }, /** * 私有方法 * 数据源置标监听器响应事件(failure) * @see _fireEvent */ _onFailure:function(_eDaton , _oTransport , _oJson){ this._fireEvent(_eDaton , _oTransport , _oJson , 'failure'); }, /** * 私有方法 * 数据源置标监听器响应事件(500) * @see _fireEvent */ _on500:function(_eDaton , _oTransport , _oJson){ this._fireEvent(_eDaton , _oTransport , _oJson , '500'); }, /** * 私有方法 * 数据源数据加载完成时调用方法,完成数据源置标的数据填充 * @param _oScenes 异步提交时的现场数据 * @param _oTransport AJAX请求的Transport对象 * @param _oJson JSON对象 * @param _fCallBack 回调函数 */ _onSuccessing : function(_oScenes , _oTransport, _oJson , _fCallBack){ // $log().info("_onSuccessing"); var oDataSource = _oScenes.oDataSource; var eDataSource = _oScenes.eDataSource; var oTrsAjaxDom = _oScenes.oTrsAjaxDom; var vParams = _oScenes.oParams||{}; //added by gongfuchang //为了实现远程服务器控制翻页的效果 var sCurrPageKey = oDataSource.currPageKey; if (sCurrPageKey){ var sCurrPage = com.trs.util.JSON.value(_oJson, sCurrPageKey); if (sCurrPage) eDataSource.setAttribute('currentPage', sCurrPage); } try{ oTrsAjaxDom.parse(this , oDataSource , eDataSource , _oJson , vParams , '' , _oTransport , _fCallBack); }catch(err){ $log().error(err.message+'\n'+(err.stack||'')); } }, /** * 私有方法 * 当前节点所在的dataSource置标 * @param _eElement HTML Element对象 * @return 数据源置标对象 */ _dataSourceTag:function(_eElement){ var pNode=_eElement.parentNode; while(pNode) { var tagName=pNode.tagName; if(tagName&&!_IE) { var index=tagName.indexOf(':')+1; tagName=tagName.substring(index); } if(tagName){ tagName=tagName.toUpperCase(); if(this.dataSourcePool.tagNames.include(tagName))break; } pNode=pNode.parentNode; } return pNode; }, /** * 私有方法 * 为数据源绑定事件 * @param _eDaton 数据源置标对象 * @param _bPageScope 是否为页面级域数据源 */ _bindEvents : function( _eDaton , _bPageScope) { var createFunc = _eDaton.getAttribute("onCreate"); var successFunc = _eDaton.getAttribute("onSuccess"); var failureFunc = _eDaton.getAttribute("onFailure"); var _500Func = _eDaton.getAttribute("on500"); var _sDatonid = _eDaton.id; if( createFunc != null) { this.observe( _sDatonid , 'create' , function(){eval(createFunc);}); } else if(_bPageScope){ this.observe( _sDatonid , 'create' , this.onCreate); } if( successFunc != null) { this.observe( _sDatonid ,'success' , function(){eval(successFunc);}); } else if(_bPageScope){ this.observe( _sDatonid , 'success' , this.onSuccess); } if( _500Func != null) { this.observe( _sDatonid , '500' , function(){eval(_500Func);}); } else if(_bPageScope){ this.observe( _sDatonid , '500' , this.on500); } if( failureFunc != null) { this.observe( _sDatonid , 'failure' , function(){eval(failureFunc);}); } else if(_bPageScope){ this.observe( _sDatonid , 'failure' , this.onFailure); } }, /** * 私有方法 * 异步加载数据源的数据并填充数据源置标 * @param _trsAjaxDom AJAX DOM对象 * @param _sDsParams 请求参数 * @param _sMethodAbout CallBind的相关参数 */ _loadData : function(_trsAjaxDom , _sDsParams , _sMethodAbout , _iPage){ var eDaton = _trsAjaxDom.element; this._bindEvents(eDaton , true); this._onCreate(eDaton); _sDsParams = this._fillValue(_sDsParams || '' , null , null , '' ); _sMethodAbout = _sMethodAbout || {}; var sMethod = _sMethodAbout['method'] || eDaton.getAttribute('method'); if(sMethod!=null){ eDaton.setAttribute('method' , sMethod); } sMethod = (sMethod) ? sMethod : 'GET'; var dataSource = this.$datasource(eDaton); if( ! dataSource.isLocal ){ if(_iPage){ _sDsParams = _sDsParams.replace(new RegExp('^((.*)&|)'+dataSource.pageKey+'=[^&]*','ig'),'$2'); } if(!_sDsParams||!_sDsParams.match(new RegExp('^(.*&|)'+dataSource.pageKey+'=','ig'))){ var page = eDaton.getAttribute('currentPage') || 1; _sDsParams = (_sDsParams) ? (_sDsParams+'&') : ''; _sDsParams += dataSource.pageKey + '=' + page; } } var scenes = { oDataSource : dataSource, eDataSource : eDaton, oTrsAjaxDom : _trsAjaxDom }; var caller = this; var options = { onSuccess : function(transport , vJson , _fCallBack){caller._onSuccessing(this , transport , vJson , _fCallBack);}.bind(scenes), on500 : function(transport , vJson){caller._on500(this , transport , vJson);}.bind(eDaton), onFailure : function(transport , vJson){caller._onFailure(this , transport , vJson);}.bind(eDaton), asynchronous : true }; setTimeout(function(){ switch ( sMethod.toUpperCase() ){ case 'GET': dataSource.get(_sDsParams , options); break; case 'FINDBYIDS': var sIds = _sMethodAbout['ids']; if( ! sIds ) { sIds = eDaton.getAttribute("params"); sIds = this._fillValue(sIds || '' , null , null , '' ); } dataSource.findByIds(_sDsParams , sIds , options); break; default: var oPostData = _sMethodAbout['postData'] || null; var bSend = _sMethodAbout['bSend'] || false; dataSource.call(sMethod , oPostData , _sDsParams , bSend , options); break; } }.bind(caller),1); }, /** * 私有方法 * 生成导航条的HTML代码 * @param _eDaton 导航条对应的数据源置标对象 * @param _oDataSource 导航条对应的数据源对象 * @param _oJson 导航条对应的数据JSON对象 * @param _oOptions 导航条对应的参数对象,以构造不同的导航条 */ _navigate:function(_eDaton,_oDataSource,_oJson,_oOptions){ var recordsNum=_oDataSource.recordsNum(_oJson); var pageSize=_oDataSource.pageSize(_oJson); var currentPage=_eDaton.getAttribute("currentPage"); var id=_eDaton.getAttribute("id"); currentPage=(currentPage)?parseInt(currentPage):1; var pages=parseInt((recordsNum+pageSize-1)/pageSize); var type=(_oOptions.type)?_oOptions.type.toLowerCase():'list'; var s=[]; if(type=='list'){ for(var i=1;i<=pages;i++){ s.push((_oOptions.page||Prototype.K)(id,i,i==currentPage)); } s.push((_oOptions.more||Prototype.emptyFunction)()); } else if(type=='normal'){ if(pages>1){ s.push((_oOptions.button||Prototype.K)(id,1,currentPage==1,1)); s.push((_oOptions.button||Prototype.K)(id,currentPage-1,currentPage<=1,2)); s.push((_oOptions.button||Prototype.K)(id,currentPage+1,currentPage>=pages,3)); s.push((_oOptions.button||Prototype.K)(id,pages,currentPage==pages,4)); } } return s.join((_oOptions.space||Prototype.emptyFunction)()); }, destroy:function(){ $destroy(this); } };