| 1 | efrain | 1 | YUI.add('tree-lazy', function (Y, NAME) {
 | 
        
           |  |  | 2 |   | 
        
           |  |  | 3 | /*jshint expr:true, maxlen:200, onevar:false */
 | 
        
           |  |  | 4 |   | 
        
           |  |  | 5 | /**
 | 
        
           |  |  | 6 | Provides `Plugin.Tree.Lazy`, a plugin for `Tree.Openable` that makes it easy to
 | 
        
           |  |  | 7 | lazily load and populate the contents of tree nodes the first time they're
 | 
        
           |  |  | 8 | opened.
 | 
        
           |  |  | 9 |   | 
        
           |  |  | 10 | @module tree
 | 
        
           |  |  | 11 | @submodule tree-lazy
 | 
        
           |  |  | 12 | **/
 | 
        
           |  |  | 13 |   | 
        
           |  |  | 14 | /**
 | 
        
           |  |  | 15 | A plugin for `Tree.Openable` that makes it easy to lazily load and populate the
 | 
        
           |  |  | 16 | contents of tree nodes the first time they're opened.
 | 
        
           |  |  | 17 |   | 
        
           |  |  | 18 | ### Example
 | 
        
           |  |  | 19 |   | 
        
           |  |  | 20 |     YUI().use('jsonp', 'tree-openable', 'tree-lazy', function (Y) {
 | 
        
           |  |  | 21 |         var Tree = Y.Base.create('openableTree', Y.Tree, [Y.Tree.Openable]),
 | 
        
           |  |  | 22 |             tree = new Tree();
 | 
        
           |  |  | 23 |   | 
        
           |  |  | 24 |         tree.plug(Y.Plugin.Tree.Lazy, {
 | 
        
           |  |  | 25 |   | 
        
           |  |  | 26 |             // Custom function that Plugin.Tree.Lazy will call when it needs to
 | 
        
           |  |  | 27 |             // load the children for a node.
 | 
        
           |  |  | 28 |             load: function (node, callback) {
 | 
        
           |  |  | 29 |                 // Request the data for this node's children via JSONP.
 | 
        
           |  |  | 30 |                 Y.jsonp('http://example.com/api/data?callback={callback}', function (data) {
 | 
        
           |  |  | 31 |                     // If we didn't get any data back, treat this as an error.
 | 
        
           |  |  | 32 |                     if (!data) {
 | 
        
           |  |  | 33 |                         callback(new Error('No data!'));
 | 
        
           |  |  | 34 |                         return;
 | 
        
           |  |  | 35 |                     }
 | 
        
           |  |  | 36 |   | 
        
           |  |  | 37 |                     // Append the children to the node (assume `data.children` is
 | 
        
           |  |  | 38 |                     // an array of child node data for the sake of this example).
 | 
        
           |  |  | 39 |                     node.append(data.children);
 | 
        
           |  |  | 40 |   | 
        
           |  |  | 41 |                     // Call the callback function to tell Plugin.Tree.Lazy that
 | 
        
           |  |  | 42 |                     // we're done loading data.
 | 
        
           |  |  | 43 |                     callback();
 | 
        
           |  |  | 44 |                 });
 | 
        
           |  |  | 45 |             }
 | 
        
           |  |  | 46 |   | 
        
           |  |  | 47 |         });
 | 
        
           |  |  | 48 |     });
 | 
        
           |  |  | 49 |   | 
        
           |  |  | 50 | @class Plugin.Tree.Lazy
 | 
        
           |  |  | 51 | @param {Object} config Config object.
 | 
        
           |  |  | 52 |   | 
        
           |  |  | 53 |     @param {Function} config.load Custom `load()` function that will be called
 | 
        
           |  |  | 54 |         when a node's children need to be loaded. This function must call the
 | 
        
           |  |  | 55 |         provided callback to indicate completion.
 | 
        
           |  |  | 56 |   | 
        
           |  |  | 57 |         @param {Function} config.load.callback Callback function. The custom
 | 
        
           |  |  | 58 |             `load()` function must call this callback to indicate completion.
 | 
        
           |  |  | 59 |   | 
        
           |  |  | 60 |             @param {Error} [config.load.callback.err] Error object. If provided,
 | 
        
           |  |  | 61 |                 the load action will be considered a failure, and an `error`
 | 
        
           |  |  | 62 |                 event will be fired. Omit this argument (or set it to `null`) to
 | 
        
           |  |  | 63 |                 indicate success.
 | 
        
           |  |  | 64 |   | 
        
           |  |  | 65 | @extends Plugin.Base
 | 
        
           |  |  | 66 | @constructor
 | 
        
           |  |  | 67 | **/
 | 
        
           |  |  | 68 |   | 
        
           |  |  | 69 | /**
 | 
        
           |  |  | 70 | Fired just before the custom `load()` method is called to load child nodes for a
 | 
        
           |  |  | 71 | node.
 | 
        
           |  |  | 72 |   | 
        
           |  |  | 73 | Calling `preventDefault()` on this event's facade will cancel the load action
 | 
        
           |  |  | 74 | and prevent the `load()` method from being called.
 | 
        
           |  |  | 75 |   | 
        
           |  |  | 76 | @event beforeLoad
 | 
        
           |  |  | 77 | @param {Tree.Node} node Tree node whose children will be loaded.
 | 
        
           |  |  | 78 | @preventable _defBeforeLoadFn
 | 
        
           |  |  | 79 | **/
 | 
        
           |  |  | 80 | var EVT_BEFORE_LOAD = 'beforeLoad';
 | 
        
           |  |  | 81 |   | 
        
           |  |  | 82 | /**
 | 
        
           |  |  | 83 | Fired when the `load()` method indicates there was an error loading child nodes.
 | 
        
           |  |  | 84 |   | 
        
           |  |  | 85 | @event error
 | 
        
           |  |  | 86 | @param {Error} error Error provided by the `load()` method.
 | 
        
           |  |  | 87 | @param {String} src Source of the error (defaults to "load").
 | 
        
           |  |  | 88 | **/
 | 
        
           |  |  | 89 | var EVT_ERROR = 'error';
 | 
        
           |  |  | 90 |   | 
        
           |  |  | 91 | /**
 | 
        
           |  |  | 92 | Fired after child nodes have finished loading and have been added to the tree.
 | 
        
           |  |  | 93 |   | 
        
           |  |  | 94 | @event load
 | 
        
           |  |  | 95 | @param {Tree.Node} node Tree node whose children have been loaded.
 | 
        
           |  |  | 96 | **/
 | 
        
           |  |  | 97 | var EVT_LOAD = 'load';
 | 
        
           |  |  | 98 |   | 
        
           |  |  | 99 | Y.namespace('Plugin.Tree').Lazy = Y.Base.create('lazyTreePlugin', Y.Plugin.Base, [], {
 | 
        
           |  |  | 100 |     // -- Lifecycle Methods ----------------------------------------------------
 | 
        
           |  |  | 101 |     initializer: function (config) {
 | 
        
           |  |  | 102 |         this._host = config.host;
 | 
        
           |  |  | 103 |   | 
        
           |  |  | 104 |         if (config.load) {
 | 
        
           |  |  | 105 |             this.load = config.load;
 | 
        
           |  |  | 106 |         }
 | 
        
           |  |  | 107 |   | 
        
           |  |  | 108 |         // Make sure we've been plugged into a Tree that mixes in the
 | 
        
           |  |  | 109 |         // Tree.Openable extension.
 | 
        
           |  |  | 110 |         if (!this._host.openNode) {
 | 
        
           |  |  | 111 |             Y.log("Plugin.Tree.Lazy was plugged into a Tree that doesn't mix in the Tree.Openable extension. This probably won't do you much good.", 'warn', 'tree-lazy');
 | 
        
           |  |  | 112 |         }
 | 
        
           |  |  | 113 |   | 
        
           |  |  | 114 |         this._published = {};
 | 
        
           |  |  | 115 |         this._attachEvents();
 | 
        
           |  |  | 116 |     },
 | 
        
           |  |  | 117 |   | 
        
           |  |  | 118 |     // -- Public Methods -------------------------------------------------------
 | 
        
           |  |  | 119 |     load: function (node, callback) {
 | 
        
           |  |  | 120 |         callback(new Error('Plugin.Tree.Lazy: Please provide a custom `load` method when instantiating this plugin.'));
 | 
        
           |  |  | 121 |     },
 | 
        
           |  |  | 122 |   | 
        
           |  |  | 123 |     // -- Protected Methods ----------------------------------------------------
 | 
        
           |  |  | 124 |     _attachEvents: function () {
 | 
        
           |  |  | 125 |         this.onHostEvent('open', this._onOpen);
 | 
        
           |  |  | 126 |     },
 | 
        
           |  |  | 127 |   | 
        
           |  |  | 128 |     // -- Protected Event Handlers ---------------------------------------------
 | 
        
           |  |  | 129 |     _onOpen: function (e) {
 | 
        
           |  |  | 130 |         var node = e.node;
 | 
        
           |  |  | 131 |   | 
        
           |  |  | 132 |         // Nothing to do if this node can't have children or if its children
 | 
        
           |  |  | 133 |         // have already been (or are already being) loaded.
 | 
        
           |  |  | 134 |         if (!node.canHaveChildren || node.state.loaded || node.state.loading) {
 | 
        
           |  |  | 135 |             return;
 | 
        
           |  |  | 136 |         }
 | 
        
           |  |  | 137 |   | 
        
           |  |  | 138 |         if (!this._published[EVT_BEFORE_LOAD]) {
 | 
        
           |  |  | 139 |             this._published[EVT_BEFORE_LOAD] = this.publish(EVT_BEFORE_LOAD, {
 | 
        
           |  |  | 140 |                 defaultFn: this._defLoadingFn
 | 
        
           |  |  | 141 |             });
 | 
        
           |  |  | 142 |         }
 | 
        
           |  |  | 143 |   | 
        
           |  |  | 144 |         this.fire(EVT_BEFORE_LOAD, {node: node});
 | 
        
           |  |  | 145 |     },
 | 
        
           |  |  | 146 |   | 
        
           |  |  | 147 |     // -- Default Event Handlers -----------------------------------------------
 | 
        
           |  |  | 148 |     _defLoadingFn: function (e) {
 | 
        
           |  |  | 149 |         var node = e.node,
 | 
        
           |  |  | 150 |             self = this;
 | 
        
           |  |  | 151 |   | 
        
           |  |  | 152 |         node.state.loading = true;
 | 
        
           |  |  | 153 |   | 
        
           |  |  | 154 |         this.load(node, function (err) {
 | 
        
           |  |  | 155 |             delete node.state.loading;
 | 
        
           |  |  | 156 |   | 
        
           |  |  | 157 |             if (err) {
 | 
        
           |  |  | 158 |                 self.fire(EVT_ERROR, {
 | 
        
           |  |  | 159 |                     error: err,
 | 
        
           |  |  | 160 |                     src  : 'load'
 | 
        
           |  |  | 161 |                 });
 | 
        
           |  |  | 162 |   | 
        
           |  |  | 163 |                 return;
 | 
        
           |  |  | 164 |             }
 | 
        
           |  |  | 165 |   | 
        
           |  |  | 166 |             node.state.loaded = true;
 | 
        
           |  |  | 167 |   | 
        
           |  |  | 168 |             self.fire(EVT_LOAD, {node: node});
 | 
        
           |  |  | 169 |         });
 | 
        
           |  |  | 170 |     }
 | 
        
           |  |  | 171 | }, {
 | 
        
           |  |  | 172 |     NS: 'lazy'
 | 
        
           |  |  | 173 | });
 | 
        
           |  |  | 174 |   | 
        
           |  |  | 175 |   | 
        
           |  |  | 176 | }, '3.18.1', {"requires": ["base-pluginhost", "plugin", "tree"]});
 |