updated dhtmlxtree to version 2.6

This commit is contained in:
Ralf Becker
2010-10-15 10:04:07 +00:00
parent 77bede9db4
commit 197fdee2a4
1114 changed files with 79484 additions and 0 deletions

View File

@ -0,0 +1,152 @@
//v.2.6 build 100722
/*
Copyright DHTMLX LTD. http://www.dhtmlx.com
You allowed to use this component or parts of it under GPL terms
To use it on other terms or get Professional edition of the component please contact us at sales@dhtmlx.com
*/
function dataProcessor(serverProcessorURL){this.serverProcessor = serverProcessorURL;this.action_param="!nativeeditor_status";this.object = null;this.updatedRows = [];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={setTransactionMode:function(mode,total){this._tMode=mode;this._tSend=total;},
escape:function(data){if (this._utf)return encodeURIComponent(data);else
return escape(data);},
enableUTFencoding:function(mode){this._utf=convertStringToBoolean(mode);},
setDataColumns:function(val){this._columns=(typeof val == "string")?val.split(","):val;},
getSyncState:function(){return !this.updatedRows.length;},
enableDataNames:function(mode){this._endnm=convertStringToBoolean(mode);},
enablePartialDataSend:function(mode){this._changed=convertStringToBoolean(mode);},
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;},
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);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,"");}};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])){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;},
checkBeforeUpdate:function(rowId){return true;},
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 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;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));this._waitMode++;},
sendAllData:function(){if (!this.updatedRows.length)return;this.messages=[];var valid=true;for (var i=0;i<this.updatedRows.length;i++)valid&=this.checkBeforeUpdate(this.updatedRows[i]);if (!valid && !this.callEvent("onValidatationError",["",this.messages])) return false;if (this._tSend)this._sendData(this._getAllData());else
for (var i=0;i<this.updatedRows.length;i++)if (!this._in_progress[this.updatedRows[i]]){if (this.is_invalid(this.updatedRows[i])) continue;this._beforeSendData(this._getRowData(this.updatedRows[i]),this.updatedRows[i]);if (this._waitMode && (this.obj.mytype=="tree" || this.obj._h2)) return;}},
_getAllData:function(rowId){var out={};var has_one = false;for(var i=0;i<this.updatedRows.length;i++){var id=this.updatedRows[i];if (this._in_progress[id] || this.is_invalid(id)) continue;if (!this.callEvent("onBeforeUpdate",[id,this.getState(id)])) continue;out[id]=this._getRowData(id,id+this.post_delim);has_one = true;this._in_progress[id]=(new Date()).valueOf();};return has_one?out:null;},
setVerificator:function(ind,verifFunction){this.mandatoryFields[ind] = verifFunction||(function(value){return (value!="");});},
clearVerificator:function(ind){this.mandatoryFields[ind] = false;},
findRow:function(pattern){var i=0;for(i=0;i<this.updatedRows.length;i++)if(pattern==this.updatedRows[i])break;return i;},
defineAction:function(name,handler){if (!this._uActions)this._uActions=[];this._uActions[name]=handler;},
afterUpdateCallback:function(sid, tid, action, btag) {var correct=(action!="error" && action!="invalid");if (!correct)this.set_invalid(sid,action);if ((this._uActions)&&(this._uActions[action])&&(!this._uActions[action](btag)))
return (delete this._in_progress[sid]);if (this._in_progress[sid]!="wait")this.setUpdated(sid, false);var soid = sid;switch (action) {case "inserted":
case "insert":
if (tid != sid){this.obj[this._methods[2]](sid, tid);sid = tid;};break;case "delete":
case "deleted":
this.obj.setUserData(sid, this.action_param, "true_deleted");this.obj[this._methods[3]](sid);return this.callEvent("onAfterUpdate", [sid, action, tid, btag]);break;};if (this._in_progress[sid]!="wait"){if (correct)this.obj.setUserData(sid, this.action_param,'');delete this._in_progress[sid];}else {delete this._in_progress[sid];this.setUpdated(tid,true,this.obj.getUserData(sid,this.action_param));};this.callEvent("onAfterUpdate", [sid, action, tid, btag]);},
afterUpdate:function(that,b,c,d,xml){xml.getXMLTopNode("data");if (!xml.xmlDoc.responseXML)return;var atag=xml.doXPath("//data/action");for (var i=0;i<atag.length;i++){var btag=atag[i];var action = btag.getAttribute("type");var sid = btag.getAttribute("sid");var tid = btag.getAttribute("tid");that.afterUpdateCallback(sid,tid,action,btag);};that.finalizeUpdate();},
finalizeUpdate:function(){if (this._waitMode)this._waitMode--;if ((this.obj.mytype=="tree" || this.obj._h2)&& this.updatedRows.length)
this.sendData();this.callEvent("onAfterUpdateFinish",[]);if (!this.updatedRows.length)this.callEvent("onFullSync",[]);},
init:function(anObj){this.obj = anObj;if (this.obj._dp_init)this.obj._dp_init(this);},
setOnAfterUpdate:function(ev){this.attachEvent("onAfterUpdate",ev);},
enableDebug:function(mode){},
setOnBeforeUpdateHandler:function(func){this.attachEvent("onBeforeDataSending",func);},
setAutoUpdate: function(interval, user) {interval = interval || 2000;this._user = user || (new Date()).valueOf();this._need_update = false;this._loader = null;this._update_busy = false;this.attachEvent("onAfterUpdate",function(sid,action,tid,xml_node){this.afterAutoUpdate(sid, action, tid, xml_node);});this.attachEvent("onFullSync",function(){this.fullSync();});var self = this;window.setInterval(function(){self.loadUpdate();}, interval);},
afterAutoUpdate: function(sid, action, tid, xml_node) {if (action == 'collision'){this._need_update = true;return false;}else {return true;}},
fullSync: function() {if (this._need_update == true){this._need_update = false;this.loadUpdate();};return true;},
getUpdates: function(url,callback){if (this._update_busy)return false;else
this._update_busy = true;this._loader = this._loader || new dtmlXMLLoaderObject(true);this._loader.async=true;this._loader.waitCall=callback;this._loader.loadXML(url);},
_v: function(node) {if (node.firstChild)return node.firstChild.nodeValue;return "";},
_a: function(arr) {var res = [];for (var i=0;i < arr.length;i++){res[i]=this._v(arr[i]);};return res;},
loadUpdate: function(){var self = this;var version = this.obj.getUserData(0,"version");var url = this.serverProcessor+getUrlSymbol(this.serverProcessor)+["dhx_user="+this._user,"dhx_version="+version].join("&");url = url.replace("editing=true&","");this.getUpdates(url, function(){var vers = self._loader.doXPath("//userdata");self.obj.setUserData(0,"version",self._v(vers[0]));var upds = self._loader.doXPath("//update");if (upds.length){self._silent_mode = true;for (var i=0;i<upds.length;i++){var status = upds[i].getAttribute('status');var id = upds[i].getAttribute('id');var parent = upds[i].getAttribute('parent');switch (status) {case 'inserted':
self.callEvent("insertCallback",[upds[i], id, parent]);break;case 'updated':
self.callEvent("updateCallback",[upds[i], id, parent]);break;case 'deleted':
self.callEvent("deleteCallback",[upds[i], id, parent]);break;}};self._silent_mode = false;};self._update_busy = false;self = null;});}};//(c)dhtmlx ltd. www.dhtmlx.com
//v.2.6 build 100722
/*
Copyright DHTMLX LTD. http://www.dhtmlx.com
You allowed to use this component or parts of it under GPL terms
To use it on other terms or get Professional edition of the component please contact us at sales@dhtmlx.com
*/

View File

@ -0,0 +1,27 @@
//v.2.6 build 100722
/*
Copyright DHTMLX LTD. http://www.dhtmlx.com
You allowed to use this component or parts of it under GPL terms
To use it on other terms or get Professional edition of the component please contact us at sales@dhtmlx.com
*/
dataProcessor.prototype._o_init = dataProcessor.prototype.init;dataProcessor.prototype.init=function(obj){this._console=this._console||this._createConsole();this.attachEvent("onValidatationError",function(rowId){this._log("Validation error for ID="+(rowId||"[multiple]"));return true;});return this._o_init(obj);};dataProcessor.prototype._createConsole=function(){var c=document.createElement("DIV");c.style.cssText='width:450px;height:420px;overflow:auto;position:absolute;z-index:99999;background-color:white;top:0px;right:0px;border:1px dashed black;font-family:Tahoma;Font-size:10pt;';c.innerHTML="<div style='width:100%;background-color:gray;font-weight:bold;color:white;'><span style='cursor:pointer;float:right;' onclick='this.parentNode.parentNode.style.display=\"none\"'><sup>[close]&nbsp;</sup></span><span style='cursor:pointer;float:right;' onclick='this.parentNode.parentNode.childNodes[2].innerHTML=\"\"'><sup>[clear]&nbsp;</sup></span>&nbsp;DataProcessor</div><div style='width:100%;height:200px;overflow-Y:scroll;'>&nbsp;Current state</div><div style='width:100%;height:200px;overflow-Y:scroll;'>&nbsp;Log:</div>";if (document.body)document.body.insertBefore(c,document.body.firstChild);else dhtmlxEvent(window,"load",function(){document.body.insertBefore(c,document.body.firstChild);})
dhtmlxEvent(window,"dblclick",function(){c.style.display='';})
return c;};dataProcessor.prototype._error=function(data){this._log("<span style='color:red'>"+data+"</span>");};dataProcessor.prototype._log=function(data){var div=document.createElement("DIV");div.innerHTML = data;var parent=this._console.childNodes[2];parent.appendChild(div);parent.scrollTop=parent.scrollHeight;if (window.console && window.console.log)window.console.log("DataProcessor :: "+data.replace("&nbsp;"," ").replace("<b>","").replace("</b>",""));};dataProcessor.prototype._updateStat=function(data){var data=["&nbsp;Current state"];for(var i=0;i<this.updatedRows.length;i++)data.push("&nbsp;ID:"+this.updatedRows[i]+" Status: "+(this.obj.getUserData(this.updatedRows[i],"!nativeeditor_status")||"updated")+", "+(this.is_invalid(this.updatedRows[i])||"valid"))
this._console.childNodes[1].innerHTML=data.join("<br/>")+"<hr/>Current mode: "+this.updateMode;};dataProcessor.prototype.xml_analize=function(xml){if (_isFF){if (!xml.xmlDoc.responseXML)this._error("Not an XML, probably incorrect content type specified ( must be text/xml ), or some text output was started before XML data");else if (xml.xmlDoc.responseXML.firstChild.tagName=="parsererror")this._error(xml.xmlDoc.responseXML.firstChild.textContent);else return true;}else if (_isIE){if (xml.xmlDoc.responseXML.parseError.errorCode)this._error("XML error : "+xml.xmlDoc.responseXML.parseError.reason);else if (!xml.xmlDoc.responseXML.documentElement)this._error("Not an XML, probably incorrect content type specified ( must be text/xml ), or some text output was started before XML data");else return true;};return false;};dataProcessor.wrap=function(name,before,after){var d=dataProcessor.prototype;if (!d._wrap)d._wrap={};d._wrap[name]=d[name];d[name]=function(){if (before)before.apply(this,arguments);var res=d._wrap[name].apply(this,arguments);if (after)after.apply(this,[arguments,res]);return res;}};dataProcessor.wrap("setUpdated",function(rowId,state,mode){this._log("&nbsp;row <b>"+rowId+"</b> "+(state?"marked":"unmarked")+" ["+(mode||"updated")+","+(this.is_invalid(rowId)||"valid")+"]");},function(){this._updateStat();});dataProcessor.wrap("sendData",function(rowId){if (rowId){this._log("&nbsp;Initiating data sending for <b>"+rowId+"</b>");if (this.obj.mytype=="tree"){if (!this.obj._idpull[rowId])this._log("&nbsp;Error! item with such ID not exists <b>"+rowId+"</b>");}else {if (!this.obj.rowsAr[rowId])this._log("&nbsp;Error! row with such ID not exists <b>"+rowId+"</b>");}}},function(){});dataProcessor.wrap("sendAllData",function(){this._log("&nbsp;Initiating data sending for <b>all</b> rows ");},function(){});dataProcessor.logSingle=function(data,id){var tdata = {};if (id)tdata[id] = data;else
tdata = data;var url = [];for (var key in tdata){url.push("<fieldset><legend>"+key+"</legend>");var suburl = [];for (var ikey in tdata[key])suburl.push(ikey+" = "+tdata[key][ikey]);url.push(suburl.join("<br>"));url.push("</fieldset>");};return url.join("");};dataProcessor.wrap("_sendData",function(data,rowId){if (rowId)this._log("&nbsp;Sending in one-by-one mode, current ID = "+rowId);else
this._log("&nbsp;Sending all data at once");this._log("&nbsp;Server url: "+this.serverProcessor+" <a onclick='this.parentNode.nextSibling.firstChild.style.display=\"block\"' href='#'>parameters</a>");var url = [];this._log("<blockquote style='display:none;'>"+dataProcessor.logSingle(data,rowId)+"<blockquote>");},function(){});dataProcessor.wrap("afterUpdate",function(that,b,c,d,xml){that._log("&nbsp;Server response received <a onclick='this.nextSibling.style.display=\"block\"' href='#'>details</a><blockquote style='display:none'><code>"+(xml.xmlDoc.responseText||"").replace(/\&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")+"</code></blockquote>");if (!that.xml_analize(xml)) return;var atag=xml.doXPath("//data/action");if (!atag){that._log("&nbsp;No actions found");var atag=xml.getXMLTopNode("data");if (!atag)that._log("&nbsp;XML not valid");else that._log("&nbsp;Incorrect content type - need to be text/xml");}},function(){});dataProcessor.wrap("afterUpdateCallback",function(sid,tid,action){if (this.obj.mytype=="tree"){if (!this.obj._idpull[sid])this._log("Incorrect SID, item with such ID not exists in grid");}else {if (!this.obj.rowsAr[sid])this._log("Incorrect SID, row with such ID not exists in grid");};this._log("&nbsp;Action: "+action+" SID:"+sid+" TID:"+tid);},function(){});
//v.2.6 build 100722
/*
Copyright DHTMLX LTD. http://www.dhtmlx.com
You allowed to use this component or parts of it under GPL terms
To use it on other terms or get Professional edition of the component please contact us at sales@dhtmlx.com
*/

View File

@ -0,0 +1,17 @@
//v.2.6 build 100722
/*
Copyright DHTMLX LTD. http://www.dhtmlx.com
You allowed to use this component or parts of it under GPL terms
To use it on other terms or get Professional edition of the component please contact us at sales@dhtmlx.com
*/
dataProcessor.prototype.setOnAfterUpdate = function(ev){this.attachEvent("onAfterUpdate",ev);};dataProcessor.prototype.enableDebug = function(mode){};dataProcessor.prototype.setOnBeforeUpdateHandler=function(func){this.attachEvent("onBeforeDataSending",func);};
//v.2.6 build 100722
/*
Copyright DHTMLX LTD. http://www.dhtmlx.com
You allowed to use this component or parts of it under GPL terms
To use it on other terms or get Professional edition of the component please contact us at sales@dhtmlx.com
*/

View File

@ -0,0 +1,3 @@
dhtmlxDataProcessor v.2.6 Standard edition build 100722
(c) DHTMLX Ltd.

View File

@ -0,0 +1,584 @@
//v.2.6 build 100722
/*
Copyright DHTMLX LTD. http://www.dhtmlx.com
You allowed to use this component or parts of it under GPL terms
To use it on other terms or get Professional edition of the component please contact us at sales@dhtmlx.com
*/
/**
* @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 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));
this._waitMode++;
},
sendAllData:function(){
if (!this.updatedRows.length) return;
this.messages=[]; var valid=true;
for (var i=0; i<this.updatedRows.length; i++)
valid&=this.checkBeforeUpdate(this.updatedRows[i]);
if (!valid && !this.callEvent("onValidatationError",["",this.messages])) return false;
if (this._tSend)
this._sendData(this._getAllData());
else
for (var i=0; i<this.updatedRows.length; i++)
if (!this._in_progress[this.updatedRows[i]]){
if (this.is_invalid(this.updatedRows[i])) continue;
this._beforeSendData(this._getRowData(this.updatedRows[i]),this.updatedRows[i]);
if (this._waitMode && (this.obj.mytype=="tree" || this.obj._h2)) return; //block send all for tree
}
},
_getAllData:function(rowId){
var out={};
var has_one = false;
for(var i=0;i<this.updatedRows.length;i++){
var id=this.updatedRows[i];
if (this._in_progress[id] || this.is_invalid(id)) continue;
if (!this.callEvent("onBeforeUpdate",[id,this.getState(id)])) continue;
out[id]=this._getRowData(id,id+this.post_delim);
has_one = true;
this._in_progress[id]=(new Date()).valueOf();
}
return has_one?out:null;
},
/**
* @desc: specify column which value should be varified before sending to server
* @param: ind - column index (0 based)
* @param: verifFunction - function (object) which should verify cell value (if not specified, then value will be compared to empty string). Two arguments will be passed into it: value and column name
* @type: public
*/
setVerificator:function(ind,verifFunction){
this.mandatoryFields[ind] = verifFunction||(function(value){return (value!="");});
},
/**
* @desc: remove column from list of those which should be verified
* @param: ind - column Index (0 based)
* @type: public
*/
clearVerificator:function(ind){
this.mandatoryFields[ind] = false;
},
findRow:function(pattern){
var i=0;
for(i=0;i<this.updatedRows.length;i++)
if(pattern==this.updatedRows[i]) break;
return i;
},
/**
* @desc: define custom actions
* @param: name - name of action, same as value of action attribute
* @param: handler - custom function, which receives a XMl response content for action
* @type: private
*/
defineAction:function(name,handler){
if (!this._uActions) this._uActions=[];
this._uActions[name]=handler;
},
/**
* @desc: used in combination with setOnBeforeUpdateHandler to create custom client-server transport system
* @param: sid - id of item before update
* @param: tid - id of item after up0ate
* @param: action - action name
* @type: public
* @topic: 0
*/
afterUpdateCallback:function(sid, tid, action, btag) {
var correct=(action!="error" && action!="invalid");
if (!correct) this.set_invalid(sid,action);
if ((this._uActions)&&(this._uActions[action])&&(!this._uActions[action](btag)))
return (delete this._in_progress[sid]);
if (this._in_progress[sid]!="wait")
this.setUpdated(sid, false);
var soid = sid;
switch (action) {
case "inserted":
case "insert":
if (tid != sid) {
this.obj[this._methods[2]](sid, tid);
sid = tid;
}
break;
case "delete":
case "deleted":
this.obj.setUserData(sid, this.action_param, "true_deleted");
this.obj[this._methods[3]](sid);
return this.callEvent("onAfterUpdate", [sid, action, tid, btag]);
break;
}
if (this._in_progress[sid]!="wait"){
if (correct) this.obj.setUserData(sid, this.action_param,'');
delete this._in_progress[sid];
} else {
delete this._in_progress[sid];
this.setUpdated(tid,true,this.obj.getUserData(sid,this.action_param));
}
this.callEvent("onAfterUpdate", [sid, action, tid, btag]);
},
/**
* @desc: response from server
* @param: xml - XMLLoader object with response XML
* @type: private
*/
afterUpdate:function(that,b,c,d,xml){
xml.getXMLTopNode("data"); //fix incorrect content type in IE
if (!xml.xmlDoc.responseXML) return;
var atag=xml.doXPath("//data/action");
for (var i=0; i<atag.length; i++){
var btag=atag[i];
var action = btag.getAttribute("type");
var sid = btag.getAttribute("sid");
var tid = btag.getAttribute("tid");
that.afterUpdateCallback(sid,tid,action,btag);
}
that.finalizeUpdate();
},
finalizeUpdate:function(){
if (this._waitMode) this._waitMode--;
if ((this.obj.mytype=="tree" || this.obj._h2) && this.updatedRows.length)
this.sendData();
this.callEvent("onAfterUpdateFinish",[]);
if (!this.updatedRows.length)
this.callEvent("onFullSync",[]);
},
/**
* @desc: initializes data-processor
* @param: anObj - dhtmlxGrid object to attach this data-processor to
* @type: public
*/
init:function(anObj){
this.obj = anObj;
if (this.obj._dp_init)
this.obj._dp_init(this);
},
setOnAfterUpdate:function(ev){
this.attachEvent("onAfterUpdate",ev);
},
enableDebug:function(mode){
},
setOnBeforeUpdateHandler:function(func){
this.attachEvent("onBeforeDataSending",func);
},
/*! starts autoupdate mode
@param interval
time interval for sending update requests
*/
setAutoUpdate: function(interval, user) {
interval = interval || 2000;
this._user = user || (new Date()).valueOf();
this._need_update = false;
this._loader = null;
this._update_busy = false;
this.attachEvent("onAfterUpdate",function(sid,action,tid,xml_node){
this.afterAutoUpdate(sid, action, tid, xml_node);
});
this.attachEvent("onFullSync",function(){
this.fullSync();
});
var self = this;
window.setInterval(function(){
self.loadUpdate();
}, interval);
},
/*! process updating request answer
if status == collision version is depricated
set flag for autoupdating immidiatly
*/
afterAutoUpdate: function(sid, action, tid, xml_node) {
if (action == 'collision') {
this._need_update = true;
return false;
} else {
return true;
}
},
/*! callback function for onFillSync event
call update function if it's need
*/
fullSync: function() {
if (this._need_update == true) {
this._need_update = false;
this.loadUpdate();
}
return true;
},
/*! sends query to the server and call callback function
*/
getUpdates: function(url,callback){
if (this._update_busy)
return false;
else
this._update_busy = true;
this._loader = this._loader || new dtmlXMLLoaderObject(true);
this._loader.async=true;
this._loader.waitCall=callback;
this._loader.loadXML(url);
},
/*! returns xml node value
@param node
xml node
*/
_v: function(node) {
if (node.firstChild) return node.firstChild.nodeValue;
return "";
},
/*! returns values array of xml nodes array
@param arr
array of xml nodes
*/
_a: function(arr) {
var res = [];
for (var i=0; i < arr.length; i++) {
res[i]=this._v(arr[i]);
};
return res;
},
/*! loads updates and processes them
*/
loadUpdate: function(){
var self = this;
var version = this.obj.getUserData(0,"version");
var url = this.serverProcessor+getUrlSymbol(this.serverProcessor)+["dhx_user="+this._user,"dhx_version="+version].join("&");
url = url.replace("editing=true&","");
this.getUpdates(url, function(){
var vers = self._loader.doXPath("//userdata");
self.obj.setUserData(0,"version",self._v(vers[0]));
var upds = self._loader.doXPath("//update");
if (upds.length){
self._silent_mode = true;
for (var i=0; i<upds.length; i++) {
var status = upds[i].getAttribute('status');
var id = upds[i].getAttribute('id');
var parent = upds[i].getAttribute('parent');
switch (status) {
case 'inserted':
self.callEvent("insertCallback",[upds[i], id, parent]);
break;
case 'updated':
self.callEvent("updateCallback",[upds[i], id, parent]);
break;
case 'deleted':
self.callEvent("deleteCallback",[upds[i], id, parent]);
break;
}
}
self._silent_mode = false;
}
self._update_busy = false;
self = null;
});
}
};
//(c)dhtmlx ltd. www.dhtmlx.com

View File

@ -0,0 +1,171 @@
//v.2.6 build 100722
/*
Copyright DHTMLX LTD. http://www.dhtmlx.com
You allowed to use this component or parts of it under GPL terms
To use it on other terms or get Professional edition of the component please contact us at sales@dhtmlx.com
*/
dataProcessor.prototype._o_init = dataProcessor.prototype.init;
dataProcessor.prototype.init=function(obj){
this._console=this._console||this._createConsole();
this.attachEvent("onValidatationError",function(rowId){
this._log("Validation error for ID="+(rowId||"[multiple]"));
return true;
});
return this._o_init(obj);
}
dataProcessor.prototype._createConsole=function(){
var c=document.createElement("DIV");
c.style.cssText='width:450px; height:420px; overflow:auto; position:absolute; z-index:99999; background-color:white; top:0px; right:0px; border:1px dashed black; font-family:Tahoma; Font-size:10pt;';
c.innerHTML="<div style='width:100%; background-color:gray; font-weight:bold; color:white;'><span style='cursor:pointer;float:right;' onclick='this.parentNode.parentNode.style.display=\"none\"'><sup>[close]&nbsp;</sup></span><span style='cursor:pointer;float:right;' onclick='this.parentNode.parentNode.childNodes[2].innerHTML=\"\"'><sup>[clear]&nbsp;</sup></span>&nbsp;DataProcessor</div><div style='width:100%; height:200px; overflow-Y:scroll;'>&nbsp;Current state</div><div style='width:100%; height:200px; overflow-Y:scroll;'>&nbsp;Log:</div>";
if (document.body) document.body.insertBefore(c,document.body.firstChild);
else dhtmlxEvent(window,"load",function(){
document.body.insertBefore(c,document.body.firstChild);
})
dhtmlxEvent(window,"dblclick",function(){
c.style.display='';
})
return c;
}
dataProcessor.prototype._error=function(data){
this._log("<span style='color:red'>"+data+"</span>");
}
dataProcessor.prototype._log=function(data){
var div=document.createElement("DIV");
div.innerHTML = data;
var parent=this._console.childNodes[2];
parent.appendChild(div);
parent.scrollTop=parent.scrollHeight;
if (window.console && window.console.log)
window.console.log("DataProcessor :: "+data.replace("&nbsp;"," ").replace("<b>","").replace("</b>",""));
}
dataProcessor.prototype._updateStat=function(data){
var data=["&nbsp;Current state"];
for(var i=0;i<this.updatedRows.length;i++)
data.push("&nbsp;ID:"+this.updatedRows[i]+" Status: "+(this.obj.getUserData(this.updatedRows[i],"!nativeeditor_status")||"updated")+", "+(this.is_invalid(this.updatedRows[i])||"valid"))
this._console.childNodes[1].innerHTML=data.join("<br/>")+"<hr/>Current mode: "+this.updateMode;
}
dataProcessor.prototype.xml_analize=function(xml){
if (_isFF){
if (!xml.xmlDoc.responseXML)
this._error("Not an XML, probably incorrect content type specified ( must be text/xml ), or some text output was started before XML data");
else if (xml.xmlDoc.responseXML.firstChild.tagName=="parsererror")
this._error(xml.xmlDoc.responseXML.firstChild.textContent);
else return true;
} else if (_isIE){
if (xml.xmlDoc.responseXML.parseError.errorCode)
this._error("XML error : "+xml.xmlDoc.responseXML.parseError.reason);
else if (!xml.xmlDoc.responseXML.documentElement)
this._error("Not an XML, probably incorrect content type specified ( must be text/xml ), or some text output was started before XML data");
else return true;
}
return false;
}
dataProcessor.wrap=function(name,before,after){
var d=dataProcessor.prototype;
if (!d._wrap) d._wrap={};
d._wrap[name]=d[name];
d[name]=function(){
if (before) before.apply(this,arguments);
var res=d._wrap[name].apply(this,arguments);
if (after) after.apply(this,[arguments,res]);
return res;
}
};
dataProcessor.wrap("setUpdated",function(rowId,state,mode){
this._log("&nbsp;row <b>"+rowId+"</b> "+(state?"marked":"unmarked")+" ["+(mode||"updated")+","+(this.is_invalid(rowId)||"valid")+"]");
},function(){
this._updateStat();
});
dataProcessor.wrap("sendData",function(rowId){
if (rowId){
this._log("&nbsp;Initiating data sending for <b>"+rowId+"</b>");
if (this.obj.mytype=="tree"){
if (!this.obj._idpull[rowId])
this._log("&nbsp;Error! item with such ID not exists <b>"+rowId+"</b>");
} else {
if (!this.obj.rowsAr[rowId])
this._log("&nbsp;Error! row with such ID not exists <b>"+rowId+"</b>");
}
}
},function(){
});
dataProcessor.wrap("sendAllData",function(){
this._log("&nbsp;Initiating data sending for <b>all</b> rows ");
},function(){
});
dataProcessor.logSingle=function(data,id){
var tdata = {};
if (id)
tdata[id] = data;
else
tdata = data;
var url = [];
for (var key in tdata) {
url.push("<fieldset><legend>"+key+"</legend>");
var suburl = [];
for (var ikey in tdata[key])
suburl.push(ikey+" = "+tdata[key][ikey]);
url.push(suburl.join("<br>"));
url.push("</fieldset>");
}
return url.join("");
}
dataProcessor.wrap("_sendData",function(data,rowId){
if (rowId)
this._log("&nbsp;Sending in one-by-one mode, current ID = "+rowId);
else
this._log("&nbsp;Sending all data at once");
this._log("&nbsp;Server url: "+this.serverProcessor+" <a onclick='this.parentNode.nextSibling.firstChild.style.display=\"block\"' href='#'>parameters</a>");
var url = [];
this._log("<blockquote style='display:none;'>"+dataProcessor.logSingle(data,rowId)+"<blockquote>");
},function(){
});
dataProcessor.wrap("afterUpdate",function(that,b,c,d,xml){
that._log("&nbsp;Server response received <a onclick='this.nextSibling.style.display=\"block\"' href='#'>details</a><blockquote style='display:none'><code>"+(xml.xmlDoc.responseText||"").replace(/\&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")+"</code></blockquote>");
if (!that.xml_analize(xml)) return;
var atag=xml.doXPath("//data/action");
if (!atag){
that._log("&nbsp;No actions found");
var atag=xml.getXMLTopNode("data");
if (!atag) that._log("&nbsp;XML not valid");
else that._log("&nbsp;Incorrect content type - need to be text/xml");
}
},function(){
});
dataProcessor.wrap("afterUpdateCallback",function(sid,tid,action){
if (this.obj.mytype=="tree"){
if (!this.obj._idpull[sid]) this._log("Incorrect SID, item with such ID not exists in grid");
} else {
if (!this.obj.rowsAr[sid]) this._log("Incorrect SID, row with such ID not exists in grid");
}
this._log("&nbsp;Action: "+action+" SID:"+sid+" TID:"+tid);
},function(){
});

View File

@ -0,0 +1,45 @@
//v.2.6 build 100722
/*
Copyright DHTMLX LTD. http://www.dhtmlx.com
You allowed to use this component or parts of it under GPL terms
To use it on other terms or get Professional edition of the component please contact us at sales@dhtmlx.com
*/
/**
* @desc: set function called after row updated
* @param: func - event handling function (or its name)
* @type: deprecated
* @topic: 10
* @event: onAfterUpdate
* @eventdesc: Event raised after row updated on server side
* @eventparam: ID of clicked row
* @eventparam: type of command
* @eventparam: new Id, for _insert_ command
*/
dataProcessor.prototype.setOnAfterUpdate = function(ev){
this.attachEvent("onAfterUpdate",ev);
}
/**
* @desc: enable/disable debuging
* @param: mode - true/false
* @type: deprecated
*/
dataProcessor.prototype.enableDebug = function(mode){
}
/**
* @desc: set function called before server request sent ( can be used for including custom client server transport system)
* @param: func - event handling function
* @type: public
* @topic: 0
* @event: onBeforeUpdate
* @eventdesc: Event occured in moment before data sent to server
* @eventparam: ID of item which need to be updated
* @eventparam: type of operation
* @eventreturns: false to block default sending routine
*/
dataProcessor.prototype.setOnBeforeUpdateHandler=function(func){
this.attachEvent("onBeforeDataSending",func);
};