/** * @desc: constructor, data processor object * @param: serverProcessorURL - url used for update * @type: public */ function dataProcessor(serverProcessorURL){ this.serverProcessor = serverProcessorURL; this.action_param="!nativeeditor_status"; this.object = null; this.updatedRows = []; //ids of updated rows this.autoUpdate = true; this.updateMode = "cell"; this._tMode="GET"; this.post_delim = "_"; this._waitMode=0; this._in_progress={};//? this._invalid={}; this.mandatoryFields=[]; this.messages=[]; this.styles={ updated:"font-weight:bold;", inserted:"font-weight:bold;", deleted:"text-decoration : line-through;", invalid:"background-color:FFE0E0;", invalid_cell:"border-bottom:2px solid red;", error:"color:red;", clear:"font-weight:normal;text-decoration:none;" }; this.enableUTFencoding(true); dhtmlxEventable(this); return this; } dataProcessor.prototype={ /** * @desc: select GET or POST transaction model * @param: mode - GET/POST * @param: total - true/false - send records row by row or all at once (for grid only) * @type: public */ setTransactionMode:function(mode,total){ this._tMode=mode; this._tSend=total; }, escape:function(data){ if (this._utf) return encodeURIComponent(data); else return escape(data); }, /** * @desc: allows to set escaping mode * @param: true - utf based escaping, simple - use current page encoding * @type: public */ enableUTFencoding:function(mode){ this._utf=convertStringToBoolean(mode); }, /** * @desc: allows to define, which column may trigger update * @param: val - array or list of true/false values * @type: public */ setDataColumns:function(val){ this._columns=(typeof val == "string")?val.split(","):val; }, /** * @desc: get state of updating * @returns: true - all in sync with server, false - some items not updated yet. * @type: public */ getSyncState:function(){ return !this.updatedRows.length; }, /** * @desc: enable/disable named field for data syncing, will use column ids for grid * @param: mode - true/false * @type: public */ enableDataNames:function(mode){ this._endnm=convertStringToBoolean(mode); }, /** * @desc: enable/disable mode , when only changed fields and row id send to the server side, instead of all fields in default mode * @param: mode - true/false * @type: public */ enablePartialDataSend:function(mode){ this._changed=convertStringToBoolean(mode); }, /** * @desc: set if rows should be send to server automaticaly * @param: mode - "row" - based on row selection changed, "cell" - based on cell editing finished, "off" - manual data sending * @type: public */ setUpdateMode:function(mode,dnd){ this.autoUpdate = (mode=="cell"); this.updateMode = mode; this.dnd=dnd; }, ignore:function(code,master){ this._silent_mode=true; code.call(master||window); this._silent_mode=false; }, /** * @desc: mark row as updated/normal. check mandatory fields,initiate autoupdate (if turned on) * @param: rowId - id of row to set update-status for * @param: state - true for "updated", false for "not updated" * @param: mode - update mode name * @type: public */ setUpdated:function(rowId,state,mode){ if (this._silent_mode) return; var ind=this.findRow(rowId); mode=mode||"updated"; var existing = this.obj.getUserData(rowId,this.action_param); if (existing && mode == "updated") mode=existing; if (state){ this.set_invalid(rowId,false); //clear previous error flag this.updatedRows[ind]=rowId; this.obj.setUserData(rowId,this.action_param,mode); if (this._in_progress[rowId]) this._in_progress[rowId]="wait"; } else{ if (!this.is_invalid(rowId)){ this.updatedRows.splice(ind,1); this.obj.setUserData(rowId,this.action_param,""); } } //clear changed flag if (!state) this._clearUpdateFlag(rowId); this.markRow(rowId,state,mode); if (state && this.autoUpdate) this.sendData(rowId); }, _clearUpdateFlag:function(id){}, markRow:function(id,state,mode){ var str=""; var invalid=this.is_invalid(id); if (invalid){ str=this.styles[invalid]; state=true; } if (this.callEvent("onRowMark",[id,state,mode,invalid])){ //default logic str=this.styles[state?mode:"clear"]+str; this.obj[this._methods[0]](id,str); if (invalid && invalid.details){ str+=this.styles[invalid+"_cell"]; for (var i=0; i < invalid.details.length; i++) if (invalid.details[i]) this.obj[this._methods[1]](id,i,str); } } }, getState:function(id){ return this.obj.getUserData(id,this.action_param); }, is_invalid:function(id){ return this._invalid[id]; }, set_invalid:function(id,mode,details){ if (details) mode={value:mode, details:details, toString:function(){ return this.value.toString(); }}; this._invalid[id]=mode; }, /** * @desc: check mandatory fields and varify values of cells, initiate update (if specified) * @param: rowId - id of row to set update-status for * @type: public */ checkBeforeUpdate:function(rowId){ return true; }, /** * @desc: send row(s) values to server * @param: rowId - id of row which data to send. If not specified, then all "updated" rows will be send * @type: public */ sendData:function(rowId){ if (this._waitMode && (this.obj.mytype=="tree" || this.obj._h2)) return; if (this.obj.editStop) this.obj.editStop(); if(typeof rowId == "undefined" || this._tSend) return this.sendAllData(); if (this._in_progress[rowId]) return false; this.messages=[]; if (!this.checkBeforeUpdate(rowId) && this.callEvent("onValidatationError",[rowId,this.messages])) return false; this._beforeSendData(this._getRowData(rowId),rowId); }, _beforeSendData:function(data,rowId){ if (!this.callEvent("onBeforeUpdate",[rowId,this.getState(rowId),data])) return false; this._sendData(data,rowId); }, serialize:function(data, id){ if (typeof data == "string") return data; if (typeof id != "undefined") return this.serialize_one(data,""); else{ var stack = []; var keys = []; for (var key in data) if (data.hasOwnProperty(key)){ stack.push(this.serialize_one(data[key],key+this.post_delim)); keys.push(key); } stack.push("ids="+this.escape(keys.join(","))); return stack.join("&"); } }, serialize_one:function(data, pref){ if (typeof data == "string") return data; var stack = []; for (var key in data) if (data.hasOwnProperty(key)) stack.push(this.escape((pref||"")+key)+"="+this.escape(data[key])); return stack.join("&"); }, _sendData:function(a1,rowId){ if (!a1) return; //nothing to send if (!this.callEvent("onBeforeDataSending",rowId?[rowId,this.getState(rowId),a1]:[null, null, a1])) return false; if (rowId) this._in_progress[rowId]=(new Date()).valueOf(); var a2=new dtmlXMLLoaderObject(this.afterUpdate,this,true); var a3 = this.serverProcessor+(this._user?(getUrlSymbol(this.serverProcessor)+["dhx_user="+this._user,"dhx_version="+this.obj.getUserData(0,"version")].join("&")):""); if (this._tMode!="POST") a2.loadXML(a3+((a3.indexOf("?")!=-1)?"&":"?")+this.serialize(a1,rowId)); else a2.loadXML(a3,true,this.serialize(a1,rowId)); this._waitMode++; }, sendAllData:function(){ if (!this.updatedRows.length) return; this.messages=[]; var valid=true; for (var i=0; i