/* DynAPI Distribution DataSource Class The DynAPI Distribution is distributed under the terms of the GNU LGPL license. requires: dynapi.util.IOElement */ DataSource = function(url,method,ioelement){ this.EventObject=EventObject; this.EventObject(); this.clsid=dynapi.functions.getGUID(); DataSource.all[this.clsid]=this; this.src=null; this.dataobjects={}; this._resetProperties(); this.setSource(url,method,ioelement); }; /* Prototype */ var p = dynapi.setPrototype('DataSource','EventObject'); // Private Methods p._boundObject = function(o,f){ if(!f || !o) return; if(!o._clsid) o._clsid=DataSource.increment(); this.dataobjects[o._clsid]=f; o.__iDataSource=this; DataSource.allDataObjects[o._clsid]=o; }; p._fieldManager = function(mode,fld,value){ var i,rt,con,fldname; // set or get field values from local recordset or bound object if(mode=='GET' && !this._modRec && this.record) return this.record[fld]; else { if(mode=='SET' && this.record) this.record[fld]=value; for(i in this.dataobjects){ if (!fld||fld==this.dataobjects[i]){ fldname=this.dataobjects[i]; con=DataSource.allDataObjects[i]; if(con) { if(mode=='SET' && con._setDSValue) { con._setDSValue(value,fldname); }else if(mode=='GET' && con._getDSValue) { return con._getDSValue(); } } } } } }; p._resetProperties=function(){ this.record=null; this.recordSet=[]; this.rowCount=0; // total records this.rowIndex=-1; // current record index(0 to rowCount) this.pageSize=1; // number of recordSet per page this.pageCount=0; // total pages this.pageNumber=0; // current page number (1 to pageCount) this.pageRIS=-1; // starting index for a page this.pageRIE=-1; // ending index for a page this.isConnected=false; }; p._send = function(act,data,params){ var r,fn,cargo={id:this.clsid,action:act,data:data};; params =(params)? params:{}; if(!this.src||!this.isConnected) { this.invokeEvent('alert',null,'DataSource: Connection failed.'); return; } this.invokeEvent('request'); if(this.webservice && !this.wsSync) { // Web Service - Async fn=DataSource.fnSODAResponse; if(this._ticket) this.ioelement.cancel(this._ticket); // cancel any previous requests if(act=='fetchpage') this._ticket=this.webservice.call(act,[this.pageNumber,this.pageSize,params.pageType],fn,cargo); else this._ticket=this.webservice.call(act,[this.rowIndex,data],fn,cargo); } else if(this.webservice && this.wsSync) { // Web Service - Sync if(act=='fetchpage') r=this.webservice.call(act,[this.pageNumber,this.pageSize,params.pageType],false); else r=this.webservice.call(act,[this.rowIndex,data],false); if(r.error) this.invokeEvent('alert',null,'DataSource: '+r.error.text); else { data=r.value; if(!data) return; DataSource.fnProcessResponse(cargo,data); } } else { // HTTP GET & POST - Async fn=DataSource.fnGETPOSTResponse; data=(data)? data:{}; data.dataAction = act; if(act!='fetchpage') data.dataRowIndex=this.rowIndex; else { data.pageSize = this.pageSize; data.pageNumber = this.pageNumber; data.pageType=params.pageType; } if(this._ticket) this.ioelement.cancel(this._ticket); // cancel any previous requests if(this.method=='get') this._ticket=this.ioelement.get(this.src,data,fn,cargo); else this._ticket=this.ioelement.post(this.src,data,fn,cargo); } }; p._unboundObject = function(o){ if(!o._clsid) return; delete this.dataobjects[o._clsid]; delete DataSource.allDataObjects[o._clsid]; }; // Public Methods ------------------------------- p.addRecord = function(){ this._modRec=true; this._oldRowIndex=this.rowIndex; this._send('addrow'); }; p.cancelAction = function(norefresh){ if (this._cancelAct=='waiting') this._cancelAct=true; // cancel submit() else { // cancel either editRecord() or addRecord() operation this._cancelAct=true; if (this._modRec && this._oldRowIndex!=this.rowIndex) this.rowIndex=this._oldRowIndex; this._oldRowIndex=null; this._modRec=false; if(!norefresh) this.refresh(); } }; p.connect = function(fn,useWebService,useSync,uid,pwd){ // connects to the data source using the SODA web service this.ws_uid=uid; this.ws_pwd=pwd; this.wsSync=useSync; this._resetProperties(); if(!useWebService) { if(typeof(fn)!='function') return; this.isConnected=true; fn(this,true); }else if(IOElement.SODA){ this._callback=fn; if(typeof(useWebService)=='string') { // use an existing web service var s,et; this.webservice=this.ioelement[useWebService]; if (this.webservice && this.webservice.isConnected) { this.isConnected=true; s=true; et=''; }else{ this.webservice=null; s=false; et='Service not found'; } this._callback(this,s,et); }else{ // create a new web service var me=this; var cbFn=function(ws,s,et){ if(s==true) { me.webservice=ws; me.isConnected=true; } // notify caller of connection me._callback(me,s,et); } this.ioelement.createWebService(this.clsid,this.src,cbFn,useSync,uid,pwd,this.method); } } }; p.deleteRecord=function(){ this._send('deleterow'); }; p.editRecord = function(){ if(this._modRec) return; this._modRec=true; this._oldRowIndex=this.rowIndex; }; p.getField = function(fld){return this._fieldManager('GET',fld)}; p.getAbsolutePage = function() {return this.pageNumber}; p.getRecordPosition = function(){return this.rowIndex}; p.getPageCount = function() {return this.pageCount}; p.getPageSize = function() {return this.pageSize}; p.getPageStart = function(){return this.pageRIS}; p.getPageEnd = function(){return this.pageRIE}; p.getRecordCount = function(){return this.rowCount}; p.getRecord = function(n){ var i, data={}; if(!this._modRec || (n!=null && n!=this.rowIndex)) data=(n==null)?this.record:this.recordSet[n]; else { for (i in this.dataobjects){ f=this.dataobjects[i]; con=DataSource.allDataObjects[i]; data[f]=con._getDSValue(); } } return data; }; p.isEditMode = function(){return this._modRec}; p.moveFirst = function(){ if(this._modRec) this.cancelAction(true); if(this.pageSize<=1) this._send('movefirst'); else{ var r,cp=this.pageNumber; //current page var fetch=(cp!=1 || !this.recordSet.length); this.rowIndex=0; this.pageNumber=1; if (fetch) this._send('fetchpage',null,{pageType:'firstpage'}); else { r=this.recordSet[0]; this.setRecord(r); } } }; p.moveLast = function(){ if(this._modRec) this.cancelAction(true); if(this.pageSize<=1) this._send('movelast'); else{ var cp=this.pageNumber; //current page var lp=this.pageCount; // last page var fetch=(lp!=cp || !this.recordSet.length); this.pageNumber=lp; this.rowIndex=this.rowCount-1; if (fetch) { this.rowIndex=-2; // force rowIndex to be set to pageRIE this._send('fetchpage',null,{pageType:'lastpage'}); }else { r=this.recordSet[this.rowIndex]; this.setRecord(r); } } }; p.moveNext = function(){ if(this._modRec) this.cancelAction(true); this._modRec=false; if(this.pageSize<=1) this._send('movenext'); else{ var ps,cp,np,fetch; var r=(this.rowIndex+1); ps=this.pageSize; cp=this.pageNumber; //current page if(r<1) np=1; // new page else np=this.pageNumber=parseInt(r/ps)+1; fetch=(np!=cp || np>this.pageCount || !this.recordSet.length); if(r>=this.rowCount) {r=this.rowCount-1; fetch=true;} this.rowIndex=r; if (fetch) this._send('fetchpage',null,{pageType:'normalpage'}); else { r=this.recordSet[r]; this.setRecord(r); } } }; p.movePrev = function(){ if(this._modRec) this.cancelAction(true); if(this.pageSize<=1) this._send('moveprev'); else{ var ps,cp,np,fetch; var r=(this.rowIndex-1); ps=this.pageSize; cp=this.pageNumber; //current page if(r<1) np=1; // new page else np=this.pageNumber=parseInt(r/ps)+1; fetch=(np!=cp || np<1 || !this.recordSet.length); if(r<0) {r=0; fetch=true;} this.rowIndex=r; if (fetch) this._send('fetchpage',null,{pageType:'normalpage'}); else { r=this.recordSet[r]; this.setRecord(r); } } }; p.retry = function() { if(this._ticket) this.ioelement.retry(this._ticket); else if(!this.isConnected) this.ioelement.retry(); }; p.refresh = function(fld){ var record=this.record; if(!fld||!record) this.setRecordPosition(this.rowIndex); else if(record){ // refresh field from local cached data record this._fieldManager('SET',fld,record[fld]); } }; p.setAbsolutePage = function(n) { var cp=this.pageNumber; var np=parseInt(n); if(np>0 && np!=cp) { this.rowIndex=-1; // force rowIndex to be set on the new page this.pageNumber=np; this._send('fetchpage'); } }; p.setField = function(fld,value){ this._fieldManager('SET',fld,value); }; p.setPageSize = function(n) { this.pageSize=parseInt(n); if(this.pageSize<1) this.pageSize=1; this.pageNumber=0; // this will force moveFirst() to reload page this.moveFirst(); }; p.setRecord = function(data){ var vl,con,i,fld; if(!data) return; this.recordSet[this.rowIndex] = this.record = data; for(i in this.dataobjects){ fld=this.dataobjects[i]; con=DataSource.allDataObjects[i]; if(con){ vl=data[fld]; con._setDSValue(vl); } }; this.invokeEvent('recordchange'); }; p.setRecordPosition = function(n) { this.rowIndex=parseInt(n); if(this._modRec) this.cancelAction(true); if(this.pageSize<=1) this._send('moveto'); else { var ps,cp,np,fetch; var r=this.rowIndex; ps=this.pageSize; cp=this.pageNumber; //current page if(r<1) np=1; // new page else np=this.pageNumber=parseInt(r/ps)+1; fetch=(np!=cp || np>this.pageCount || !this.recordSet.length); if(r>=this.rowCount) {r=this.rowCount-1; fetch=true;} this.rowIndex=r; if (fetch) this._send('fetchpage',null,{pageType:'normalpage'}); else { r=this.recordSet[r]; this.setRecord(r); } } }; p.setSource = function(url,method,ioelement){ this.src=url; if(method) method=(method+'').toLowerCase(); if(method || !this.method) this.method=(method=='post'||method=='get')? method:'post'; if(ioelement) this.ioelement=ioelement; else if(!this.ioelement) this.ioelement=IOElement.getSharedIO(); }; p.submit = function(){ if (!this._modRec) this.invokeEvent('alert',null,'DataSource: Submit action canceled'); else { var data = this.getRecord(); this._cancelAct='waiting'; this.invokeEvent('validate',null,data); if(this._cancelAct==true) return; this._cancelAct=false; this._send('submitrow',data); } }; /* Non-Prototype */ DataSource._cnt=0; DataSource.all={}; DataSource.allDataObjects={}; DataSource.increment = function(){return 'dsObject'+(this._cnt++)}; DataSource._getFORMInput = function(){return this.value}; DataSource._setFORMInput = function(d){this.value=d}; DataSource._getFORMImage = function(){return this.src}; DataSource._setFORMImage = function(d){if(this.src) this.src=d;}; DataSource._getFORMSelect = function(){ var i,d=[]; for(i=0;i<this.options.length;i++) { if(this.options[i].selected) d[d.length]=this.options[i].value; }; return d.join(','); }; DataSource._setFORMSelect = function(d){ var i,a,o,ov={}; if (typeof(d)=='object'){ // clear <select> menu and display name/value pairs while(this.length>0) this.remove(0); for(i in d){ this.add(new Option(i,d[i])); } }else { // select values from <select> menu a=(d+'').split(','); for(i=0;i<a.length;i++) ov[a[i]]=true; for(i=0;i<this.options.length;i++) { o=this.options[i]; if(ov[o.value]) o.selected=true; else o.selected=false; }; } }; DataSource._getFORMCheckBox = function(){ if (!this.length) { if(this.checked) return this.value; }else { var i,chkv=[]; for(i=0;i<this.length;i++) { if(this[i].checked) chkv[chkv.length]=this[i].value; }; return chkv.join(','); } }; DataSource._setFORMCheckBox = function(d){ if (!this.length) { if(d==this.value) this.checked=true; else this.checked=false; }else { var i,chk,chkv={}; var a=(d+'').split(','); for(i=0;i<a.length;i++) chkv[a[i]]=true; for(i=0;i<this.length;i++) { chk=this[i]; if(chkv[chk.value]) chk.checked=true; else chk.checked=false; }; } }; DataSource._getFORMRadio= function(){ if (!this.length) { if(this.checked) return this.value; }else { for(var i=0;i<this.length;i++) { if(this[i].checked) return this[i].value; }; } }; DataSource._setFORMRadio= function(d){ if (!this.length) { if(d==this.value) this.checked=true; else this.checked=false; }else{ var i,rb; for(i=0;i<this.length;i++) { rb=this[i]; if(d==rb.value) rb.checked=true; else rb.checked=false; }; } }; DataSource._GetDataSource = function(){ return this.__iDataSource}; DataSource._SetDataSource = function(ds,field){ if(ds && ds._boundObject) ds._boundObject(this,field); }; DataSource.IsFormElm=function(o){ var ot,type=(o && o.type)? o.type+'':''; ot=type.replace(/hidden|textarea|text|button|submit|image|select|checkbox|radio/,''); if(type && ot!=type) return true; else return false; }; DataSource.createBoundObject = function(o,getfn,setfn){ if (typeof(o)=='object'){ if(!getfn && !setfn && this.IsFormElm(o)){ // check if form element var tp=(o.type+'').toLowerCase(); if(tp=='image') { getfn=this._getFORMImage; setfn=this._setFORMImage; }else if(tp.indexOf('select')==0) { getfn=this._getFORMSelect; setfn=this._setFORMSelect; }else if(tp=='checkbox') { getfn=this._getFORMCheckBox; setfn=this._setFORMCheckBox; }else if(tp=='radio') { getfn=this._getFORMRadio; setfn=this._setFORMRadio; }else if (tp=='text'||tp=='textarea'||tp=='hidden'||tp=='button'||tp=='submit'){ getfn=this._getFORMInput; setfn=this._setFORMInput; } }else if(o.src && !getfn && !setfn) { // check if image object getfn=this._getFORMImage; setfn=this._setFORMImage; } if(getfn && setfn){ o._getDSValue = getfn; o._setDSValue = setfn; o.getDataSource = DataSource._GetDataSource; o.setDataSource = DataSource._SetDataSource; } } return o; }; DataSource.boundFormElements = function(frm,ds){ var i,elm,elmName,elmType,il={}; for (i=0;i<frm.elements.length;i++){ elm=frm.elements[i]; elmName=elm.name; elmType=elm.type; if(!il[elmName]){ fld=(elm.fieldname)? elm.fieldname:elmName; if(frm[elmName].length && (elmType=='radio'||elmType=='checkbox')) { il[elmName]=true; elm=frm[elmName]; if(!elm.type) elm.type=elmType; } elm=DataSource.createBoundObject(elm); elm.setDataSource(ds,fld); } } }; // CallBack Functions DataSource.fnProcessResponse = function(cargo,data){ var ds=DataSource.all[cargo.id]; if(!ds) return; ds._ticket=null; if(cargo.action=='submitrow'){ // data should be set to true if all went well if(data) ds.recordSet[ds.rowIndex]=cargo.data; ds.invokeEvent('submit',null,data); ds.invokeEvent('response'); }else if(cargo.action=='fetchpage'){ var rowStart=data.dataRowIndex; var fieldnames=data.fieldnames; var fieldvalues=data.fieldvalues; if(!fieldnames||!fieldvalues) return; ds.pageCount=0; ds.pageRIS=rowStart; ds.pageRIE=rowStart+(ds.pageSize-1); ds.pageNumber=parseInt(ds.pageRIS/ds.pageSize)+1; ds.rowCount=data.dataRowCount; if(ds.pageRIE>=ds.rowCount) ds.pageRIE=ds.rowCount-1; if(ds.rowCount==null) ds.rowCount=0; if(ds.rowCount>0) ds.pageCount=parseInt((ds.rowCount-1)/ds.pageSize)+1; if(ds.rowIndex==-2) ds.rowIndex=ds.pageRIE; // set rowIndex to RIS if -2 or to RIE if <0 or >=rowCount else if(ds.rowIndex<0||ds.rowIndex>=data.dataRowCount) ds.rowIndex=ds.pageRIS; var r,c,record; for(r=0;r<fieldvalues.length;r++){ if(fieldvalues[r]){ record={} for(c=0;c<fieldnames.length;c++){ record[fieldnames[c]]=fieldvalues[r][c]; } ds.recordSet[r+rowStart]=record; } } ds.setRecord(ds.recordSet[ds.rowIndex]); ds.invokeEvent('response'); }else { // after a deleterow reload the current page if(cargo.action=='deleterow' && ds.pageSize>1) ds._send('fetchpage'); else{ ds.rowCount = ds.pageCount = data.dataRowCount; ds.rowIndex = ds.pageRIS = ds.pageRIE = data.dataRowIndex; if(ds.rowCount==null) ds.rowCount=-1; ds.setRecord(data); ds.invokeEvent('response'); } } }; DataSource.fnGETPOSTResponse = function(e,s){ var ds,data,cargo; var o=e.getSource(); if(!s){ cargo=o.getCargo(true); ds=DataSource.all[cargo.id]; ds.invokeEvent('alert',null,'DataSource: Server Timeout'); return; } cargo=o.getCargo(); data = o.getVariable('record'); if(!data) return; DataSource.fnProcessResponse(cargo,data); }; DataSource.fnSODAResponse = function(e){ var ds,data,cargo; var o=e.getSource(); var r=o.getResponse(); if (r.error) { cargo=o.getCargo(true); ds=DataSource.all[cargo.id]; ds.invokeEvent('alert',null,'DataSource: Server Timeout - '+r.error.text); return; } cargo=o.getCargo(); data=r.value; if(!data) return; DataSource.fnProcessResponse(cargo,data); }; // Data source functions for DynElement DynElement.prototype._getDSValue = function(){ return (this.getHTML)? this.getHTML():null; }; DynElement.prototype._setDSValue = function(d){ if(this.setHTML) this.setHTML(d); }; DynElement.prototype.getDataSource = DataSource._GetDataSource; DynElement.prototype.setDataSource = function(ds,field){ if(ds && ds._boundObject) { this._clsid=this.id; ds._boundObject(this,field); } };