TreeGridTick.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. /* *
  2. *
  3. * (c) 2016 Highsoft AS
  4. * Authors: Jon Arild Nygard
  5. *
  6. * License: www.highcharts.com/license
  7. *
  8. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  9. *
  10. * */
  11. 'use strict';
  12. import U from '../Utilities.js';
  13. var addEvent = U.addEvent, defined = U.defined, isObject = U.isObject, isNumber = U.isNumber, pick = U.pick, wrap = U.wrap;
  14. /**
  15. * @private
  16. */
  17. var TreeGridTick;
  18. (function (TreeGridTick) {
  19. /* *
  20. *
  21. * Interfaces
  22. *
  23. * */
  24. /* *
  25. *
  26. * Variables
  27. *
  28. * */
  29. var applied = false;
  30. /* *
  31. *
  32. * Functions
  33. *
  34. * */
  35. /**
  36. * @private
  37. */
  38. function compose(TickClass) {
  39. if (!applied) {
  40. addEvent(TickClass, 'init', onInit);
  41. wrap(TickClass.prototype, 'getLabelPosition', wrapGetLabelPosition);
  42. wrap(TickClass.prototype, 'renderLabel', wrapRenderLabel);
  43. // backwards compatibility
  44. TickClass.prototype.collapse = function (redraw) {
  45. this.treeGrid.collapse(redraw);
  46. };
  47. TickClass.prototype.expand = function (redraw) {
  48. this.treeGrid.expand(redraw);
  49. };
  50. TickClass.prototype.toggleCollapse = function (redraw) {
  51. this.treeGrid.toggleCollapse(redraw);
  52. };
  53. applied = true;
  54. }
  55. }
  56. TreeGridTick.compose = compose;
  57. /**
  58. * @private
  59. */
  60. function onInit() {
  61. var tick = this;
  62. if (!tick.treeGrid) {
  63. tick.treeGrid = new Additions(tick);
  64. }
  65. }
  66. /**
  67. * @private
  68. */
  69. function onTickHover(label) {
  70. label.addClass('highcharts-treegrid-node-active');
  71. if (!label.renderer.styledMode) {
  72. label.css({
  73. textDecoration: 'underline'
  74. });
  75. }
  76. }
  77. /**
  78. * @private
  79. */
  80. function onTickHoverExit(label, options) {
  81. var css = defined(options.style) ? options.style : {};
  82. label.removeClass('highcharts-treegrid-node-active');
  83. if (!label.renderer.styledMode) {
  84. label.css({ textDecoration: css.textDecoration });
  85. }
  86. }
  87. /**
  88. * @private
  89. */
  90. function renderLabelIcon(tick, params) {
  91. var treeGrid = tick.treeGrid, isNew = !treeGrid.labelIcon, renderer = params.renderer, labelBox = params.xy, options = params.options, width = options.width, height = options.height, iconCenter = {
  92. x: labelBox.x - (width / 2) - options.padding,
  93. y: labelBox.y - (height / 2)
  94. }, rotation = params.collapsed ? 90 : 180, shouldRender = params.show && isNumber(iconCenter.y);
  95. var icon = treeGrid.labelIcon;
  96. if (!icon) {
  97. treeGrid.labelIcon = icon = renderer
  98. .path(renderer.symbols[options.type](options.x, options.y, width, height))
  99. .addClass('highcharts-label-icon')
  100. .add(params.group);
  101. }
  102. // Set the new position, and show or hide
  103. if (!shouldRender) {
  104. icon.attr({ y: -9999 }); // #1338
  105. }
  106. // Presentational attributes
  107. if (!renderer.styledMode) {
  108. icon
  109. .attr({
  110. 'stroke-width': 1,
  111. 'fill': pick(params.color, '#666666')
  112. })
  113. .css({
  114. cursor: 'pointer',
  115. stroke: options.lineColor,
  116. strokeWidth: options.lineWidth
  117. });
  118. }
  119. // Update the icon positions
  120. icon[isNew ? 'attr' : 'animate']({
  121. translateX: iconCenter.x,
  122. translateY: iconCenter.y,
  123. rotation: rotation
  124. });
  125. }
  126. /**
  127. * @private
  128. */
  129. function wrapGetLabelPosition(proceed, x, y, label, horiz, labelOptions, tickmarkOffset, index, step) {
  130. var tick = this, lbOptions = pick(tick.options && tick.options.labels, labelOptions), pos = tick.pos, axis = tick.axis, options = axis.options, isTreeGrid = options.type === 'treegrid', result = proceed.apply(tick, [x, y, label, horiz, lbOptions, tickmarkOffset, index, step]);
  131. var symbolOptions, indentation, mapOfPosToGridNode, node, level;
  132. if (isTreeGrid) {
  133. symbolOptions = (lbOptions && isObject(lbOptions.symbol, true) ?
  134. lbOptions.symbol :
  135. {});
  136. indentation = (lbOptions && isNumber(lbOptions.indentation) ?
  137. lbOptions.indentation :
  138. 0);
  139. mapOfPosToGridNode = axis.treeGrid.mapOfPosToGridNode;
  140. node = mapOfPosToGridNode && mapOfPosToGridNode[pos];
  141. level = (node && node.depth) || 1;
  142. result.x += (
  143. // Add space for symbols
  144. ((symbolOptions.width) + (symbolOptions.padding * 2)) +
  145. // Apply indentation
  146. ((level - 1) * indentation));
  147. }
  148. return result;
  149. }
  150. /**
  151. * @private
  152. */
  153. function wrapRenderLabel(proceed) {
  154. var tick = this, pos = tick.pos, axis = tick.axis, label = tick.label, mapOfPosToGridNode = axis.treeGrid.mapOfPosToGridNode, options = axis.options, labelOptions = pick(tick.options && tick.options.labels, options && options.labels), symbolOptions = (labelOptions && isObject(labelOptions.symbol, true) ?
  155. labelOptions.symbol :
  156. {}), node = mapOfPosToGridNode && mapOfPosToGridNode[pos], level = node && node.depth, isTreeGrid = options.type === 'treegrid', shouldRender = axis.tickPositions.indexOf(pos) > -1, prefixClassName = 'highcharts-treegrid-node-', styledMode = axis.chart.styledMode;
  157. var collapsed, addClassName, removeClassName;
  158. if (isTreeGrid && node) {
  159. // Add class name for hierarchical styling.
  160. if (label &&
  161. label.element) {
  162. label.addClass(prefixClassName + 'level-' + level);
  163. }
  164. }
  165. proceed.apply(tick, Array.prototype.slice.call(arguments, 1));
  166. if (isTreeGrid &&
  167. label &&
  168. label.element &&
  169. node &&
  170. node.descendants &&
  171. node.descendants > 0) {
  172. collapsed = axis.treeGrid.isCollapsed(node);
  173. renderLabelIcon(tick, {
  174. color: !styledMode && label.styles && label.styles.color || '',
  175. collapsed: collapsed,
  176. group: label.parentGroup,
  177. options: symbolOptions,
  178. renderer: label.renderer,
  179. show: shouldRender,
  180. xy: label.xy
  181. });
  182. // Add class name for the node.
  183. addClassName = prefixClassName +
  184. (collapsed ? 'collapsed' : 'expanded');
  185. removeClassName = prefixClassName +
  186. (collapsed ? 'expanded' : 'collapsed');
  187. label
  188. .addClass(addClassName)
  189. .removeClass(removeClassName);
  190. if (!styledMode) {
  191. label.css({
  192. cursor: 'pointer'
  193. });
  194. }
  195. // Add events to both label text and icon
  196. [label, tick.treeGrid.labelIcon].forEach(function (object) {
  197. if (object && !object.attachedTreeGridEvents) {
  198. // On hover
  199. addEvent(object.element, 'mouseover', function () {
  200. onTickHover(label);
  201. });
  202. // On hover out
  203. addEvent(object.element, 'mouseout', function () {
  204. onTickHoverExit(label, labelOptions);
  205. });
  206. addEvent(object.element, 'click', function () {
  207. tick.treeGrid.toggleCollapse();
  208. });
  209. object.attachedTreeGridEvents = true;
  210. }
  211. });
  212. }
  213. }
  214. /* *
  215. *
  216. * Classes
  217. *
  218. * */
  219. /**
  220. * @private
  221. * @class
  222. */
  223. var Additions = /** @class */ (function () {
  224. /* *
  225. *
  226. * Constructors
  227. *
  228. * */
  229. /**
  230. * @private
  231. */
  232. function Additions(tick) {
  233. this.tick = tick;
  234. }
  235. /* *
  236. *
  237. * Functions
  238. *
  239. * */
  240. /**
  241. * Collapse the grid cell. Used when axis is of type treegrid.
  242. *
  243. * @see gantt/treegrid-axis/collapsed-dynamically/demo.js
  244. *
  245. * @private
  246. * @function Highcharts.Tick#collapse
  247. *
  248. * @param {boolean} [redraw=true]
  249. * Whether to redraw the chart or wait for an explicit call to
  250. * {@link Highcharts.Chart#redraw}
  251. */
  252. Additions.prototype.collapse = function (redraw) {
  253. var tick = this.tick, axis = tick.axis, brokenAxis = axis.brokenAxis;
  254. if (brokenAxis &&
  255. axis.treeGrid.mapOfPosToGridNode) {
  256. var pos = tick.pos, node = axis.treeGrid.mapOfPosToGridNode[pos], breaks = axis.treeGrid.collapse(node);
  257. brokenAxis.setBreaks(breaks, pick(redraw, true));
  258. }
  259. };
  260. /**
  261. * Expand the grid cell. Used when axis is of type treegrid.
  262. *
  263. * @see gantt/treegrid-axis/collapsed-dynamically/demo.js
  264. *
  265. * @private
  266. * @function Highcharts.Tick#expand
  267. *
  268. * @param {boolean} [redraw=true]
  269. * Whether to redraw the chart or wait for an explicit call to
  270. * {@link Highcharts.Chart#redraw}
  271. */
  272. Additions.prototype.expand = function (redraw) {
  273. var tick = this.tick, axis = tick.axis, brokenAxis = axis.brokenAxis;
  274. if (brokenAxis &&
  275. axis.treeGrid.mapOfPosToGridNode) {
  276. var pos = tick.pos, node = axis.treeGrid.mapOfPosToGridNode[pos], breaks = axis.treeGrid.expand(node);
  277. brokenAxis.setBreaks(breaks, pick(redraw, true));
  278. }
  279. };
  280. /**
  281. * Toggle the collapse/expand state of the grid cell. Used when axis is
  282. * of type treegrid.
  283. *
  284. * @see gantt/treegrid-axis/collapsed-dynamically/demo.js
  285. *
  286. * @private
  287. * @function Highcharts.Tick#toggleCollapse
  288. *
  289. * @param {boolean} [redraw=true]
  290. * Whether to redraw the chart or wait for an explicit call to
  291. * {@link Highcharts.Chart#redraw}
  292. */
  293. Additions.prototype.toggleCollapse = function (redraw) {
  294. var tick = this.tick, axis = tick.axis, brokenAxis = axis.brokenAxis;
  295. if (brokenAxis &&
  296. axis.treeGrid.mapOfPosToGridNode) {
  297. var pos = tick.pos, node = axis.treeGrid.mapOfPosToGridNode[pos], breaks = axis.treeGrid.toggleCollapse(node);
  298. brokenAxis.setBreaks(breaks, pick(redraw, true));
  299. }
  300. };
  301. return Additions;
  302. }());
  303. TreeGridTick.Additions = Additions;
  304. })(TreeGridTick || (TreeGridTick = {}));
  305. export default TreeGridTick;