You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

242 lines
7.8 KiB

  1. // Extending Fancytree
  2. // ===================
  3. //
  4. // See also the [live demo](https://wwWendt.de/tech/fancytree/demo/sample-ext-childcounter.html) of this code.
  5. //
  6. // Every extension should have a comment header containing some information
  7. // about the author, copyright and licensing. Also a pointer to the latest
  8. // source code.
  9. // Prefix with `/*!` so the comment is not removed by the minifier.
  10. /*!
  11. * jquery.fancytree.childcounter.js
  12. *
  13. * Add a child counter bubble to tree nodes.
  14. * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
  15. *
  16. * Copyright (c) 2008-2023, Martin Wendt (https://wwWendt.de)
  17. *
  18. * Released under the MIT license
  19. * https://github.com/mar10/fancytree/wiki/LicenseInfo
  20. *
  21. * @version 2.38.3
  22. * @date 2023-02-01T20:52:50Z
  23. */
  24. // To keep the global namespace clean, we wrap everything in a closure.
  25. // The UMD wrapper pattern defines the dependencies on jQuery and the
  26. // Fancytree core module, and makes sure that we can use the `require()`
  27. // syntax with package loaders.
  28. (function (factory) {
  29. if (typeof define === "function" && define.amd) {
  30. // AMD. Register as an anonymous module.
  31. define(["jquery", "./jquery.fancytree"], factory);
  32. } else if (typeof module === "object" && module.exports) {
  33. // Node/CommonJS
  34. require("./jquery.fancytree");
  35. module.exports = factory(require("jquery"));
  36. } else {
  37. // Browser globals
  38. factory(jQuery);
  39. }
  40. })(function ($) {
  41. // Consider to use [strict mode](http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/)
  42. "use strict";
  43. // The [coding guidelines](http://contribute.jquery.org/style-guide/js/)
  44. // require jshint /eslint compliance.
  45. // But for this sample, we want to allow unused variables for demonstration purpose.
  46. /*eslint-disable no-unused-vars */
  47. // Adding methods
  48. // --------------
  49. // New member functions can be added to the `Fancytree` class.
  50. // This function will be available for every tree instance:
  51. //
  52. // var tree = $.ui.fancytree.getTree("#tree");
  53. // tree.countSelected(false);
  54. $.ui.fancytree._FancytreeClass.prototype.countSelected = function (
  55. topOnly
  56. ) {
  57. var tree = this,
  58. treeOptions = tree.options;
  59. return tree.getSelectedNodes(topOnly).length;
  60. };
  61. // The `FancytreeNode` class can also be easily extended. This would be called
  62. // like
  63. // node.updateCounters();
  64. //
  65. // It is also good practice to add a docstring comment.
  66. /**
  67. * [ext-childcounter] Update counter badges for `node` and its parents.
  68. * May be called in the `loadChildren` event, to update parents of lazy loaded
  69. * nodes.
  70. * @alias FancytreeNode#updateCounters
  71. * @requires jquery.fancytree.childcounters.js
  72. */
  73. $.ui.fancytree._FancytreeNodeClass.prototype.updateCounters = function () {
  74. var node = this,
  75. $badge = $("span.fancytree-childcounter", node.span),
  76. extOpts = node.tree.options.childcounter,
  77. count = node.countChildren(extOpts.deep);
  78. node.data.childCounter = count;
  79. if (
  80. (count || !extOpts.hideZeros) &&
  81. (!node.isExpanded() || !extOpts.hideExpanded)
  82. ) {
  83. if (!$badge.length) {
  84. $badge = $("<span class='fancytree-childcounter'/>").appendTo(
  85. $(
  86. "span.fancytree-icon,span.fancytree-custom-icon",
  87. node.span
  88. )
  89. );
  90. }
  91. $badge.text(count);
  92. } else {
  93. $badge.remove();
  94. }
  95. if (extOpts.deep && !node.isTopLevel() && !node.isRootNode()) {
  96. node.parent.updateCounters();
  97. }
  98. };
  99. // Finally, we can extend the widget API and create functions that are called
  100. // like so:
  101. //
  102. // $("#tree").fancytree("widgetMethod1", "abc");
  103. $.ui.fancytree.prototype.widgetMethod1 = function (arg1) {
  104. var tree = this.tree;
  105. return arg1;
  106. };
  107. // Register a Fancytree extension
  108. // ------------------------------
  109. // A full blown extension, extension is available for all trees and can be
  110. // enabled like so (see also the [live demo](https://wwWendt.de/tech/fancytree/demo/sample-ext-childcounter.html)):
  111. //
  112. // <script src="../src/jquery.fancytree.js"></script>
  113. // <script src="../src/jquery.fancytree.childcounter.js"></script>
  114. // ...
  115. //
  116. // $("#tree").fancytree({
  117. // extensions: ["childcounter"],
  118. // childcounter: {
  119. // hideExpanded: true
  120. // },
  121. // ...
  122. // });
  123. //
  124. /* 'childcounter' extension */
  125. $.ui.fancytree.registerExtension({
  126. // Every extension must be registered by a unique name.
  127. name: "childcounter",
  128. // Version information should be compliant with [semver](http://semver.org)
  129. version: "2.38.3",
  130. // Extension specific options and their defaults.
  131. // This options will be available as `tree.options.childcounter.hideExpanded`
  132. options: {
  133. deep: true,
  134. hideZeros: true,
  135. hideExpanded: false,
  136. },
  137. // Attributes other than `options` (or functions) can be defined here, and
  138. // will be added to the tree.ext.EXTNAME namespace, in this case `tree.ext.childcounter.foo`.
  139. // They can also be accessed as `this._local.foo` from within the extension
  140. // methods.
  141. foo: 42,
  142. // Local functions are prefixed with an underscore '_'.
  143. // Callable as `this._local._appendCounter()`.
  144. _appendCounter: function (bar) {
  145. var tree = this;
  146. },
  147. // **Override virtual methods for this extension.**
  148. //
  149. // Fancytree implements a number of 'hook methods', prefixed by 'node...' or 'tree...'.
  150. // with a `ctx` argument (see [EventData](https://wwWendt.de/tech/fancytree/doc/jsdoc/global.html#EventData)
  151. // for details) and an extended calling context:<br>
  152. // `this` : the Fancytree instance<br>
  153. // `this._local`: the namespace that contains extension attributes and private methods (same as this.ext.EXTNAME)<br>
  154. // `this._super`: the virtual function that was overridden (member of previous extension or Fancytree)
  155. //
  156. // See also the [complete list of available hook functions](https://wwWendt.de/tech/fancytree/doc/jsdoc/Fancytree_Hooks.html).
  157. /* Init */
  158. // `treeInit` is triggered when a tree is initalized. We can set up classes or
  159. // bind event handlers here...
  160. treeInit: function (ctx) {
  161. var tree = this, // same as ctx.tree,
  162. opts = ctx.options,
  163. extOpts = ctx.options.childcounter;
  164. // Optionally check for dependencies with other extensions
  165. /* this._requireExtension("glyph", false, false); */
  166. // Call the base implementation
  167. this._superApply(arguments);
  168. // Add a class to the tree container
  169. this.$container.addClass("fancytree-ext-childcounter");
  170. },
  171. // Destroy this tree instance (we only call the default implementation, so
  172. // this method could as well be omitted).
  173. treeDestroy: function (ctx) {
  174. this._superApply(arguments);
  175. },
  176. // Overload the `renderTitle` hook, to append a counter badge
  177. nodeRenderTitle: function (ctx, title) {
  178. var node = ctx.node,
  179. extOpts = ctx.options.childcounter,
  180. count =
  181. node.data.childCounter == null
  182. ? node.countChildren(extOpts.deep)
  183. : +node.data.childCounter;
  184. // Let the base implementation render the title
  185. // We use `_super()` instead of `_superApply()` here, since it is a little bit
  186. // more performant when called often
  187. this._super(ctx, title);
  188. // Append a counter badge
  189. if (
  190. (count || !extOpts.hideZeros) &&
  191. (!node.isExpanded() || !extOpts.hideExpanded)
  192. ) {
  193. $(
  194. "span.fancytree-icon,span.fancytree-custom-icon",
  195. node.span
  196. ).append(
  197. $("<span class='fancytree-childcounter'/>").text(count)
  198. );
  199. }
  200. },
  201. // Overload the `setExpanded` hook, so the counters are updated
  202. nodeSetExpanded: function (ctx, flag, callOpts) {
  203. var tree = ctx.tree,
  204. node = ctx.node;
  205. // Let the base implementation expand/collapse the node, then redraw the title
  206. // after the animation has finished
  207. return this._superApply(arguments).always(function () {
  208. tree.nodeRenderTitle(ctx);
  209. });
  210. },
  211. // End of extension definition
  212. });
  213. // Value returned by `require('jquery.fancytree..')`
  214. return $.ui.fancytree;
  215. }); // End of closure