4 * Copyright(c) 2006-2007, Ext JS, LLC.
6 * Originally Released Under LGPL - original licence link has changed is not relivant.
9 * <script type="text/javascript">
12 * @class Roo.tree.TreeLoader
13 * @extends Roo.util.Observable
14 * A TreeLoader provides for lazy loading of an {@link Roo.tree.TreeNode}'s child
15 * nodes from a specified URL. The response must be a javascript Array definition
16 * who's elements are node definition objects. eg:
21 { 'id': 1, 'text': 'A folder Node', 'leaf': false },
22 { 'id': 2, 'text': 'A leaf Node', 'leaf': true }
29 * The old style respose with just an array is still supported, but not recommended.
32 * A server request is sent, and child nodes are loaded only when a node is expanded.
33 * The loading node's id is passed to the server under the parameter name "node" to
34 * enable the server to produce the correct child nodes.
36 * To pass extra parameters, an event handler may be attached to the "beforeload"
37 * event, and the parameters specified in the TreeLoader's baseParams property:
39 myTreeLoader.on("beforeload", function(treeLoader, node) {
40 this.baseParams.category = node.attributes.category;
43 * This would pass an HTTP parameter called "category" to the server containing
44 * the value of the Node's "category" attribute.
46 * Creates a new Treeloader.
47 * @param {Object} config A config object containing config properties.
49 Roo.tree.TreeLoader = function(config){
51 this.requestMethod = "POST";
52 Roo.apply(this, config);
58 * Fires before a network request is made to retrieve the Json text which specifies a node's children.
59 * @param {Object} This TreeLoader object.
60 * @param {Object} node The {@link Roo.tree.TreeNode} object being loaded.
61 * @param {Object} callback The callback function specified in the {@link #load} call.
66 * Fires when the node has been successfuly loaded.
67 * @param {Object} This TreeLoader object.
68 * @param {Object} node The {@link Roo.tree.TreeNode} object being loaded.
69 * @param {Object} response The response object containing the data from the server.
73 * @event loadexception
74 * Fires if the network request failed.
75 * @param {Object} This TreeLoader object.
76 * @param {Object} node The {@link Roo.tree.TreeNode} object being loaded.
77 * @param {Object} response The response object containing the data from the server.
82 * Fires before a node is created, enabling you to return custom Node types
83 * @param {Object} This TreeLoader object.
84 * @param {Object} attr - the data returned from the AJAX call (modify it to suit)
89 Roo.tree.TreeLoader.superclass.constructor.call(this);
92 Roo.extend(Roo.tree.TreeLoader, Roo.util.Observable, {
94 * @cfg {String} dataUrl The URL from which to request a Json string which
95 * specifies an array of node definition object representing the child nodes
99 * @cfg {String} requestMethod either GET or POST
100 * defaults to POST (due to BC)
104 * @cfg {Object} baseParams (optional) An object containing properties which
105 * specify HTTP parameters to be passed to each request for child nodes.
108 * @cfg {Object} baseAttrs (optional) An object containing attributes to be added to all nodes
109 * created by this loader. If the attributes sent by the server have an attribute in this object,
110 * they take priority.
113 * @cfg {Object} uiProviders (optional) An object containing properties which
115 * DEPRECATED - use 'create' event handler to modify attributes - which affect creation.
116 * specify custom {@link Roo.tree.TreeNodeUI} implementations. If the optional
117 * <i>uiProvider</i> attribute of a returned child node is a string rather
118 * than a reference to a TreeNodeUI implementation, this that string value
119 * is used as a property name in the uiProviders object. You can define the provider named
120 * 'default' , and this will be used for all nodes (if no uiProvider is delivered by the node data)
125 * @cfg {Boolean} clearOnLoad (optional) Default to true. Remove previously existing
126 * child nodes before loading.
131 * @cfg {String} root (optional) Default to false. Use this to read data from an object
132 * property on loading, rather than expecting an array. (eg. more compatible to a standard
133 * Grid query { data : [ .....] }
138 * @cfg {String} queryParam (optional)
139 * Name of the query as it will be passed on the querystring (defaults to 'node')
140 * eg. the request will be ?node=[id]
147 * Load an {@link Roo.tree.TreeNode} from the URL specified in the constructor.
148 * This is called automatically when a node is expanded, but may be used to reload
149 * a node (or append new children if the {@link #clearOnLoad} option is false.)
150 * @param {Roo.tree.TreeNode} node
151 * @param {Function} callback
153 load : function(node, callback){
154 if(this.clearOnLoad){
155 while(node.firstChild){
156 node.removeChild(node.firstChild);
159 if(node.attributes.children){ // preloaded json children
160 var cs = node.attributes.children;
161 for(var i = 0, len = cs.length; i < len; i++){
162 node.appendChild(this.createNode(cs[i]));
164 if(typeof callback == "function"){
167 }else if(this.dataUrl){
168 this.requestData(node, callback);
172 getParams: function(node){
173 var buf = [], bp = this.baseParams;
175 if(typeof bp[key] != "function"){
176 buf.push(encodeURIComponent(key), "=", encodeURIComponent(bp[key]), "&");
179 var n = this.queryParam === false ? 'node' : this.queryParam;
180 buf.push(n + "=", encodeURIComponent(node.id));
184 requestData : function(node, callback){
185 if(this.fireEvent("beforeload", this, node, callback) !== false){
186 this.transId = Roo.Ajax.request({
187 method:this.requestMethod,
188 url: this.dataUrl||this.url,
189 success: this.handleResponse,
190 failure: this.handleFailure,
192 argument: {callback: callback, node: node},
193 params: this.getParams(node)
196 // if the load is cancelled, make sure we notify
197 // the node that we are done
198 if(typeof callback == "function"){
204 isLoading : function(){
205 return this.transId ? true : false;
209 if(this.isLoading()){
210 Roo.Ajax.abort(this.transId);
215 createNode : function(attr)
217 // apply baseAttrs, nice idea Corey!
219 Roo.applyIf(attr, this.baseAttrs);
221 if(this.applyLoader !== false){
224 // uiProvider = depreciated..
226 if(typeof(attr.uiProvider) == 'string'){
227 attr.uiProvider = this.uiProviders[attr.uiProvider] ||
228 /** eval:var:attr */ eval(attr.uiProvider);
230 if(typeof(this.uiProviders['default']) != 'undefined') {
231 attr.uiProvider = this.uiProviders['default'];
234 this.fireEvent('create', this, attr);
236 attr.leaf = typeof(attr.leaf) == 'string' ? attr.leaf * 1 : attr.leaf;
238 new Roo.tree.TreeNode(attr) :
239 new Roo.tree.AsyncTreeNode(attr));
242 processResponse : function(response, node, callback)
244 var json = response.responseText;
247 var o = Roo.decode(json);
249 if (this.root === false && typeof(o.success) != undefined) {
250 this.root = 'data'; // the default behaviour for list like data..
253 if (this.root !== false && !o.success) {
254 // it's a failure condition.
255 var a = response.argument;
256 this.fireEvent("loadexception", this, a.node, response);
257 Roo.log("Load failed - should have a handler really");
263 if (this.root !== false) {
267 for(var i = 0, len = o.length; i < len; i++){
268 var n = this.createNode(o[i]);
273 if(typeof callback == "function"){
274 callback(this, node);
277 this.handleFailure(response);
281 handleResponse : function(response){
282 this.transId = false;
283 var a = response.argument;
284 this.processResponse(response, a.node, a.callback);
285 this.fireEvent("load", this, a.node, response);
288 handleFailure : function(response)
290 // should handle failure better..
291 this.transId = false;
292 var a = response.argument;
293 this.fireEvent("loadexception", this, a.node, response);
294 if(typeof a.callback == "function"){
295 a.callback(this, a.node);