API Docs for: 3.10.3
Show:

File: tree/js/plugins/tree-lazy.js

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