~cdparra/gelee/trunk

« back to all changes in this revision

Viewing changes to webui/ecosystem/extjs/source/widgets/tree/TreeLoader.js

  • Committer: parra
  • Date: 2010-03-15 02:39:02 UTC
  • Revision ID: svn-v4:ac5bba68-f036-4e09-846e-8f32731cc928:trunk/gelee:1433
merged gelee at svn

Show diffs side-by-side

added added

removed removed

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