PHP Code:
Ext.ns('Ext', 'Ext.ux', 'Ext.ux.tree');
/**
* @class Ext.ux.tree.SyncableTreeLoader
* @extends Ext.tree.TreeLoader
*
*
* A SyncableTreeLoader provides the same functionality as its Baseclass (Ext.tree.Treeloader) plus the
* possibility of lazy updating an existing Structure of TreeNodes from a specified Url.
*
* The response must be a JavaScript Object definition whose Members are (by default) "deleted", "updated", "added"
*
* "deleted" contains a simple Javascript Array definition of the TreeNode-Id that should be deleted
*
* "updated" contains a JavasScript Array defintion contaioning the Object definition of the updated
* TreeNodes with its new attribute properties
*
* "added" contains a JavaScript Array of definition containing the Object definition of the treeNodes
* that should get Added to the Tree. Cause the Tree needs to know where to insert/append the TreeNode,
* the definition of the Node needs to contain an Attribute with the Id of its Parentnode "Parentnode"
* and Optional its Presilbing.
*
* A possible Response looks like this:
* <pre><code>
{
"deleted" : ['nodeId123'],
"updated" : [{
"leaf" : false,
"id" : "nodeId342",
"children" : [{
"leaf" : false,
"id" : "node12314",
"children" : [],
"attr" : {
"preSilbing_id" : null,
"parent_id" : "nodeId342",
"Dokumente" : "0",
"leaf" : false,
"text" : "childs text"
}
}
],
"attr" : {
"parent_id" : "parentNodeId",
"preSilbing_id" : null,
"text" : "Node Text",
"leaf" : false
}
}],
"added" : [{
"leaf" : false,
"id" : "nodeId555",
"children" : [{
"leaf" : false,
"id" : "node12314",
"children" : [],
"attr" : {
"preSilbing_id" : null,
"parent_id" : "nodeId342",
"Dokumente" : "0",
"leaf" : false,
"text" : "childs text"
}
}
],
"attr" : {
"parent_id" : "RootNodeID",
"preSilbing_id" : "FirstChildsId",
"text" : "Node Text",
"leaf" : false
}]
}
</code></pre>
* @author Martin Spaeth
* @copyright (c) 2008, by Martin Spaeth
*/
Ext.ux.tree.SyncableTreeLoader = Ext.extend( Ext.tree.TreeLoader, {
/**
* @cfg {string} updateParamName
* Parametername for the requesttype
*/
updateParamName: 'request',
/**
* @cfg {string} updateParamValue
* value of the Parameter to show the server that this is an updaterequest
*/
updateParamValue: 'update',
/**
* @cfg {String} updatedName
* Name of the array containing the nodes that should get updateted
*/
updatedName: 'updated',
/**
* @cfg {String} deletedName
* Name of the array containing the Id's of the nodes that should get deleted
*/
deletedName: 'deleted',
/**
* @cfg {String} addedName
* Name of the array containing the nodes that should get added
*/
addedName: 'added',
/**
* @cfg {String} parentIDAttr
* name of the attribute containing the parentId of a node
*/
parentIDAttr: 'parentIdAttr',
/**
* @cfg {String} preSilbAttr
* name of the attribute containing the preSilbingId of a node
*/
preSilbAttr: 'preSilbingIdAttr',
clearOnLoad : true,
/**
* @cfg tree {Ext.tree.Tree} the Tree this Treeloader is instantiated for
*/
tree: undefined,
/**
* Create a String containing all needed Request Parameters
* @param {Ext.tree.TreeNode} node
* @param {boolean} update
* @return {String} Parameterstring for a Request z.b. node=432&updete=true
*/
getParams: function(node, update){
var buf = [], bp = this.baseParams;
for(var key in bp){
if(typeof bp[key] != "function"){
buf.push(encodeURIComponent(key), "=", encodeURIComponent(bp[key]), "&");
}
}
buf.push("node=", encodeURIComponent(node.id));
if(update){
// adding the updateparameter
buf.push("&"+this.updateParamName+"=", encodeURIComponent(this.updateParamValue));
}
return buf.join("");
},
/**
* RequestData Function with the possibility to fire an updaterequest
* @param {Ext.tree.TreeNode} node the Node for wicht the data should be requested
* @param {function} callback a callbackfunction
* @param {boolean} update is it an updaterequest
*/
requestData : function(node, callback, update){
if(this.fireEvent("beforeload", this, node, callback) !== false){
this.transId = Ext.Ajax.request({
update: update,
method:this.requestMethod,
url: this.dataUrl || this.url,
success: this.handleResponse,
failure: this.handleFailure,
scope: this,
argument: {callback: callback, node: node},
params: this.getParams(node, update)
});
}else{
// if the load is cancelled, make sure we notify
// the node that we are done
if(typeof callback == "function"){
callback();
}
}
},
/**
* the function that processes the Response an handles all the Update logic
* @param {Object} response from the Server
* @param {Ext.tree.TreeNode} node The Node the Response is for
* @param {function} callback
*/
processResponse : function(response, node, callback){
var json = response.responseText;
var update = response.options.update;
var tree = node.getOwnerTree();
try {
var o = eval("("+json+")");
// is the response part of an update request?
if(update){
// delete Nodes
var del = o[this.deletedName];
if(del && del.length){
for(var i = 0; del.length > i; i++){
var delNodeId = del[i];
tree.getNodeById(delNodeId).remove();
}
}
// Add all Nodes from the added Array Responsed by the server
var added = o[this.addedName];
if(added && added.length){
for(var i1 = 0; added.length > i1; i1++){
var addedNode = added[i1];
/**
* @type Ext.tree.TreeNode
*/
var parent = tree.getNodeById(addedNode.attr[this.parentIDAttr]);
var preSilbing = tree.getNodeById(addedNode.attr[this.preSilbAttr]);
parent.beginUpdate();
// Append the Node to the Parent or Insert it after the presilbing.
if(!preSilbing){
parent.appendChild(this.createNode(addedNode));
} else {
parent.insertBefore(this.createNode(addedNode), preSilbing.nextSibling);
}
parent.endUpdate();
}
}
// Update all the nodes the Update array contains
var updated = o[this.updatedName];
if(updated && updated.length){
for(var i2 = 0; updated.length > i2; i2++){
var updatedNode = updated[i2];
/**
* @type Ext.tree.TreeNode
*/
var toUpdate = tree.getNodeById(updatedNode.id);
toUpdate.beginUpdate();
// toUpdate.updateNode(updatedNode);
// update should only handle the attributes of a node nor the children
if(updateNode.children) {
delete updateNode.children;
}
Ext.apply(toUpdate, updateNode);
// update the text of the node
if(updateNode.text){
toUpdate.setText(updateNode.text);
}
// replace the Icon
if(updateNode.iconCls){
Ext.fly(toUpdate.getUI().getIconEl()).replaceClass(oldIconCls, updateNode.iconCls);
toUpdate.iconCls = updateNode.iconCls;
}
// replace the quicktip
if(updateNode.qtip) {
var ui = toUpdate.getUI();
if(ui.textNode.setAttributeNS){
ui.textNode.setAttributeNS("ext", "qtip", updateNode.qtip);
if(updateNode.qtipTitle){
ui.textNode.setAttributeNS("ext", "qtitle", updateNode.qtipTitle);
}
}else{
ui.textNode.setAttribute("ext:qtip", updateNode.qtip);
if(updateNode.qtipTitle){
ui.textNode.setAttribute("ext:qtitle", updateNode.qtipTitle);
}
}
}
toUpdate.endUpdate();
}
}
if(typeof callback == "function"){
callback(this, node);
}
}
else {
node.beginUpdate();
for(var i = 0, len = o.length; i < len; i++){
var n = this.createNode(o[i]);
if(n){
node.appendChild(n);
}
}
node.endUpdate();
if(typeof callback == "function"){
callback(this, node);
}
}
}catch(e){
this.handleFailure(response);
}
}
});