Upgrade to ExtJS 3.1.1 - Released 02/08/2010
[extjs.git] / docs / source / TreeLoader.html
1 <html>\r
2 <head>\r
3   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />    \r
4   <title>The source code</title>\r
5     <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />\r
6     <script type="text/javascript" src="../resources/prettify/prettify.js"></script>\r
7 </head>\r
8 <body  onload="prettyPrint();">\r
9     <pre class="prettyprint lang-js"><div id="cls-Ext.tree.TreeLoader"></div>/**\r
10  * @class Ext.tree.TreeLoader\r
11  * @extends Ext.util.Observable\r
12  * A TreeLoader provides for lazy loading of an {@link Ext.tree.TreeNode}'s child\r
13  * nodes from a specified URL. The response must be a JavaScript Array definition\r
14  * whose elements are node definition objects. e.g.:\r
15  * <pre><code>\r
16     [{\r
17         id: 1,\r
18         text: 'A leaf Node',\r
19         leaf: true\r
20     },{\r
21         id: 2,\r
22         text: 'A folder Node',\r
23         children: [{\r
24             id: 3,\r
25             text: 'A child Node',\r
26             leaf: true\r
27         }]\r
28    }]\r
29 </code></pre>\r
30  * <br><br>\r
31  * A server request is sent, and child nodes are loaded only when a node is expanded.\r
32  * The loading node's id is passed to the server under the parameter name "node" to\r
33  * enable the server to produce the correct child nodes.\r
34  * <br><br>\r
35  * To pass extra parameters, an event handler may be attached to the "beforeload"\r
36  * event, and the parameters specified in the TreeLoader's baseParams property:\r
37  * <pre><code>\r
38     myTreeLoader.on("beforeload", function(treeLoader, node) {\r
39         this.baseParams.category = node.attributes.category;\r
40     }, this);\r
41 </code></pre>\r
42  * This would pass an HTTP parameter called "category" to the server containing\r
43  * the value of the Node's "category" attribute.\r
44  * @constructor\r
45  * Creates a new Treeloader.\r
46  * @param {Object} config A config object containing config properties.\r
47  */\r
48 Ext.tree.TreeLoader = function(config){\r
49     this.baseParams = {};\r
50     Ext.apply(this, config);\r
51 \r
52     this.addEvents(\r
53         <div id="event-Ext.tree.TreeLoader-beforeload"></div>/**\r
54          * @event beforeload\r
55          * Fires before a network request is made to retrieve the Json text which specifies a node's children.\r
56          * @param {Object} This TreeLoader object.\r
57          * @param {Object} node The {@link Ext.tree.TreeNode} object being loaded.\r
58          * @param {Object} callback The callback function specified in the {@link #load} call.\r
59          */\r
60         "beforeload",\r
61         <div id="event-Ext.tree.TreeLoader-load"></div>/**\r
62          * @event load\r
63          * Fires when the node has been successfuly loaded.\r
64          * @param {Object} This TreeLoader object.\r
65          * @param {Object} node The {@link Ext.tree.TreeNode} object being loaded.\r
66          * @param {Object} response The response object containing the data from the server.\r
67          */\r
68         "load",\r
69         <div id="event-Ext.tree.TreeLoader-loadexception"></div>/**\r
70          * @event loadexception\r
71          * Fires if the network request failed.\r
72          * @param {Object} This TreeLoader object.\r
73          * @param {Object} node The {@link Ext.tree.TreeNode} object being loaded.\r
74          * @param {Object} response The response object containing the data from the server.\r
75          */\r
76         "loadexception"\r
77     );\r
78     Ext.tree.TreeLoader.superclass.constructor.call(this);\r
79     if(Ext.isString(this.paramOrder)){\r
80         this.paramOrder = this.paramOrder.split(/[\s,|]/);\r
81     }\r
82 };\r
83 \r
84 Ext.extend(Ext.tree.TreeLoader, Ext.util.Observable, {\r
85     <div id="cfg-Ext.tree.TreeLoader-dataUrl"></div>/**\r
86     * @cfg {String} dataUrl The URL from which to request a Json string which\r
87     * specifies an array of node definition objects representing the child nodes\r
88     * to be loaded.\r
89     */\r
90     <div id="cfg-Ext.tree.TreeLoader-requestMethod"></div>/**\r
91      * @cfg {String} requestMethod The HTTP request method for loading data (defaults to the value of {@link Ext.Ajax#method}).\r
92      */\r
93     <div id="cfg-Ext.tree.TreeLoader-url"></div>/**\r
94      * @cfg {String} url Equivalent to {@link #dataUrl}.\r
95      */\r
96     <div id="cfg-Ext.tree.TreeLoader-preloadChildren"></div>/**\r
97      * @cfg {Boolean} preloadChildren If set to true, the loader recursively loads "children" attributes when doing the first load on nodes.\r
98      */\r
99     <div id="cfg-Ext.tree.TreeLoader-baseParams"></div>/**\r
100     * @cfg {Object} baseParams (optional) An object containing properties which\r
101     * specify HTTP parameters to be passed to each request for child nodes.\r
102     */\r
103     <div id="cfg-Ext.tree.TreeLoader-baseAttrs"></div>/**\r
104     * @cfg {Object} baseAttrs (optional) An object containing attributes to be added to all nodes\r
105     * created by this loader. If the attributes sent by the server have an attribute in this object,\r
106     * they take priority.\r
107     */\r
108     <div id="cfg-Ext.tree.TreeLoader-uiProviders"></div>/**\r
109     * @cfg {Object} uiProviders (optional) An object containing properties which\r
110     * specify custom {@link Ext.tree.TreeNodeUI} implementations. If the optional\r
111     * <i>uiProvider</i> attribute of a returned child node is a string rather\r
112     * than a reference to a TreeNodeUI implementation, then that string value\r
113     * is used as a property name in the uiProviders object.\r
114     */\r
115     uiProviders : {},\r
116 \r
117     <div id="cfg-Ext.tree.TreeLoader-clearOnLoad"></div>/**\r
118     * @cfg {Boolean} clearOnLoad (optional) Default to true. Remove previously existing\r
119     * child nodes before loading.\r
120     */\r
121     clearOnLoad : true,\r
122 \r
123     <div id="cfg-Ext.tree.TreeLoader-paramOrder"></div>/**\r
124      * @cfg {Array/String} paramOrder Defaults to <tt>undefined</tt>. Only used when using directFn.\r
125      * Specifies the params in the order in which they must be passed to the server-side Direct method\r
126      * as either (1) an Array of String values, or (2) a String of params delimited by either whitespace,\r
127      * comma, or pipe. For example,\r
128      * any of the following would be acceptable:<pre><code>\r
129 nodeParameter: 'node',\r
130 paramOrder: ['param1','param2','param3']\r
131 paramOrder: 'node param1 param2 param3'\r
132 paramOrder: 'param1,node,param2,param3'\r
133 paramOrder: 'param1|param2|param|node'\r
134      </code></pre>\r
135      */\r
136     paramOrder: undefined,\r
137 \r
138     <div id="cfg-Ext.tree.TreeLoader-paramsAsHash"></div>/**\r
139      * @cfg {Boolean} paramsAsHash Only used when using directFn.\r
140      * Send parameters as a collection of named arguments (defaults to <tt>false</tt>). Providing a\r
141      * <tt>{@link #paramOrder}</tt> nullifies this configuration.\r
142      */\r
143     paramsAsHash: false,\r
144 \r
145     <div id="cfg-Ext.tree.TreeLoader-nodeParameter"></div>/**\r
146      * @cfg {String} nodeParameter The name of the parameter sent to the server which contains\r
147      * the identifier of the node. Defaults to <tt>'node'</tt>.\r
148      */\r
149     nodeParameter: 'node',\r
150 \r
151     <div id="cfg-Ext.tree.TreeLoader-directFn"></div>/**\r
152      * @cfg {Function} directFn\r
153      * Function to call when executing a request.\r
154      */\r
155     directFn : undefined,\r
156 \r
157     <div id="method-Ext.tree.TreeLoader-load"></div>/**\r
158      * Load an {@link Ext.tree.TreeNode} from the URL specified in the constructor.\r
159      * This is called automatically when a node is expanded, but may be used to reload\r
160      * a node (or append new children if the {@link #clearOnLoad} option is false.)\r
161      * @param {Ext.tree.TreeNode} node\r
162      * @param {Function} callback Function to call after the node has been loaded. The\r
163      * function is passed the TreeNode which was requested to be loaded.\r
164      * @param (Object) scope The cope (<code>this</code> reference) in which the callback is executed.\r
165      * defaults to the loaded TreeNode.\r
166      */\r
167     load : function(node, callback, scope){\r
168         if(this.clearOnLoad){\r
169             while(node.firstChild){\r
170                 node.removeChild(node.firstChild);\r
171             }\r
172         }\r
173         if(this.doPreload(node)){ // preloaded json children\r
174             this.runCallback(callback, scope || node, [node]);\r
175         }else if(this.directFn || this.dataUrl || this.url){\r
176             this.requestData(node, callback, scope || node);\r
177         }\r
178     },\r
179 \r
180     doPreload : function(node){\r
181         if(node.attributes.children){\r
182             if(node.childNodes.length < 1){ // preloaded?\r
183                 var cs = node.attributes.children;\r
184                 node.beginUpdate();\r
185                 for(var i = 0, len = cs.length; i < len; i++){\r
186                     var cn = node.appendChild(this.createNode(cs[i]));\r
187                     if(this.preloadChildren){\r
188                         this.doPreload(cn);\r
189                     }\r
190                 }\r
191                 node.endUpdate();\r
192             }\r
193             return true;\r
194         }\r
195         return false;\r
196     },\r
197 \r
198     getParams: function(node){\r
199         var bp = Ext.apply({}, this.baseParams),\r
200             np = this.nodeParameter,\r
201             po = this.paramOrder;\r
202 \r
203         np && (bp[ np ] = node.id);\r
204 \r
205         if(this.directFn){\r
206             var buf = [node.id];\r
207             if(po){\r
208                 // reset 'buf' if the nodeParameter was included in paramOrder\r
209                 if(np && po.indexOf(np) > -1){\r
210                     buf = [];\r
211                 }\r
212 \r
213                 for(var i = 0, len = po.length; i < len; i++){\r
214                     buf.push(bp[ po[i] ]);\r
215                 }\r
216             }else if(this.paramsAsHash){\r
217                 buf = [bp];\r
218             }\r
219             return buf;\r
220         }else{\r
221             return bp;\r
222         }\r
223     },\r
224 \r
225     requestData : function(node, callback, scope){\r
226         if(this.fireEvent("beforeload", this, node, callback) !== false){\r
227             if(this.directFn){\r
228                 var args = this.getParams(node);\r
229                 args.push(this.processDirectResponse.createDelegate(this, [{callback: callback, node: node, scope: scope}], true));\r
230                 this.directFn.apply(window, args);\r
231             }else{\r
232                 this.transId = Ext.Ajax.request({\r
233                     method:this.requestMethod,\r
234                     url: this.dataUrl||this.url,\r
235                     success: this.handleResponse,\r
236                     failure: this.handleFailure,\r
237                     scope: this,\r
238                     argument: {callback: callback, node: node, scope: scope},\r
239                     params: this.getParams(node)\r
240                 });\r
241             }\r
242         }else{\r
243             // if the load is cancelled, make sure we notify\r
244             // the node that we are done\r
245             this.runCallback(callback, scope || node, []);\r
246         }\r
247     },\r
248 \r
249     processDirectResponse: function(result, response, args){\r
250         if(response.status){\r
251             this.handleResponse({\r
252                 responseData: Ext.isArray(result) ? result : null,\r
253                 responseText: result,\r
254                 argument: args\r
255             });\r
256         }else{\r
257             this.handleFailure({\r
258                 argument: args\r
259             });\r
260         }\r
261     },\r
262 \r
263     // private\r
264     runCallback: function(cb, scope, args){\r
265         if(Ext.isFunction(cb)){\r
266             cb.apply(scope, args);\r
267         }\r
268     },\r
269 \r
270     isLoading : function(){\r
271         return !!this.transId;\r
272     },\r
273 \r
274     abort : function(){\r
275         if(this.isLoading()){\r
276             Ext.Ajax.abort(this.transId);\r
277         }\r
278     },\r
279 \r
280     <div id="method-Ext.tree.TreeLoader-createNode"></div>/**\r
281     * <p>Override this function for custom TreeNode node implementation, or to\r
282     * modify the attributes at creation time.</p>\r
283     * Example:<pre><code>\r
284 new Ext.tree.TreePanel({\r
285     ...\r
286     loader: new Ext.tree.TreeLoader({\r
287         url: 'dataUrl',\r
288         createNode: function(attr) {\r
289 //          Allow consolidation consignments to have\r
290 //          consignments dropped into them.\r
291             if (attr.isConsolidation) {\r
292                 attr.iconCls = 'x-consol',\r
293                 attr.allowDrop = true;\r
294             }\r
295             return Ext.tree.TreeLoader.prototype.createNode.call(this, attr);\r
296         }\r
297     }),\r
298     ...\r
299 });\r
300 </code></pre>\r
301     * @param attr {Object} The attributes from which to create the new node.\r
302     */\r
303     createNode : function(attr){\r
304         // apply baseAttrs, nice idea Corey!\r
305         if(this.baseAttrs){\r
306             Ext.applyIf(attr, this.baseAttrs);\r
307         }\r
308         if(this.applyLoader !== false && !attr.loader){\r
309             attr.loader = this;\r
310         }\r
311         if(Ext.isString(attr.uiProvider)){\r
312            attr.uiProvider = this.uiProviders[attr.uiProvider] || eval(attr.uiProvider);\r
313         }\r
314         if(attr.nodeType){\r
315             return new Ext.tree.TreePanel.nodeTypes[attr.nodeType](attr);\r
316         }else{\r
317             return attr.leaf ?\r
318                         new Ext.tree.TreeNode(attr) :\r
319                         new Ext.tree.AsyncTreeNode(attr);\r
320         }\r
321     },\r
322 \r
323     processResponse : function(response, node, callback, scope){\r
324         var json = response.responseText;\r
325         try {\r
326             var o = response.responseData || Ext.decode(json);\r
327             node.beginUpdate();\r
328             for(var i = 0, len = o.length; i < len; i++){\r
329                 var n = this.createNode(o[i]);\r
330                 if(n){\r
331                     node.appendChild(n);\r
332                 }\r
333             }\r
334             node.endUpdate();\r
335             this.runCallback(callback, scope || node, [node]);\r
336         }catch(e){\r
337             this.handleFailure(response);\r
338         }\r
339     },\r
340 \r
341     handleResponse : function(response){\r
342         this.transId = false;\r
343         var a = response.argument;\r
344         this.processResponse(response, a.node, a.callback, a.scope);\r
345         this.fireEvent("load", this, a.node, response);\r
346     },\r
347 \r
348     handleFailure : function(response){\r
349         this.transId = false;\r
350         var a = response.argument;\r
351         this.fireEvent("loadexception", this, a.node, response);\r
352         this.runCallback(a.callback, a.scope || a.node, [a.node]);\r
353     },\r
354 \r
355     destroy : function(){\r
356         this.abort();\r
357         this.purgeListeners();\r
358     }\r
359 });</pre>    \r
360 </body>\r
361 </html>