TreeLoader.js
上传用户:dawnssy
上传日期:2022-08-06
资源大小:9345k
文件大小:12k
源码类别:

JavaScript

开发平台:

JavaScript

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