TreeLoader.js
上传用户:shuoshiled
上传日期:2018-01-28
资源大小:10124k
文件大小:12k
源码类别:

中间件编程

开发平台:

JavaScript

  1. /*!  * Ext JS Library 3.0.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(typeof this.paramOrder == 'string'){
  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.      * @cfg {Function} directFn
  133.      * Function to call when executing a request.
  134.      */
  135.     directFn : undefined,
  136.     /**
  137.      * Load an {@link Ext.tree.TreeNode} from the URL specified in the constructor.
  138.      * This is called automatically when a node is expanded, but may be used to reload
  139.      * a node (or append new children if the {@link #clearOnLoad} option is false.)
  140.      * @param {Ext.tree.TreeNode} node
  141.      * @param {Function} callback
  142.      * @param (Object) scope
  143.      */
  144.     load : function(node, callback, scope){
  145.         if(this.clearOnLoad){
  146.             while(node.firstChild){
  147.                 node.removeChild(node.firstChild);
  148.             }
  149.         }
  150.         if(this.doPreload(node)){ // preloaded json children
  151.             this.runCallback(callback, scope || node, []);
  152.         }else if(this.directFn || this.dataUrl || this.url){
  153.             this.requestData(node, callback, scope || node);
  154.         }
  155.     },
  156.     doPreload : function(node){
  157.         if(node.attributes.children){
  158.             if(node.childNodes.length < 1){ // preloaded?
  159.                 var cs = node.attributes.children;
  160.                 node.beginUpdate();
  161.                 for(var i = 0, len = cs.length; i < len; i++){
  162.                     var cn = node.appendChild(this.createNode(cs[i]));
  163.                     if(this.preloadChildren){
  164.                         this.doPreload(cn);
  165.                     }
  166.                 }
  167.                 node.endUpdate();
  168.             }
  169.             return true;
  170.         }
  171.         return false;
  172.     },
  173.     getParams: function(node){
  174.         var buf = [], bp = this.baseParams;
  175.         if(this.directFn){
  176.             buf.push(node.id);
  177.             if(bp){
  178.                 if(this.paramOrder){
  179.                     for(var i = 0, len = this.paramOrder.length; i < len; i++){
  180.                         buf.push(bp[this.paramOrder[i]]);
  181.                     }
  182.                 }else if(this.paramsAsHash){
  183.                     buf.push(bp);
  184.                 }
  185.             }
  186.             return buf;
  187.         }else{
  188.             for(var key in bp){
  189.                 if(!Ext.isFunction(bp[key])){
  190.                     buf.push(encodeURIComponent(key), "=", encodeURIComponent(bp[key]), "&");
  191.                 }
  192.             }
  193.             buf.push("node=", encodeURIComponent(node.id));
  194.             return buf.join("");
  195.         }
  196.     },
  197.     requestData : function(node, callback, scope){
  198.         if(this.fireEvent("beforeload", this, node, callback) !== false){
  199.             if(this.directFn){
  200.                 var args = this.getParams(node);
  201.                 args.push(this.processDirectResponse.createDelegate(this, [{callback: callback, node: node, scope: scope}], true));
  202.                 this.directFn.apply(window, args);
  203.             }else{
  204.                 this.transId = Ext.Ajax.request({
  205.                     method:this.requestMethod,
  206.                     url: this.dataUrl||this.url,
  207.                     success: this.handleResponse,
  208.                     failure: this.handleFailure,
  209.                     scope: this,
  210.                     argument: {callback: callback, node: node, scope: scope},
  211.                     params: this.getParams(node)
  212.                 });
  213.             }
  214.         }else{
  215.             // if the load is cancelled, make sure we notify
  216.             // the node that we are done
  217.             this.runCallback(callback, scope || node, []);
  218.         }
  219.     },
  220.     processDirectResponse: function(result, response, args){
  221.         if(response.status){
  222.             this.handleResponse({
  223.                 responseData: Ext.isArray(result) ? result : null,
  224.                 responseText: result,
  225.                 argument: args
  226.             });
  227.         }else{
  228.             this.handleFailure({
  229.                 argument: args
  230.             });
  231.         }
  232.     },
  233.     // private
  234.     runCallback: function(cb, scope, args){
  235.         if(Ext.isFunction(cb)){
  236.             cb.apply(scope, args);
  237.         }
  238.     },
  239.     isLoading : function(){
  240.         return !!this.transId;
  241.     },
  242.     abort : function(){
  243.         if(this.isLoading()){
  244.             Ext.Ajax.abort(this.transId);
  245.         }
  246.     },
  247.     /**
  248.     * <p>Override this function for custom TreeNode node implementation, or to
  249.     * modify the attributes at creation time.</p>
  250.     * Example:<pre><code>
  251. new Ext.tree.TreePanel({
  252.     ...
  253.     new Ext.tree.TreeLoader({
  254.         url: 'dataUrl',
  255.         createNode: function(attr) {
  256. //          Allow consolidation consignments to have
  257. //          consignments dropped into them.
  258.             if (attr.isConsolidation) {
  259.                 attr.iconCls = 'x-consol',
  260.                 attr.allowDrop = true;
  261.             }
  262.             return Ext.tree.TreeLoader.prototype.call(this, attr);
  263.         }
  264.     }),
  265.     ...
  266. });
  267. </code></pre>
  268.     * @param attr {Object} The attributes from which to create the new node.
  269.     */
  270.     createNode : function(attr){
  271.         // apply baseAttrs, nice idea Corey!
  272.         if(this.baseAttrs){
  273.             Ext.applyIf(attr, this.baseAttrs);
  274.         }
  275.         if(this.applyLoader !== false){
  276.             attr.loader = this;
  277.         }
  278.         if(typeof attr.uiProvider == 'string'){
  279.            attr.uiProvider = this.uiProviders[attr.uiProvider] || eval(attr.uiProvider);
  280.         }
  281.         if(attr.nodeType){
  282.             return new Ext.tree.TreePanel.nodeTypes[attr.nodeType](attr);
  283.         }else{
  284.             return attr.leaf ?
  285.                         new Ext.tree.TreeNode(attr) :
  286.                         new Ext.tree.AsyncTreeNode(attr);
  287.         }
  288.     },
  289.     processResponse : function(response, node, callback, scope){
  290.         var json = response.responseText;
  291.         try {
  292.             var o = response.responseData || Ext.decode(json);
  293.             node.beginUpdate();
  294.             for(var i = 0, len = o.length; i < len; i++){
  295.                 var n = this.createNode(o[i]);
  296.                 if(n){
  297.                     node.appendChild(n);
  298.                 }
  299.             }
  300.             node.endUpdate();
  301.             this.runCallback(callback, scope || node, [node]);
  302.         }catch(e){
  303.             this.handleFailure(response);
  304.         }
  305.     },
  306.     handleResponse : function(response){
  307.         this.transId = false;
  308.         var a = response.argument;
  309.         this.processResponse(response, a.node, a.callback, a.scope);
  310.         this.fireEvent("load", this, a.node, response);
  311.     },
  312.     handleFailure : function(response){
  313.         this.transId = false;
  314.         var a = response.argument;
  315.         this.fireEvent("loadexception", this, a.node, response);
  316.         this.runCallback(a.callback, a.scope || a.node, [a.node]);
  317.     }
  318. });