tree-series.js 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. import H from '../parts/Globals.js';
  2. var extend = H.extend,
  3. isArray = H.isArray,
  4. isBoolean = function (x) {
  5. return typeof x === 'boolean';
  6. },
  7. isFn = function (x) {
  8. return typeof x === 'function';
  9. },
  10. isObject = H.isObject,
  11. isNumber = H.isNumber,
  12. merge = H.merge,
  13. pick = H.pick;
  14. // TODO Combine buildTree and buildNode with setTreeValues
  15. // TODO Remove logic from Treemap and make it utilize this mixin.
  16. var setTreeValues = function setTreeValues(tree, options) {
  17. var before = options.before,
  18. idRoot = options.idRoot,
  19. mapIdToNode = options.mapIdToNode,
  20. nodeRoot = mapIdToNode[idRoot],
  21. levelIsConstant = (
  22. isBoolean(options.levelIsConstant) ?
  23. options.levelIsConstant :
  24. true
  25. ),
  26. points = options.points,
  27. point = points[tree.i],
  28. optionsPoint = point && point.options || {},
  29. childrenTotal = 0,
  30. children = [],
  31. value;
  32. extend(tree, {
  33. levelDynamic: tree.level - (levelIsConstant ? 0 : nodeRoot.level),
  34. name: pick(point && point.name, ''),
  35. visible: (
  36. idRoot === tree.id ||
  37. (isBoolean(options.visible) ? options.visible : false)
  38. )
  39. });
  40. if (isFn(before)) {
  41. tree = before(tree, options);
  42. }
  43. // First give the children some values
  44. tree.children.forEach(function (child, i) {
  45. var newOptions = extend({}, options);
  46. extend(newOptions, {
  47. index: i,
  48. siblings: tree.children.length,
  49. visible: tree.visible
  50. });
  51. child = setTreeValues(child, newOptions);
  52. children.push(child);
  53. if (child.visible) {
  54. childrenTotal += child.val;
  55. }
  56. });
  57. tree.visible = childrenTotal > 0 || tree.visible;
  58. // Set the values
  59. value = pick(optionsPoint.value, childrenTotal);
  60. extend(tree, {
  61. children: children,
  62. childrenTotal: childrenTotal,
  63. isLeaf: tree.visible && !childrenTotal,
  64. val: value
  65. });
  66. return tree;
  67. };
  68. var getColor = function getColor(node, options) {
  69. var index = options.index,
  70. mapOptionsToLevel = options.mapOptionsToLevel,
  71. parentColor = options.parentColor,
  72. parentColorIndex = options.parentColorIndex,
  73. series = options.series,
  74. colors = options.colors,
  75. siblings = options.siblings,
  76. points = series.points,
  77. getColorByPoint,
  78. chartOptionsChart = series.chart.options.chart,
  79. point,
  80. level,
  81. colorByPoint,
  82. colorIndexByPoint,
  83. color,
  84. colorIndex;
  85. function variation(color) {
  86. var colorVariation = level && level.colorVariation;
  87. if (colorVariation) {
  88. if (colorVariation.key === 'brightness') {
  89. return H.color(color).brighten(
  90. colorVariation.to * (index / siblings)
  91. ).get();
  92. }
  93. }
  94. return color;
  95. }
  96. if (node) {
  97. point = points[node.i];
  98. level = mapOptionsToLevel[node.level] || {};
  99. getColorByPoint = point && level.colorByPoint;
  100. if (getColorByPoint) {
  101. colorIndexByPoint = point.index % (colors ?
  102. colors.length :
  103. chartOptionsChart.colorCount
  104. );
  105. colorByPoint = colors && colors[colorIndexByPoint];
  106. }
  107. // Select either point color, level color or inherited color.
  108. if (!series.chart.styledMode) {
  109. color = pick(
  110. point && point.options.color,
  111. level && level.color,
  112. colorByPoint,
  113. parentColor && variation(parentColor),
  114. series.color
  115. );
  116. }
  117. colorIndex = pick(
  118. point && point.options.colorIndex,
  119. level && level.colorIndex,
  120. colorIndexByPoint,
  121. parentColorIndex,
  122. options.colorIndex
  123. );
  124. }
  125. return {
  126. color: color,
  127. colorIndex: colorIndex
  128. };
  129. };
  130. /**
  131. * Creates a map from level number to its given options.
  132. *
  133. * @private
  134. * @function getLevelOptions
  135. *
  136. * @param {object} params
  137. * Object containing parameters.
  138. * - `defaults` Object containing default options. The default options
  139. * are merged with the userOptions to get the final options for a
  140. * specific level.
  141. * - `from` The lowest level number.
  142. * - `levels` User options from series.levels.
  143. * - `to` The highest level number.
  144. *
  145. * @return {Highcharts.Dictionary<object>}
  146. * Returns a map from level number to its given options.
  147. */
  148. var getLevelOptions = function getLevelOptions(params) {
  149. var result = null,
  150. defaults,
  151. converted,
  152. i,
  153. from,
  154. to,
  155. levels;
  156. if (isObject(params)) {
  157. result = {};
  158. from = isNumber(params.from) ? params.from : 1;
  159. levels = params.levels;
  160. converted = {};
  161. defaults = isObject(params.defaults) ? params.defaults : {};
  162. if (isArray(levels)) {
  163. converted = levels.reduce(function (obj, item) {
  164. var level,
  165. levelIsConstant,
  166. options;
  167. if (isObject(item) && isNumber(item.level)) {
  168. options = merge({}, item);
  169. levelIsConstant = (
  170. isBoolean(options.levelIsConstant) ?
  171. options.levelIsConstant :
  172. defaults.levelIsConstant
  173. );
  174. // Delete redundant properties.
  175. delete options.levelIsConstant;
  176. delete options.level;
  177. // Calculate which level these options apply to.
  178. level = item.level + (levelIsConstant ? 0 : from - 1);
  179. if (isObject(obj[level])) {
  180. extend(obj[level], options);
  181. } else {
  182. obj[level] = options;
  183. }
  184. }
  185. return obj;
  186. }, {});
  187. }
  188. to = isNumber(params.to) ? params.to : 1;
  189. for (i = 0; i <= to; i++) {
  190. result[i] = merge(
  191. {},
  192. defaults,
  193. isObject(converted[i]) ? converted[i] : {}
  194. );
  195. }
  196. }
  197. return result;
  198. };
  199. /**
  200. * Update the rootId property on the series. Also makes sure that it is
  201. * accessible to exporting.
  202. *
  203. * @private
  204. * @function updateRootId
  205. *
  206. * @param {object} series
  207. * The series to operate on.
  208. *
  209. * @return {string}
  210. * Returns the resulting rootId after update.
  211. */
  212. var updateRootId = function (series) {
  213. var rootId,
  214. options;
  215. if (isObject(series)) {
  216. // Get the series options.
  217. options = isObject(series.options) ? series.options : {};
  218. // Calculate the rootId.
  219. rootId = pick(series.rootNode, options.rootId, '');
  220. // Set rootId on series.userOptions to pick it up in exporting.
  221. if (isObject(series.userOptions)) {
  222. series.userOptions.rootId = rootId;
  223. }
  224. // Set rootId on series to pick it up on next update.
  225. series.rootNode = rootId;
  226. }
  227. return rootId;
  228. };
  229. var result = {
  230. getColor: getColor,
  231. getLevelOptions: getLevelOptions,
  232. setTreeValues: setTreeValues,
  233. updateRootId: updateRootId
  234. };
  235. export default result;