treegrid.src.js 123 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670
  1. /**
  2. * @license Highcharts Gantt JS v8.1.2 (2020-06-16)
  3. *
  4. * Tree Grid
  5. *
  6. * (c) 2016-2019 Jon Arild Nygard
  7. *
  8. * License: www.highcharts.com/license
  9. */
  10. 'use strict';
  11. (function (factory) {
  12. if (typeof module === 'object' && module.exports) {
  13. factory['default'] = factory;
  14. module.exports = factory;
  15. } else if (typeof define === 'function' && define.amd) {
  16. define('highcharts/modules/treegrid', ['highcharts'], function (Highcharts) {
  17. factory(Highcharts);
  18. factory.Highcharts = Highcharts;
  19. return factory;
  20. });
  21. } else {
  22. factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined);
  23. }
  24. }(function (Highcharts) {
  25. var _modules = Highcharts ? Highcharts._modules : {};
  26. function _registerModule(obj, path, args, fn) {
  27. if (!obj.hasOwnProperty(path)) {
  28. obj[path] = fn.apply(null, args);
  29. }
  30. }
  31. _registerModule(_modules, 'parts-gantt/Tree.js', [_modules['parts/Utilities.js']], function (U) {
  32. /* *
  33. *
  34. * (c) 2016-2020 Highsoft AS
  35. *
  36. * Authors: Jon Arild Nygard
  37. *
  38. * License: www.highcharts.com/license
  39. *
  40. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  41. *
  42. * */
  43. /* eslint no-console: 0 */
  44. var extend = U.extend, isNumber = U.isNumber, pick = U.pick;
  45. /**
  46. * Creates an object map from parent id to childrens index.
  47. *
  48. * @private
  49. * @function Highcharts.Tree#getListOfParents
  50. *
  51. * @param {Array<*>} data
  52. * List of points set in options. `Array.parent` is parent id of point.
  53. *
  54. * @param {Array<string>} ids
  55. * List of all point ids.
  56. *
  57. * @return {Highcharts.Dictionary<Array<*>>}
  58. * Map from parent id to children index in data
  59. */
  60. var getListOfParents = function (data, ids) {
  61. var listOfParents = data.reduce(function (prev, curr) {
  62. var parent = pick(curr.parent, '');
  63. if (typeof prev[parent] === 'undefined') {
  64. prev[parent] = [];
  65. }
  66. prev[parent].push(curr);
  67. return prev;
  68. }, {}), parents = Object.keys(listOfParents);
  69. // If parent does not exist, hoist parent to root of tree.
  70. parents.forEach(function (parent, list) {
  71. var children = listOfParents[parent];
  72. if ((parent !== '') && (ids.indexOf(parent) === -1)) {
  73. children.forEach(function (child) {
  74. list[''].push(child);
  75. });
  76. delete list[parent];
  77. }
  78. });
  79. return listOfParents;
  80. };
  81. var getNode = function (id, parent, level, data, mapOfIdToChildren, options) {
  82. var descendants = 0, height = 0, after = options && options.after, before = options && options.before, node = {
  83. data: data,
  84. depth: level - 1,
  85. id: id,
  86. level: level,
  87. parent: parent
  88. }, start, end, children;
  89. // Allow custom logic before the children has been created.
  90. if (typeof before === 'function') {
  91. before(node, options);
  92. }
  93. // Call getNode recursively on the children. Calulate the height of the
  94. // node, and the number of descendants.
  95. children = ((mapOfIdToChildren[id] || [])).map(function (child) {
  96. var node = getNode(child.id, id, (level + 1), child, mapOfIdToChildren, options), childStart = child.start, childEnd = (child.milestone === true ?
  97. childStart :
  98. child.end);
  99. // Start should be the lowest child.start.
  100. start = ((!isNumber(start) || childStart < start) ?
  101. childStart :
  102. start);
  103. // End should be the largest child.end.
  104. // If child is milestone, then use start as end.
  105. end = ((!isNumber(end) || childEnd > end) ?
  106. childEnd :
  107. end);
  108. descendants = descendants + 1 + node.descendants;
  109. height = Math.max(node.height + 1, height);
  110. return node;
  111. });
  112. // Calculate start and end for point if it is not already explicitly set.
  113. if (data) {
  114. data.start = pick(data.start, start);
  115. data.end = pick(data.end, end);
  116. }
  117. extend(node, {
  118. children: children,
  119. descendants: descendants,
  120. height: height
  121. });
  122. // Allow custom logic after the children has been created.
  123. if (typeof after === 'function') {
  124. after(node, options);
  125. }
  126. return node;
  127. };
  128. var getTree = function (data, options) {
  129. var ids = data.map(function (d) {
  130. return d.id;
  131. }), mapOfIdToChildren = getListOfParents(data, ids);
  132. return getNode('', null, 1, null, mapOfIdToChildren, options);
  133. };
  134. var Tree = {
  135. getListOfParents: getListOfParents,
  136. getNode: getNode,
  137. getTree: getTree
  138. };
  139. return Tree;
  140. });
  141. _registerModule(_modules, 'parts-gantt/TreeGridTick.js', [_modules['parts/Utilities.js']], function (U) {
  142. /* *
  143. *
  144. * (c) 2016 Highsoft AS
  145. * Authors: Jon Arild Nygard
  146. *
  147. * License: www.highcharts.com/license
  148. *
  149. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  150. *
  151. * */
  152. var addEvent = U.addEvent, defined = U.defined, isObject = U.isObject, isNumber = U.isNumber, pick = U.pick, wrap = U.wrap;
  153. /**
  154. * @private
  155. */
  156. var TreeGridTick;
  157. (function (TreeGridTick) {
  158. /* *
  159. *
  160. * Interfaces
  161. *
  162. * */
  163. /* *
  164. *
  165. * Variables
  166. *
  167. * */
  168. var applied = false;
  169. /* *
  170. *
  171. * Functions
  172. *
  173. * */
  174. /**
  175. * @private
  176. */
  177. function compose(TickClass) {
  178. if (!applied) {
  179. addEvent(TickClass, 'init', onInit);
  180. wrap(TickClass.prototype, 'getLabelPosition', wrapGetLabelPosition);
  181. wrap(TickClass.prototype, 'renderLabel', wrapRenderLabel);
  182. // backwards compatibility
  183. TickClass.prototype.collapse = function (redraw) {
  184. this.treeGrid.collapse(redraw);
  185. };
  186. TickClass.prototype.expand = function (redraw) {
  187. this.treeGrid.expand(redraw);
  188. };
  189. TickClass.prototype.toggleCollapse = function (redraw) {
  190. this.treeGrid.toggleCollapse(redraw);
  191. };
  192. applied = true;
  193. }
  194. }
  195. TreeGridTick.compose = compose;
  196. /**
  197. * @private
  198. */
  199. function onInit() {
  200. var tick = this;
  201. if (!tick.treeGrid) {
  202. tick.treeGrid = new Additions(tick);
  203. }
  204. }
  205. /**
  206. * @private
  207. */
  208. function onTickHover(label) {
  209. label.addClass('highcharts-treegrid-node-active');
  210. if (!label.renderer.styledMode) {
  211. label.css({
  212. textDecoration: 'underline'
  213. });
  214. }
  215. }
  216. /**
  217. * @private
  218. */
  219. function onTickHoverExit(label, options) {
  220. var css = defined(options.style) ? options.style : {};
  221. label.removeClass('highcharts-treegrid-node-active');
  222. if (!label.renderer.styledMode) {
  223. label.css({ textDecoration: css.textDecoration });
  224. }
  225. }
  226. /**
  227. * @private
  228. */
  229. function renderLabelIcon(tick, params) {
  230. var treeGrid = tick.treeGrid, isNew = !treeGrid.labelIcon, renderer = params.renderer, labelBox = params.xy, options = params.options, width = options.width, height = options.height, iconCenter = {
  231. x: labelBox.x - (width / 2) - options.padding,
  232. y: labelBox.y - (height / 2)
  233. }, rotation = params.collapsed ? 90 : 180, shouldRender = params.show && isNumber(iconCenter.y);
  234. var icon = treeGrid.labelIcon;
  235. if (!icon) {
  236. treeGrid.labelIcon = icon = renderer
  237. .path(renderer.symbols[options.type](options.x, options.y, width, height))
  238. .addClass('highcharts-label-icon')
  239. .add(params.group);
  240. }
  241. // Set the new position, and show or hide
  242. if (!shouldRender) {
  243. icon.attr({ y: -9999 }); // #1338
  244. }
  245. // Presentational attributes
  246. if (!renderer.styledMode) {
  247. icon
  248. .attr({
  249. 'stroke-width': 1,
  250. 'fill': pick(params.color, '#666666')
  251. })
  252. .css({
  253. cursor: 'pointer',
  254. stroke: options.lineColor,
  255. strokeWidth: options.lineWidth
  256. });
  257. }
  258. // Update the icon positions
  259. icon[isNew ? 'attr' : 'animate']({
  260. translateX: iconCenter.x,
  261. translateY: iconCenter.y,
  262. rotation: rotation
  263. });
  264. }
  265. /**
  266. * @private
  267. */
  268. function wrapGetLabelPosition(proceed, x, y, label, horiz, labelOptions, tickmarkOffset, index, step) {
  269. 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]);
  270. var symbolOptions, indentation, mapOfPosToGridNode, node, level;
  271. if (isTreeGrid) {
  272. symbolOptions = (lbOptions && isObject(lbOptions.symbol, true) ?
  273. lbOptions.symbol :
  274. {});
  275. indentation = (lbOptions && isNumber(lbOptions.indentation) ?
  276. lbOptions.indentation :
  277. 0);
  278. mapOfPosToGridNode = axis.treeGrid.mapOfPosToGridNode;
  279. node = mapOfPosToGridNode && mapOfPosToGridNode[pos];
  280. level = (node && node.depth) || 1;
  281. result.x += (
  282. // Add space for symbols
  283. ((symbolOptions.width) + (symbolOptions.padding * 2)) +
  284. // Apply indentation
  285. ((level - 1) * indentation));
  286. }
  287. return result;
  288. }
  289. /**
  290. * @private
  291. */
  292. function wrapRenderLabel(proceed) {
  293. 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) ?
  294. labelOptions.symbol :
  295. {}), 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;
  296. var collapsed, addClassName, removeClassName;
  297. if (isTreeGrid && node) {
  298. // Add class name for hierarchical styling.
  299. if (label &&
  300. label.element) {
  301. label.addClass(prefixClassName + 'level-' + level);
  302. }
  303. }
  304. proceed.apply(tick, Array.prototype.slice.call(arguments, 1));
  305. if (isTreeGrid &&
  306. label &&
  307. label.element &&
  308. node &&
  309. node.descendants &&
  310. node.descendants > 0) {
  311. collapsed = axis.treeGrid.isCollapsed(node);
  312. renderLabelIcon(tick, {
  313. color: !styledMode && label.styles && label.styles.color || '',
  314. collapsed: collapsed,
  315. group: label.parentGroup,
  316. options: symbolOptions,
  317. renderer: label.renderer,
  318. show: shouldRender,
  319. xy: label.xy
  320. });
  321. // Add class name for the node.
  322. addClassName = prefixClassName +
  323. (collapsed ? 'collapsed' : 'expanded');
  324. removeClassName = prefixClassName +
  325. (collapsed ? 'expanded' : 'collapsed');
  326. label
  327. .addClass(addClassName)
  328. .removeClass(removeClassName);
  329. if (!styledMode) {
  330. label.css({
  331. cursor: 'pointer'
  332. });
  333. }
  334. // Add events to both label text and icon
  335. [label, tick.treeGrid.labelIcon].forEach(function (object) {
  336. if (object && !object.attachedTreeGridEvents) {
  337. // On hover
  338. addEvent(object.element, 'mouseover', function () {
  339. onTickHover(label);
  340. });
  341. // On hover out
  342. addEvent(object.element, 'mouseout', function () {
  343. onTickHoverExit(label, labelOptions);
  344. });
  345. addEvent(object.element, 'click', function () {
  346. tick.treeGrid.toggleCollapse();
  347. });
  348. object.attachedTreeGridEvents = true;
  349. }
  350. });
  351. }
  352. }
  353. /* *
  354. *
  355. * Classes
  356. *
  357. * */
  358. /**
  359. * @private
  360. * @class
  361. */
  362. var Additions = /** @class */ (function () {
  363. /* *
  364. *
  365. * Constructors
  366. *
  367. * */
  368. /**
  369. * @private
  370. */
  371. function Additions(tick) {
  372. this.tick = tick;
  373. }
  374. /* *
  375. *
  376. * Functions
  377. *
  378. * */
  379. /**
  380. * Collapse the grid cell. Used when axis is of type treegrid.
  381. *
  382. * @see gantt/treegrid-axis/collapsed-dynamically/demo.js
  383. *
  384. * @private
  385. * @function Highcharts.Tick#collapse
  386. *
  387. * @param {boolean} [redraw=true]
  388. * Whether to redraw the chart or wait for an explicit call to
  389. * {@link Highcharts.Chart#redraw}
  390. */
  391. Additions.prototype.collapse = function (redraw) {
  392. var tick = this.tick, axis = tick.axis, brokenAxis = axis.brokenAxis;
  393. if (brokenAxis &&
  394. axis.treeGrid.mapOfPosToGridNode) {
  395. var pos = tick.pos, node = axis.treeGrid.mapOfPosToGridNode[pos], breaks = axis.treeGrid.collapse(node);
  396. brokenAxis.setBreaks(breaks, pick(redraw, true));
  397. }
  398. };
  399. /**
  400. * Expand the grid cell. Used when axis is of type treegrid.
  401. *
  402. * @see gantt/treegrid-axis/collapsed-dynamically/demo.js
  403. *
  404. * @private
  405. * @function Highcharts.Tick#expand
  406. *
  407. * @param {boolean} [redraw=true]
  408. * Whether to redraw the chart or wait for an explicit call to
  409. * {@link Highcharts.Chart#redraw}
  410. */
  411. Additions.prototype.expand = function (redraw) {
  412. var tick = this.tick, axis = tick.axis, brokenAxis = axis.brokenAxis;
  413. if (brokenAxis &&
  414. axis.treeGrid.mapOfPosToGridNode) {
  415. var pos = tick.pos, node = axis.treeGrid.mapOfPosToGridNode[pos], breaks = axis.treeGrid.expand(node);
  416. brokenAxis.setBreaks(breaks, pick(redraw, true));
  417. }
  418. };
  419. /**
  420. * Toggle the collapse/expand state of the grid cell. Used when axis is
  421. * of type treegrid.
  422. *
  423. * @see gantt/treegrid-axis/collapsed-dynamically/demo.js
  424. *
  425. * @private
  426. * @function Highcharts.Tick#toggleCollapse
  427. *
  428. * @param {boolean} [redraw=true]
  429. * Whether to redraw the chart or wait for an explicit call to
  430. * {@link Highcharts.Chart#redraw}
  431. */
  432. Additions.prototype.toggleCollapse = function (redraw) {
  433. var tick = this.tick, axis = tick.axis, brokenAxis = axis.brokenAxis;
  434. if (brokenAxis &&
  435. axis.treeGrid.mapOfPosToGridNode) {
  436. var pos = tick.pos, node = axis.treeGrid.mapOfPosToGridNode[pos], breaks = axis.treeGrid.toggleCollapse(node);
  437. brokenAxis.setBreaks(breaks, pick(redraw, true));
  438. }
  439. };
  440. return Additions;
  441. }());
  442. TreeGridTick.Additions = Additions;
  443. })(TreeGridTick || (TreeGridTick = {}));
  444. return TreeGridTick;
  445. });
  446. _registerModule(_modules, 'mixins/tree-series.js', [_modules['parts/Color.js'], _modules['parts/Utilities.js']], function (Color, U) {
  447. /* *
  448. *
  449. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  450. *
  451. * */
  452. var extend = U.extend, isArray = U.isArray, isNumber = U.isNumber, isObject = U.isObject, merge = U.merge, pick = U.pick;
  453. var isBoolean = function (x) {
  454. return typeof x === 'boolean';
  455. }, isFn = function (x) {
  456. return typeof x === 'function';
  457. };
  458. /* eslint-disable valid-jsdoc */
  459. /**
  460. * @todo Combine buildTree and buildNode with setTreeValues
  461. * @todo Remove logic from Treemap and make it utilize this mixin.
  462. * @private
  463. */
  464. var setTreeValues = function setTreeValues(tree, options) {
  465. var before = options.before, idRoot = options.idRoot, mapIdToNode = options.mapIdToNode, nodeRoot = mapIdToNode[idRoot], levelIsConstant = (isBoolean(options.levelIsConstant) ?
  466. options.levelIsConstant :
  467. true), points = options.points, point = points[tree.i], optionsPoint = point && point.options || {}, childrenTotal = 0, children = [], value;
  468. extend(tree, {
  469. levelDynamic: tree.level - (levelIsConstant ? 0 : nodeRoot.level),
  470. name: pick(point && point.name, ''),
  471. visible: (idRoot === tree.id ||
  472. (isBoolean(options.visible) ? options.visible : false))
  473. });
  474. if (isFn(before)) {
  475. tree = before(tree, options);
  476. }
  477. // First give the children some values
  478. tree.children.forEach(function (child, i) {
  479. var newOptions = extend({}, options);
  480. extend(newOptions, {
  481. index: i,
  482. siblings: tree.children.length,
  483. visible: tree.visible
  484. });
  485. child = setTreeValues(child, newOptions);
  486. children.push(child);
  487. if (child.visible) {
  488. childrenTotal += child.val;
  489. }
  490. });
  491. tree.visible = childrenTotal > 0 || tree.visible;
  492. // Set the values
  493. value = pick(optionsPoint.value, childrenTotal);
  494. extend(tree, {
  495. children: children,
  496. childrenTotal: childrenTotal,
  497. isLeaf: tree.visible && !childrenTotal,
  498. val: value
  499. });
  500. return tree;
  501. };
  502. /**
  503. * @private
  504. */
  505. var getColor = function getColor(node, options) {
  506. var index = options.index, mapOptionsToLevel = options.mapOptionsToLevel, parentColor = options.parentColor, parentColorIndex = options.parentColorIndex, series = options.series, colors = options.colors, siblings = options.siblings, points = series.points, getColorByPoint, chartOptionsChart = series.chart.options.chart, point, level, colorByPoint, colorIndexByPoint, color, colorIndex;
  507. /**
  508. * @private
  509. */
  510. function variation(color) {
  511. var colorVariation = level && level.colorVariation;
  512. if (colorVariation) {
  513. if (colorVariation.key === 'brightness') {
  514. return Color.parse(color).brighten(colorVariation.to * (index / siblings)).get();
  515. }
  516. }
  517. return color;
  518. }
  519. if (node) {
  520. point = points[node.i];
  521. level = mapOptionsToLevel[node.level] || {};
  522. getColorByPoint = point && level.colorByPoint;
  523. if (getColorByPoint) {
  524. colorIndexByPoint = point.index % (colors ?
  525. colors.length :
  526. chartOptionsChart.colorCount);
  527. colorByPoint = colors && colors[colorIndexByPoint];
  528. }
  529. // Select either point color, level color or inherited color.
  530. if (!series.chart.styledMode) {
  531. color = pick(point && point.options.color, level && level.color, colorByPoint, parentColor && variation(parentColor), series.color);
  532. }
  533. colorIndex = pick(point && point.options.colorIndex, level && level.colorIndex, colorIndexByPoint, parentColorIndex, options.colorIndex);
  534. }
  535. return {
  536. color: color,
  537. colorIndex: colorIndex
  538. };
  539. };
  540. /**
  541. * Creates a map from level number to its given options.
  542. *
  543. * @private
  544. * @function getLevelOptions
  545. * @param {object} params
  546. * Object containing parameters.
  547. * - `defaults` Object containing default options. The default options
  548. * are merged with the userOptions to get the final options for a
  549. * specific level.
  550. * - `from` The lowest level number.
  551. * - `levels` User options from series.levels.
  552. * - `to` The highest level number.
  553. * @return {Highcharts.Dictionary<object>|null}
  554. * Returns a map from level number to its given options.
  555. */
  556. var getLevelOptions = function getLevelOptions(params) {
  557. var result = null, defaults, converted, i, from, to, levels;
  558. if (isObject(params)) {
  559. result = {};
  560. from = isNumber(params.from) ? params.from : 1;
  561. levels = params.levels;
  562. converted = {};
  563. defaults = isObject(params.defaults) ? params.defaults : {};
  564. if (isArray(levels)) {
  565. converted = levels.reduce(function (obj, item) {
  566. var level, levelIsConstant, options;
  567. if (isObject(item) && isNumber(item.level)) {
  568. options = merge({}, item);
  569. levelIsConstant = (isBoolean(options.levelIsConstant) ?
  570. options.levelIsConstant :
  571. defaults.levelIsConstant);
  572. // Delete redundant properties.
  573. delete options.levelIsConstant;
  574. delete options.level;
  575. // Calculate which level these options apply to.
  576. level = item.level + (levelIsConstant ? 0 : from - 1);
  577. if (isObject(obj[level])) {
  578. extend(obj[level], options);
  579. }
  580. else {
  581. obj[level] = options;
  582. }
  583. }
  584. return obj;
  585. }, {});
  586. }
  587. to = isNumber(params.to) ? params.to : 1;
  588. for (i = 0; i <= to; i++) {
  589. result[i] = merge({}, defaults, isObject(converted[i]) ? converted[i] : {});
  590. }
  591. }
  592. return result;
  593. };
  594. /**
  595. * Update the rootId property on the series. Also makes sure that it is
  596. * accessible to exporting.
  597. *
  598. * @private
  599. * @function updateRootId
  600. *
  601. * @param {object} series
  602. * The series to operate on.
  603. *
  604. * @return {string}
  605. * Returns the resulting rootId after update.
  606. */
  607. var updateRootId = function (series) {
  608. var rootId, options;
  609. if (isObject(series)) {
  610. // Get the series options.
  611. options = isObject(series.options) ? series.options : {};
  612. // Calculate the rootId.
  613. rootId = pick(series.rootNode, options.rootId, '');
  614. // Set rootId on series.userOptions to pick it up in exporting.
  615. if (isObject(series.userOptions)) {
  616. series.userOptions.rootId = rootId;
  617. }
  618. // Set rootId on series to pick it up on next update.
  619. series.rootNode = rootId;
  620. }
  621. return rootId;
  622. };
  623. var result = {
  624. getColor: getColor,
  625. getLevelOptions: getLevelOptions,
  626. setTreeValues: setTreeValues,
  627. updateRootId: updateRootId
  628. };
  629. return result;
  630. });
  631. _registerModule(_modules, 'parts-gantt/GridAxis.js', [_modules['parts/Axis.js'], _modules['parts/Globals.js'], _modules['parts/Options.js'], _modules['parts/Tick.js'], _modules['parts/Utilities.js']], function (Axis, H, O, Tick, U) {
  632. /* *
  633. *
  634. * (c) 2016 Highsoft AS
  635. * Authors: Lars A. V. Cabrera
  636. *
  637. * License: www.highcharts.com/license
  638. *
  639. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  640. *
  641. * */
  642. var dateFormat = O.dateFormat;
  643. var addEvent = U.addEvent, defined = U.defined, erase = U.erase, find = U.find, isArray = U.isArray, isNumber = U.isNumber, merge = U.merge, pick = U.pick, timeUnits = U.timeUnits, wrap = U.wrap;
  644. var argsToArray = function (args) {
  645. return Array.prototype.slice.call(args, 1);
  646. }, isObject = function (x) {
  647. // Always use strict mode
  648. return U.isObject(x, true);
  649. }, Chart = H.Chart;
  650. var applyGridOptions = function applyGridOptions(axis) {
  651. var options = axis.options;
  652. // Center-align by default
  653. if (!options.labels) {
  654. options.labels = {};
  655. }
  656. options.labels.align = pick(options.labels.align, 'center');
  657. // @todo: Check against tickLabelPlacement between/on etc
  658. /* Prevents adding the last tick label if the axis is not a category
  659. axis.
  660. Since numeric labels are normally placed at starts and ends of a
  661. range of value, and this module makes the label point at the value,
  662. an "extra" label would appear. */
  663. if (!axis.categories) {
  664. options.showLastLabel = false;
  665. }
  666. // Prevents rotation of labels when squished, as rotating them would not
  667. // help.
  668. axis.labelRotation = 0;
  669. options.labels.rotation = 0;
  670. };
  671. /**
  672. * Set grid options for the axis labels. Requires Highcharts Gantt.
  673. *
  674. * @since 6.2.0
  675. * @product gantt
  676. * @apioption xAxis.grid
  677. */
  678. /**
  679. * Enable grid on the axis labels. Defaults to true for Gantt charts.
  680. *
  681. * @type {boolean}
  682. * @default true
  683. * @since 6.2.0
  684. * @product gantt
  685. * @apioption xAxis.grid.enabled
  686. */
  687. /**
  688. * Set specific options for each column (or row for horizontal axes) in the
  689. * grid. Each extra column/row is its own axis, and the axis options can be set
  690. * here.
  691. *
  692. * @sample gantt/demo/left-axis-table
  693. * Left axis as a table
  694. *
  695. * @type {Array<Highcharts.XAxisOptions>}
  696. * @apioption xAxis.grid.columns
  697. */
  698. /**
  699. * Set border color for the label grid lines.
  700. *
  701. * @type {Highcharts.ColorString}
  702. * @apioption xAxis.grid.borderColor
  703. */
  704. /**
  705. * Set border width of the label grid lines.
  706. *
  707. * @type {number}
  708. * @default 1
  709. * @apioption xAxis.grid.borderWidth
  710. */
  711. /**
  712. * Set cell height for grid axis labels. By default this is calculated from font
  713. * size. This option only applies to horizontal axes.
  714. *
  715. * @sample gantt/grid-axis/cellheight
  716. * Gant chart with custom cell height
  717. * @type {number}
  718. * @apioption xAxis.grid.cellHeight
  719. */
  720. ''; // detach doclets above
  721. /**
  722. * Get the largest label width and height.
  723. *
  724. * @private
  725. * @function Highcharts.Axis#getMaxLabelDimensions
  726. *
  727. * @param {Highcharts.Dictionary<Highcharts.Tick>} ticks
  728. * All the ticks on one axis.
  729. *
  730. * @param {Array<number|string>} tickPositions
  731. * All the tick positions on one axis.
  732. *
  733. * @return {Highcharts.SizeObject}
  734. * Object containing the properties height and width.
  735. *
  736. * @todo Move this to the generic axis implementation, as it is used there.
  737. */
  738. Axis.prototype.getMaxLabelDimensions = function (ticks, tickPositions) {
  739. var dimensions = {
  740. width: 0,
  741. height: 0
  742. };
  743. tickPositions.forEach(function (pos) {
  744. var tick = ticks[pos], tickHeight = 0, tickWidth = 0, label;
  745. if (isObject(tick)) {
  746. label = isObject(tick.label) ? tick.label : {};
  747. // Find width and height of tick
  748. tickHeight = label.getBBox ? label.getBBox().height : 0;
  749. if (label.textStr && !isNumber(label.textPxLength)) {
  750. label.textPxLength = label.getBBox().width;
  751. }
  752. tickWidth = isNumber(label.textPxLength) ?
  753. // Math.round ensures crisp lines
  754. Math.round(label.textPxLength) :
  755. 0;
  756. // Update the result if width and/or height are larger
  757. dimensions.height = Math.max(tickHeight, dimensions.height);
  758. dimensions.width = Math.max(tickWidth, dimensions.width);
  759. }
  760. });
  761. return dimensions;
  762. };
  763. // Adds week date format
  764. H.dateFormats.W = function (timestamp) {
  765. var d = new this.Date(timestamp);
  766. var firstDay = (this.get('Day', d) + 6) % 7;
  767. var thursday = new this.Date(d.valueOf());
  768. this.set('Date', thursday, this.get('Date', d) - firstDay + 3);
  769. var firstThursday = new this.Date(this.get('FullYear', thursday), 0, 1);
  770. if (this.get('Day', firstThursday) !== 4) {
  771. this.set('Month', d, 0);
  772. this.set('Date', d, 1 + (11 - this.get('Day', firstThursday)) % 7);
  773. }
  774. return (1 +
  775. Math.floor((thursday.valueOf() - firstThursday.valueOf()) / 604800000)).toString();
  776. };
  777. // First letter of the day of the week, e.g. 'M' for 'Monday'.
  778. H.dateFormats.E = function (timestamp) {
  779. return dateFormat('%a', timestamp, true).charAt(0);
  780. };
  781. /* eslint-disable no-invalid-this */
  782. addEvent(Chart, 'afterSetChartSize', function () {
  783. this.axes.forEach(function (axis) {
  784. (axis.grid && axis.grid.columns || []).forEach(function (column) {
  785. column.setAxisSize();
  786. column.setAxisTranslation();
  787. });
  788. });
  789. });
  790. // Center tick labels in cells.
  791. addEvent(Tick, 'afterGetLabelPosition', function (e) {
  792. var tick = this, label = tick.label, axis = tick.axis, reversed = axis.reversed, chart = axis.chart, options = axis.options, gridOptions = options.grid || {}, labelOpts = axis.options.labels, align = labelOpts.align,
  793. // verticalAlign is currently not supported for axis.labels.
  794. verticalAlign = 'middle', // labelOpts.verticalAlign,
  795. side = GridAxis.Side[axis.side], tickmarkOffset = e.tickmarkOffset, tickPositions = axis.tickPositions, tickPos = tick.pos - tickmarkOffset, nextTickPos = (isNumber(tickPositions[e.index + 1]) ?
  796. tickPositions[e.index + 1] - tickmarkOffset :
  797. axis.max + tickmarkOffset), tickSize = axis.tickSize('tick'), tickWidth = tickSize ? tickSize[0] : 0, crispCorr = tickSize ? tickSize[1] / 2 : 0, labelHeight, lblMetrics, lines, bottom, top, left, right;
  798. // Only center tick labels in grid axes
  799. if (gridOptions.enabled === true) {
  800. // Calculate top and bottom positions of the cell.
  801. if (side === 'top') {
  802. bottom = axis.top + axis.offset;
  803. top = bottom - tickWidth;
  804. }
  805. else if (side === 'bottom') {
  806. top = chart.chartHeight - axis.bottom + axis.offset;
  807. bottom = top + tickWidth;
  808. }
  809. else {
  810. bottom = axis.top + axis.len - axis.translate(reversed ? nextTickPos : tickPos);
  811. top = axis.top + axis.len - axis.translate(reversed ? tickPos : nextTickPos);
  812. }
  813. // Calculate left and right positions of the cell.
  814. if (side === 'right') {
  815. left = chart.chartWidth - axis.right + axis.offset;
  816. right = left + tickWidth;
  817. }
  818. else if (side === 'left') {
  819. right = axis.left + axis.offset;
  820. left = right - tickWidth;
  821. }
  822. else {
  823. left = Math.round(axis.left + axis.translate(reversed ? nextTickPos : tickPos)) - crispCorr;
  824. right = Math.round(axis.left + axis.translate(reversed ? tickPos : nextTickPos)) - crispCorr;
  825. }
  826. tick.slotWidth = right - left;
  827. // Calculate the positioning of the label based on
  828. // alignment.
  829. e.pos.x = (align === 'left' ?
  830. left :
  831. align === 'right' ?
  832. right :
  833. left + ((right - left) / 2) // default to center
  834. );
  835. e.pos.y = (verticalAlign === 'top' ?
  836. top :
  837. verticalAlign === 'bottom' ?
  838. bottom :
  839. top + ((bottom - top) / 2) // default to middle
  840. );
  841. lblMetrics = chart.renderer.fontMetrics(labelOpts.style.fontSize, label.element);
  842. labelHeight = label.getBBox().height;
  843. // Adjustment to y position to align the label correctly.
  844. // Would be better to have a setter or similar for this.
  845. if (!labelOpts.useHTML) {
  846. lines = Math.round(labelHeight / lblMetrics.h);
  847. e.pos.y += (
  848. // Center the label
  849. // TODO: why does this actually center the label?
  850. ((lblMetrics.b - (lblMetrics.h - lblMetrics.f)) / 2) +
  851. // Adjust for height of additional lines.
  852. -(((lines - 1) * lblMetrics.h) / 2));
  853. }
  854. else {
  855. e.pos.y += (
  856. // Readjust yCorr in htmlUpdateTransform
  857. lblMetrics.b +
  858. // Adjust for height of html label
  859. -(labelHeight / 2));
  860. }
  861. e.pos.x += (axis.horiz && labelOpts.x || 0);
  862. }
  863. });
  864. /* eslint-enable no-invalid-this */
  865. /**
  866. * Additions for grid axes.
  867. * @private
  868. * @class
  869. */
  870. var GridAxisAdditions = /** @class */ (function () {
  871. /* *
  872. *
  873. * Constructors
  874. *
  875. * */
  876. function GridAxisAdditions(axis) {
  877. this.axis = axis;
  878. }
  879. /* *
  880. *
  881. * Functions
  882. *
  883. * */
  884. /**
  885. * Checks if an axis is the outer axis in its dimension. Since
  886. * axes are placed outwards in order, the axis with the highest
  887. * index is the outermost axis.
  888. *
  889. * Example: If there are multiple x-axes at the top of the chart,
  890. * this function returns true if the axis supplied is the last
  891. * of the x-axes.
  892. *
  893. * @private
  894. *
  895. * @return {boolean}
  896. * True if the axis is the outermost axis in its dimension; false if
  897. * not.
  898. */
  899. GridAxisAdditions.prototype.isOuterAxis = function () {
  900. var axis = this.axis;
  901. var chart = axis.chart;
  902. var columnIndex = axis.grid.columnIndex;
  903. var columns = (axis.linkedParent && axis.linkedParent.grid.columns ||
  904. axis.grid.columns);
  905. var parentAxis = columnIndex ? axis.linkedParent : axis;
  906. var thisIndex = -1, lastIndex = 0;
  907. chart[axis.coll].forEach(function (otherAxis, index) {
  908. if (otherAxis.side === axis.side && !otherAxis.options.isInternal) {
  909. lastIndex = index;
  910. if (otherAxis === parentAxis) {
  911. // Get the index of the axis in question
  912. thisIndex = index;
  913. }
  914. }
  915. });
  916. return (lastIndex === thisIndex &&
  917. (isNumber(columnIndex) ? columns.length === columnIndex : true));
  918. };
  919. return GridAxisAdditions;
  920. }());
  921. /**
  922. * Axis with grid support.
  923. * @private
  924. * @class
  925. */
  926. var GridAxis = /** @class */ (function () {
  927. function GridAxis() {
  928. }
  929. /* *
  930. *
  931. * Static Functions
  932. *
  933. * */
  934. /* eslint-disable valid-jsdoc */
  935. /**
  936. * Extends axis class with grid support.
  937. * @private
  938. */
  939. GridAxis.compose = function (AxisClass) {
  940. Axis.keepProps.push('grid');
  941. wrap(AxisClass.prototype, 'unsquish', GridAxis.wrapUnsquish);
  942. // Add event handlers
  943. addEvent(AxisClass, 'init', GridAxis.onInit);
  944. addEvent(AxisClass, 'afterGetOffset', GridAxis.onAfterGetOffset);
  945. addEvent(AxisClass, 'afterGetTitlePosition', GridAxis.onAfterGetTitlePosition);
  946. addEvent(AxisClass, 'afterInit', GridAxis.onAfterInit);
  947. addEvent(AxisClass, 'afterRender', GridAxis.onAfterRender);
  948. addEvent(AxisClass, 'afterSetAxisTranslation', GridAxis.onAfterSetAxisTranslation);
  949. addEvent(AxisClass, 'afterSetOptions', GridAxis.onAfterSetOptions);
  950. addEvent(AxisClass, 'afterSetOptions', GridAxis.onAfterSetOptions2);
  951. addEvent(AxisClass, 'afterSetScale', GridAxis.onAfterSetScale);
  952. addEvent(AxisClass, 'afterTickSize', GridAxis.onAfterTickSize);
  953. addEvent(AxisClass, 'trimTicks', GridAxis.onTrimTicks);
  954. addEvent(AxisClass, 'destroy', GridAxis.onDestroy);
  955. };
  956. /**
  957. * Handle columns and getOffset.
  958. * @private
  959. */
  960. GridAxis.onAfterGetOffset = function () {
  961. var grid = this.grid;
  962. (grid && grid.columns || []).forEach(function (column) {
  963. column.getOffset();
  964. });
  965. };
  966. /**
  967. * @private
  968. */
  969. GridAxis.onAfterGetTitlePosition = function (e) {
  970. var axis = this;
  971. var options = axis.options;
  972. var gridOptions = options.grid || {};
  973. if (gridOptions.enabled === true) {
  974. // compute anchor points for each of the title align options
  975. var title = axis.axisTitle, axisHeight = axis.height, horiz = axis.horiz, axisLeft = axis.left, offset = axis.offset, opposite = axis.opposite, _a = axis.options.title, axisTitleOptions = _a === void 0 ? {} : _a, axisTop = axis.top, axisWidth = axis.width;
  976. var tickSize = axis.tickSize();
  977. var titleWidth = title && title.getBBox().width;
  978. var xOption = axisTitleOptions.x || 0;
  979. var yOption = axisTitleOptions.y || 0;
  980. var titleMargin = pick(axisTitleOptions.margin, horiz ? 5 : 10);
  981. var titleFontSize = axis.chart.renderer.fontMetrics(axisTitleOptions.style &&
  982. axisTitleOptions.style.fontSize, title).f;
  983. var crispCorr = tickSize ? tickSize[0] / 2 : 0;
  984. // TODO account for alignment
  985. // the position in the perpendicular direction of the axis
  986. var offAxis = ((horiz ? axisTop + axisHeight : axisLeft) +
  987. (horiz ? 1 : -1) * // horizontal axis reverses the margin
  988. (opposite ? -1 : 1) * // so does opposite axes
  989. crispCorr +
  990. (axis.side === GridAxis.Side.bottom ? titleFontSize : 0));
  991. e.titlePosition.x = horiz ?
  992. axisLeft - titleWidth / 2 - titleMargin + xOption :
  993. offAxis + (opposite ? axisWidth : 0) + offset + xOption;
  994. e.titlePosition.y = horiz ?
  995. (offAxis -
  996. (opposite ? axisHeight : 0) +
  997. (opposite ? titleFontSize : -titleFontSize) / 2 +
  998. offset +
  999. yOption) :
  1000. axisTop - titleMargin + yOption;
  1001. }
  1002. };
  1003. /**
  1004. * @private
  1005. */
  1006. GridAxis.onAfterInit = function () {
  1007. var axis = this;
  1008. var chart = axis.chart, _a = axis.options.grid, gridOptions = _a === void 0 ? {} : _a, userOptions = axis.userOptions;
  1009. if (gridOptions.enabled) {
  1010. applyGridOptions(axis);
  1011. /* eslint-disable no-invalid-this */
  1012. // TODO: wrap the axis instead
  1013. wrap(axis, 'labelFormatter', function (proceed) {
  1014. var _a = this, axis = _a.axis, value = _a.value;
  1015. var tickPos = axis.tickPositions;
  1016. var series = (axis.isLinked ?
  1017. axis.linkedParent :
  1018. axis).series[0];
  1019. var isFirst = value === tickPos[0];
  1020. var isLast = value === tickPos[tickPos.length - 1];
  1021. var point = series && find(series.options.data, function (p) {
  1022. return p[axis.isXAxis ? 'x' : 'y'] === value;
  1023. });
  1024. // Make additional properties available for the
  1025. // formatter
  1026. this.isFirst = isFirst;
  1027. this.isLast = isLast;
  1028. this.point = point;
  1029. // Call original labelFormatter
  1030. return proceed.call(this);
  1031. });
  1032. /* eslint-enable no-invalid-this */
  1033. }
  1034. if (gridOptions.columns) {
  1035. var columns = axis.grid.columns = [], columnIndex = axis.grid.columnIndex = 0;
  1036. // Handle columns, each column is a grid axis
  1037. while (++columnIndex < gridOptions.columns.length) {
  1038. var columnOptions = merge(userOptions, gridOptions.columns[gridOptions.columns.length - columnIndex - 1], {
  1039. linkedTo: 0,
  1040. // Force to behave like category axis
  1041. type: 'category'
  1042. });
  1043. delete columnOptions.grid.columns; // Prevent recursion
  1044. var column = new Axis(axis.chart, columnOptions);
  1045. column.grid.isColumn = true;
  1046. column.grid.columnIndex = columnIndex;
  1047. // Remove column axis from chart axes array, and place it
  1048. // in the columns array.
  1049. erase(chart.axes, column);
  1050. erase(chart[axis.coll], column);
  1051. columns.push(column);
  1052. }
  1053. }
  1054. };
  1055. /**
  1056. * Draw an extra line on the far side of the outermost axis,
  1057. * creating floor/roof/wall of a grid. And some padding.
  1058. * ```
  1059. * Make this:
  1060. * (axis.min) __________________________ (axis.max)
  1061. * | | | | |
  1062. * Into this:
  1063. * (axis.min) __________________________ (axis.max)
  1064. * ___|____|____|____|____|__
  1065. * ```
  1066. * @private
  1067. */
  1068. GridAxis.onAfterRender = function () {
  1069. var axis = this;
  1070. var grid = axis.grid;
  1071. var options = axis.options;
  1072. var renderer = axis.chart.renderer;
  1073. var gridOptions = options.grid || {};
  1074. var yStartIndex, yEndIndex, xStartIndex, xEndIndex;
  1075. if (gridOptions.enabled === true) {
  1076. // @todo acutual label padding (top, bottom, left, right)
  1077. axis.maxLabelDimensions = axis.getMaxLabelDimensions(axis.ticks, axis.tickPositions);
  1078. // Remove right wall before rendering if updating
  1079. if (axis.rightWall) {
  1080. axis.rightWall.destroy();
  1081. }
  1082. /*
  1083. Draw an extra axis line on outer axes
  1084. >
  1085. Make this: |______|______|______|___
  1086. > _________________________
  1087. Into this: |______|______|______|__|
  1088. */
  1089. if (axis.grid && axis.grid.isOuterAxis() && axis.axisLine) {
  1090. var lineWidth = options.lineWidth;
  1091. if (lineWidth) {
  1092. var linePath = axis.getLinePath(lineWidth);
  1093. var startPoint = linePath[0];
  1094. var endPoint = linePath[1];
  1095. // Negate distance if top or left axis
  1096. // Subtract 1px to draw the line at the end of the tick
  1097. var tickLength = (axis.tickSize('tick') || [1])[0];
  1098. var distance = (tickLength - 1) * ((axis.side === GridAxis.Side.top ||
  1099. axis.side === GridAxis.Side.left) ? -1 : 1);
  1100. // If axis is horizontal, reposition line path vertically
  1101. if (startPoint[0] === 'M' && endPoint[0] === 'L') {
  1102. if (axis.horiz) {
  1103. startPoint[2] += distance;
  1104. endPoint[2] += distance;
  1105. }
  1106. else {
  1107. // If axis is vertical, reposition line path
  1108. // horizontally
  1109. startPoint[1] += distance;
  1110. endPoint[1] += distance;
  1111. }
  1112. }
  1113. if (!axis.grid.axisLineExtra) {
  1114. axis.grid.axisLineExtra = renderer
  1115. .path(linePath)
  1116. .attr({
  1117. zIndex: 7
  1118. })
  1119. .addClass('highcharts-axis-line')
  1120. .add(axis.axisGroup);
  1121. if (!renderer.styledMode) {
  1122. axis.grid.axisLineExtra.attr({
  1123. stroke: options.lineColor,
  1124. 'stroke-width': lineWidth
  1125. });
  1126. }
  1127. }
  1128. else {
  1129. axis.grid.axisLineExtra.animate({
  1130. d: linePath
  1131. });
  1132. }
  1133. // show or hide the line depending on
  1134. // options.showEmpty
  1135. axis.axisLine[axis.showAxis ? 'show' : 'hide'](true);
  1136. }
  1137. }
  1138. (grid && grid.columns || []).forEach(function (column) {
  1139. column.render();
  1140. });
  1141. }
  1142. };
  1143. /**
  1144. * @private
  1145. */
  1146. GridAxis.onAfterSetAxisTranslation = function () {
  1147. var axis = this;
  1148. var tickInfo = axis.tickPositions && axis.tickPositions.info;
  1149. var options = axis.options;
  1150. var gridOptions = options.grid || {};
  1151. var userLabels = axis.userOptions.labels || {};
  1152. if (axis.horiz) {
  1153. if (gridOptions.enabled === true) {
  1154. axis.series.forEach(function (series) {
  1155. series.options.pointRange = 0;
  1156. });
  1157. }
  1158. // Lower level time ticks, like hours or minutes, represent
  1159. // points in time and not ranges. These should be aligned
  1160. // left in the grid cell by default. The same applies to
  1161. // years of higher order.
  1162. if (tickInfo &&
  1163. options.dateTimeLabelFormats &&
  1164. options.labels &&
  1165. !defined(userLabels.align) &&
  1166. (options.dateTimeLabelFormats[tickInfo.unitName].range === false ||
  1167. tickInfo.count > 1 // years
  1168. )) {
  1169. options.labels.align = 'left';
  1170. if (!defined(userLabels.x)) {
  1171. options.labels.x = 3;
  1172. }
  1173. }
  1174. }
  1175. };
  1176. /**
  1177. * Creates a left and right wall on horizontal axes:
  1178. * - Places leftmost tick at the start of the axis, to create a left
  1179. * wall
  1180. * - Ensures that the rightmost tick is at the end of the axis, to
  1181. * create a right wall.
  1182. * @private
  1183. */
  1184. GridAxis.onAfterSetOptions = function (e) {
  1185. var options = this.options, userOptions = e.userOptions, gridAxisOptions, gridOptions = ((options && isObject(options.grid)) ? options.grid : {});
  1186. if (gridOptions.enabled === true) {
  1187. // Merge the user options into default grid axis options so
  1188. // that when a user option is set, it takes presedence.
  1189. gridAxisOptions = merge(true, {
  1190. className: ('highcharts-grid-axis ' + (userOptions.className || '')),
  1191. dateTimeLabelFormats: {
  1192. hour: {
  1193. list: ['%H:%M', '%H']
  1194. },
  1195. day: {
  1196. list: ['%A, %e. %B', '%a, %e. %b', '%E']
  1197. },
  1198. week: {
  1199. list: ['Week %W', 'W%W']
  1200. },
  1201. month: {
  1202. list: ['%B', '%b', '%o']
  1203. }
  1204. },
  1205. grid: {
  1206. borderWidth: 1
  1207. },
  1208. labels: {
  1209. padding: 2,
  1210. style: {
  1211. fontSize: '13px'
  1212. }
  1213. },
  1214. margin: 0,
  1215. title: {
  1216. text: null,
  1217. reserveSpace: false,
  1218. rotation: 0
  1219. },
  1220. // In a grid axis, only allow one unit of certain types,
  1221. // for example we shouln't have one grid cell spanning
  1222. // two days.
  1223. units: [[
  1224. 'millisecond',
  1225. [1, 10, 100]
  1226. ], [
  1227. 'second',
  1228. [1, 10]
  1229. ], [
  1230. 'minute',
  1231. [1, 5, 15]
  1232. ], [
  1233. 'hour',
  1234. [1, 6]
  1235. ], [
  1236. 'day',
  1237. [1]
  1238. ], [
  1239. 'week',
  1240. [1]
  1241. ], [
  1242. 'month',
  1243. [1]
  1244. ], [
  1245. 'year',
  1246. null
  1247. ]]
  1248. }, userOptions);
  1249. // X-axis specific options
  1250. if (this.coll === 'xAxis') {
  1251. // For linked axes, tickPixelInterval is used only if
  1252. // the tickPositioner below doesn't run or returns
  1253. // undefined (like multiple years)
  1254. if (defined(userOptions.linkedTo) &&
  1255. !defined(userOptions.tickPixelInterval)) {
  1256. gridAxisOptions.tickPixelInterval = 350;
  1257. }
  1258. // For the secondary grid axis, use the primary axis'
  1259. // tick intervals and return ticks one level higher.
  1260. if (
  1261. // Check for tick pixel interval in options
  1262. !defined(userOptions.tickPixelInterval) &&
  1263. // Only for linked axes
  1264. defined(userOptions.linkedTo) &&
  1265. !defined(userOptions.tickPositioner) &&
  1266. !defined(userOptions.tickInterval)) {
  1267. gridAxisOptions.tickPositioner = function (min, max) {
  1268. var parentInfo = (this.linkedParent &&
  1269. this.linkedParent.tickPositions &&
  1270. this.linkedParent.tickPositions.info);
  1271. if (parentInfo) {
  1272. var unitIdx, count, unitName, i, units = gridAxisOptions.units, unitRange;
  1273. for (i = 0; i < units.length; i++) {
  1274. if (units[i][0] ===
  1275. parentInfo.unitName) {
  1276. unitIdx = i;
  1277. break;
  1278. }
  1279. }
  1280. // Get the first allowed count on the next
  1281. // unit.
  1282. if (units[unitIdx + 1]) {
  1283. unitName = units[unitIdx + 1][0];
  1284. count =
  1285. (units[unitIdx + 1][1] || [1])[0];
  1286. // In case the base X axis shows years, make
  1287. // the secondary axis show ten times the
  1288. // years (#11427)
  1289. }
  1290. else if (parentInfo.unitName === 'year') {
  1291. unitName = 'year';
  1292. count = parentInfo.count * 10;
  1293. }
  1294. unitRange = timeUnits[unitName];
  1295. this.tickInterval = unitRange * count;
  1296. return this.getTimeTicks({
  1297. unitRange: unitRange,
  1298. count: count,
  1299. unitName: unitName
  1300. }, min, max, this.options.startOfWeek);
  1301. }
  1302. };
  1303. }
  1304. }
  1305. // Now merge the combined options into the axis options
  1306. merge(true, this.options, gridAxisOptions);
  1307. if (this.horiz) {
  1308. /* _________________________
  1309. Make this: ___|_____|_____|_____|__|
  1310. ^ ^
  1311. _________________________
  1312. Into this: |_____|_____|_____|_____|
  1313. ^ ^ */
  1314. options.minPadding = pick(userOptions.minPadding, 0);
  1315. options.maxPadding = pick(userOptions.maxPadding, 0);
  1316. }
  1317. // If borderWidth is set, then use its value for tick and
  1318. // line width.
  1319. if (isNumber(options.grid.borderWidth)) {
  1320. options.tickWidth = options.lineWidth = gridOptions.borderWidth;
  1321. }
  1322. }
  1323. };
  1324. /**
  1325. * @private
  1326. */
  1327. GridAxis.onAfterSetOptions2 = function (e) {
  1328. var axis = this;
  1329. var userOptions = e.userOptions;
  1330. var gridOptions = userOptions && userOptions.grid || {};
  1331. var columns = gridOptions.columns;
  1332. // Add column options to the parent axis. Children has their column
  1333. // options set on init in onGridAxisAfterInit.
  1334. if (gridOptions.enabled && columns) {
  1335. merge(true, axis.options, columns[columns.length - 1]);
  1336. }
  1337. };
  1338. /**
  1339. * Handle columns and setScale.
  1340. * @private
  1341. */
  1342. GridAxis.onAfterSetScale = function () {
  1343. var axis = this;
  1344. (axis.grid.columns || []).forEach(function (column) {
  1345. column.setScale();
  1346. });
  1347. };
  1348. /**
  1349. * Draw vertical axis ticks extra long to create cell floors and roofs.
  1350. * Overrides the tickLength for vertical axes.
  1351. * @private
  1352. */
  1353. GridAxis.onAfterTickSize = function (e) {
  1354. var defaultLeftAxisOptions = Axis.defaultLeftAxisOptions;
  1355. var _a = this, horiz = _a.horiz, maxLabelDimensions = _a.maxLabelDimensions, _b = _a.options.grid, gridOptions = _b === void 0 ? {} : _b;
  1356. if (gridOptions.enabled && maxLabelDimensions) {
  1357. var labelPadding = (Math.abs(defaultLeftAxisOptions.labels.x) * 2);
  1358. var distance = horiz ?
  1359. gridOptions.cellHeight || labelPadding + maxLabelDimensions.height :
  1360. labelPadding + maxLabelDimensions.width;
  1361. if (isArray(e.tickSize)) {
  1362. e.tickSize[0] = distance;
  1363. }
  1364. else {
  1365. e.tickSize = [distance, 0];
  1366. }
  1367. }
  1368. };
  1369. /**
  1370. * @private
  1371. */
  1372. GridAxis.onDestroy = function (e) {
  1373. var grid = this.grid;
  1374. (grid.columns || []).forEach(function (column) {
  1375. column.destroy(e.keepEvents);
  1376. });
  1377. grid.columns = void 0;
  1378. };
  1379. /**
  1380. * Wraps axis init to draw cell walls on vertical axes.
  1381. * @private
  1382. */
  1383. GridAxis.onInit = function (e) {
  1384. var axis = this;
  1385. var userOptions = e.userOptions || {};
  1386. var gridOptions = userOptions.grid || {};
  1387. if (gridOptions.enabled && defined(gridOptions.borderColor)) {
  1388. userOptions.tickColor = userOptions.lineColor = gridOptions.borderColor;
  1389. }
  1390. if (!axis.grid) {
  1391. axis.grid = new GridAxisAdditions(axis);
  1392. }
  1393. };
  1394. /**
  1395. * Makes tick labels which are usually ignored in a linked axis
  1396. * displayed if they are within range of linkedParent.min.
  1397. * ```
  1398. * _____________________________
  1399. * | | | | |
  1400. * Make this: | | 2 | 3 | 4 |
  1401. * |___|_______|_______|_______|
  1402. * ^
  1403. * _____________________________
  1404. * | | | | |
  1405. * Into this: | 1 | 2 | 3 | 4 |
  1406. * |___|_______|_______|_______|
  1407. * ^
  1408. * ```
  1409. * @private
  1410. * @todo Does this function do what the drawing says? Seems to affect
  1411. * ticks and not the labels directly?
  1412. */
  1413. GridAxis.onTrimTicks = function () {
  1414. var axis = this;
  1415. var options = axis.options;
  1416. var gridOptions = options.grid || {};
  1417. var categoryAxis = axis.categories;
  1418. var tickPositions = axis.tickPositions;
  1419. var firstPos = tickPositions[0];
  1420. var lastPos = tickPositions[tickPositions.length - 1];
  1421. var linkedMin = axis.linkedParent && axis.linkedParent.min;
  1422. var linkedMax = axis.linkedParent && axis.linkedParent.max;
  1423. var min = linkedMin || axis.min;
  1424. var max = linkedMax || axis.max;
  1425. var tickInterval = axis.tickInterval;
  1426. var endMoreThanMin = (firstPos < min &&
  1427. firstPos + tickInterval > min);
  1428. var startLessThanMax = (lastPos > max &&
  1429. lastPos - tickInterval < max);
  1430. if (gridOptions.enabled === true &&
  1431. !categoryAxis &&
  1432. (axis.horiz || axis.isLinked)) {
  1433. if (endMoreThanMin && !options.startOnTick) {
  1434. tickPositions[0] = min;
  1435. }
  1436. if (startLessThanMax && !options.endOnTick) {
  1437. tickPositions[tickPositions.length - 1] = max;
  1438. }
  1439. }
  1440. };
  1441. /**
  1442. * Avoid altering tickInterval when reserving space.
  1443. * @private
  1444. */
  1445. GridAxis.wrapUnsquish = function (proceed) {
  1446. var axis = this;
  1447. var _a = axis.options.grid, gridOptions = _a === void 0 ? {} : _a;
  1448. if (gridOptions.enabled === true && axis.categories) {
  1449. return axis.tickInterval;
  1450. }
  1451. return proceed.apply(axis, argsToArray(arguments));
  1452. };
  1453. return GridAxis;
  1454. }());
  1455. (function (GridAxis) {
  1456. /**
  1457. * Enum for which side the axis is on. Maps to axis.side.
  1458. * @private
  1459. */
  1460. var Side;
  1461. (function (Side) {
  1462. Side[Side["top"] = 0] = "top";
  1463. Side[Side["right"] = 1] = "right";
  1464. Side[Side["bottom"] = 2] = "bottom";
  1465. Side[Side["left"] = 3] = "left";
  1466. })(Side = GridAxis.Side || (GridAxis.Side = {}));
  1467. })(GridAxis || (GridAxis = {}));
  1468. GridAxis.compose(Axis);
  1469. return GridAxis;
  1470. });
  1471. _registerModule(_modules, 'modules/broken-axis.src.js', [_modules['parts/Axis.js'], _modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['parts/Stacking.js']], function (Axis, H, U, StackItem) {
  1472. /* *
  1473. *
  1474. * (c) 2009-2020 Torstein Honsi
  1475. *
  1476. * License: www.highcharts.com/license
  1477. *
  1478. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  1479. *
  1480. * */
  1481. var addEvent = U.addEvent, find = U.find, fireEvent = U.fireEvent, isArray = U.isArray, isNumber = U.isNumber, pick = U.pick;
  1482. var Series = H.Series;
  1483. /* eslint-disable valid-jsdoc */
  1484. /**
  1485. * Provides support for broken axes.
  1486. * @private
  1487. * @class
  1488. */
  1489. var BrokenAxisAdditions = /** @class */ (function () {
  1490. /* *
  1491. *
  1492. * Constructors
  1493. *
  1494. * */
  1495. function BrokenAxisAdditions(axis) {
  1496. this.hasBreaks = false;
  1497. this.axis = axis;
  1498. }
  1499. /* *
  1500. *
  1501. * Static Functions
  1502. *
  1503. * */
  1504. /**
  1505. * @private
  1506. */
  1507. BrokenAxisAdditions.isInBreak = function (brk, val) {
  1508. var ret, repeat = brk.repeat || Infinity, from = brk.from, length = brk.to - brk.from, test = (val >= from ?
  1509. (val - from) % repeat :
  1510. repeat - ((from - val) % repeat));
  1511. if (!brk.inclusive) {
  1512. ret = test < length && test !== 0;
  1513. }
  1514. else {
  1515. ret = test <= length;
  1516. }
  1517. return ret;
  1518. };
  1519. /**
  1520. * @private
  1521. */
  1522. BrokenAxisAdditions.lin2Val = function (val) {
  1523. var axis = this;
  1524. var brokenAxis = axis.brokenAxis;
  1525. var breakArray = brokenAxis && brokenAxis.breakArray;
  1526. if (!breakArray) {
  1527. return val;
  1528. }
  1529. var nval = val, brk, i;
  1530. for (i = 0; i < breakArray.length; i++) {
  1531. brk = breakArray[i];
  1532. if (brk.from >= nval) {
  1533. break;
  1534. }
  1535. else if (brk.to < nval) {
  1536. nval += brk.len;
  1537. }
  1538. else if (BrokenAxisAdditions.isInBreak(brk, nval)) {
  1539. nval += brk.len;
  1540. }
  1541. }
  1542. return nval;
  1543. };
  1544. /**
  1545. * @private
  1546. */
  1547. BrokenAxisAdditions.val2Lin = function (val) {
  1548. var axis = this;
  1549. var brokenAxis = axis.brokenAxis;
  1550. var breakArray = brokenAxis && brokenAxis.breakArray;
  1551. if (!breakArray) {
  1552. return val;
  1553. }
  1554. var nval = val, brk, i;
  1555. for (i = 0; i < breakArray.length; i++) {
  1556. brk = breakArray[i];
  1557. if (brk.to <= val) {
  1558. nval -= brk.len;
  1559. }
  1560. else if (brk.from >= val) {
  1561. break;
  1562. }
  1563. else if (BrokenAxisAdditions.isInBreak(brk, val)) {
  1564. nval -= (val - brk.from);
  1565. break;
  1566. }
  1567. }
  1568. return nval;
  1569. };
  1570. /* *
  1571. *
  1572. * Functions
  1573. *
  1574. * */
  1575. /**
  1576. * Returns the first break found where the x is larger then break.from and
  1577. * smaller then break.to.
  1578. *
  1579. * @param {number} x
  1580. * The number which should be within a break.
  1581. *
  1582. * @param {Array<Highcharts.XAxisBreaksOptions>} breaks
  1583. * The array of breaks to search within.
  1584. *
  1585. * @return {Highcharts.XAxisBreaksOptions|undefined}
  1586. * Returns the first break found that matches, returns false if no break is
  1587. * found.
  1588. */
  1589. BrokenAxisAdditions.prototype.findBreakAt = function (x, breaks) {
  1590. return find(breaks, function (b) {
  1591. return b.from < x && x < b.to;
  1592. });
  1593. };
  1594. /**
  1595. * @private
  1596. */
  1597. BrokenAxisAdditions.prototype.isInAnyBreak = function (val, testKeep) {
  1598. var brokenAxis = this;
  1599. var axis = brokenAxis.axis;
  1600. var breaks = axis.options.breaks, i = breaks && breaks.length, inbrk, keep, ret;
  1601. if (i) {
  1602. while (i--) {
  1603. if (BrokenAxisAdditions.isInBreak(breaks[i], val)) {
  1604. inbrk = true;
  1605. if (!keep) {
  1606. keep = pick(breaks[i].showPoints, !axis.isXAxis);
  1607. }
  1608. }
  1609. }
  1610. if (inbrk && testKeep) {
  1611. ret = inbrk && !keep;
  1612. }
  1613. else {
  1614. ret = inbrk;
  1615. }
  1616. }
  1617. return ret;
  1618. };
  1619. /**
  1620. * Dynamically set or unset breaks in an axis. This function in lighter than
  1621. * usin Axis.update, and it also preserves animation.
  1622. *
  1623. * @private
  1624. * @function Highcharts.Axis#setBreaks
  1625. *
  1626. * @param {Array<Highcharts.XAxisBreaksOptions>} [breaks]
  1627. * The breaks to add. When `undefined` it removes existing breaks.
  1628. *
  1629. * @param {boolean} [redraw=true]
  1630. * Whether to redraw the chart immediately.
  1631. *
  1632. * @return {void}
  1633. */
  1634. BrokenAxisAdditions.prototype.setBreaks = function (breaks, redraw) {
  1635. var brokenAxis = this;
  1636. var axis = brokenAxis.axis;
  1637. var hasBreaks = (isArray(breaks) && !!breaks.length);
  1638. axis.isDirty = brokenAxis.hasBreaks !== hasBreaks;
  1639. brokenAxis.hasBreaks = hasBreaks;
  1640. axis.options.breaks = axis.userOptions.breaks = breaks;
  1641. axis.forceRedraw = true; // Force recalculation in setScale
  1642. // Recalculate series related to the axis.
  1643. axis.series.forEach(function (series) {
  1644. series.isDirty = true;
  1645. });
  1646. if (!hasBreaks && axis.val2lin === BrokenAxisAdditions.val2Lin) {
  1647. // Revert to prototype functions
  1648. delete axis.val2lin;
  1649. delete axis.lin2val;
  1650. }
  1651. if (hasBreaks) {
  1652. axis.userOptions.ordinal = false;
  1653. axis.lin2val = BrokenAxisAdditions.lin2Val;
  1654. axis.val2lin = BrokenAxisAdditions.val2Lin;
  1655. axis.setExtremes = function (newMin, newMax, redraw, animation, eventArguments) {
  1656. // If trying to set extremes inside a break, extend min to
  1657. // after, and max to before the break ( #3857 )
  1658. if (brokenAxis.hasBreaks) {
  1659. var axisBreak, breaks = this.options.breaks;
  1660. while ((axisBreak = brokenAxis.findBreakAt(newMin, breaks))) {
  1661. newMin = axisBreak.to;
  1662. }
  1663. while ((axisBreak = brokenAxis.findBreakAt(newMax, breaks))) {
  1664. newMax = axisBreak.from;
  1665. }
  1666. // If both min and max is within the same break.
  1667. if (newMax < newMin) {
  1668. newMax = newMin;
  1669. }
  1670. }
  1671. Axis.prototype.setExtremes.call(this, newMin, newMax, redraw, animation, eventArguments);
  1672. };
  1673. axis.setAxisTranslation = function (saveOld) {
  1674. Axis.prototype.setAxisTranslation.call(this, saveOld);
  1675. brokenAxis.unitLength = null;
  1676. if (brokenAxis.hasBreaks) {
  1677. var breaks = axis.options.breaks || [],
  1678. // Temporary one:
  1679. breakArrayT = [], breakArray = [], length = 0, inBrk, repeat, min = axis.userMin || axis.min, max = axis.userMax || axis.max, pointRangePadding = pick(axis.pointRangePadding, 0), start, i;
  1680. // Min & max check (#4247)
  1681. breaks.forEach(function (brk) {
  1682. repeat = brk.repeat || Infinity;
  1683. if (BrokenAxisAdditions.isInBreak(brk, min)) {
  1684. min +=
  1685. (brk.to % repeat) -
  1686. (min % repeat);
  1687. }
  1688. if (BrokenAxisAdditions.isInBreak(brk, max)) {
  1689. max -=
  1690. (max % repeat) -
  1691. (brk.from % repeat);
  1692. }
  1693. });
  1694. // Construct an array holding all breaks in the axis
  1695. breaks.forEach(function (brk) {
  1696. start = brk.from;
  1697. repeat = brk.repeat || Infinity;
  1698. while (start - repeat > min) {
  1699. start -= repeat;
  1700. }
  1701. while (start < min) {
  1702. start += repeat;
  1703. }
  1704. for (i = start; i < max; i += repeat) {
  1705. breakArrayT.push({
  1706. value: i,
  1707. move: 'in'
  1708. });
  1709. breakArrayT.push({
  1710. value: i + (brk.to - brk.from),
  1711. move: 'out',
  1712. size: brk.breakSize
  1713. });
  1714. }
  1715. });
  1716. breakArrayT.sort(function (a, b) {
  1717. return ((a.value === b.value) ?
  1718. ((a.move === 'in' ? 0 : 1) -
  1719. (b.move === 'in' ? 0 : 1)) :
  1720. a.value - b.value);
  1721. });
  1722. // Simplify the breaks
  1723. inBrk = 0;
  1724. start = min;
  1725. breakArrayT.forEach(function (brk) {
  1726. inBrk += (brk.move === 'in' ? 1 : -1);
  1727. if (inBrk === 1 && brk.move === 'in') {
  1728. start = brk.value;
  1729. }
  1730. if (inBrk === 0) {
  1731. breakArray.push({
  1732. from: start,
  1733. to: brk.value,
  1734. len: brk.value - start - (brk.size || 0)
  1735. });
  1736. length += brk.value - start - (brk.size || 0);
  1737. }
  1738. });
  1739. /**
  1740. * HC <= 8 backwards compatibility, used by demo samples.
  1741. * @deprecated
  1742. * @private
  1743. * @requires modules/broken-axis
  1744. */
  1745. axis.breakArray = brokenAxis.breakArray = breakArray;
  1746. // Used with staticScale, and below the actual axis length,
  1747. // when breaks are substracted.
  1748. brokenAxis.unitLength = max - min - length + pointRangePadding;
  1749. fireEvent(axis, 'afterBreaks');
  1750. if (axis.staticScale) {
  1751. axis.transA = axis.staticScale;
  1752. }
  1753. else if (brokenAxis.unitLength) {
  1754. axis.transA *=
  1755. (max - axis.min + pointRangePadding) /
  1756. brokenAxis.unitLength;
  1757. }
  1758. if (pointRangePadding) {
  1759. axis.minPixelPadding =
  1760. axis.transA * axis.minPointOffset;
  1761. }
  1762. axis.min = min;
  1763. axis.max = max;
  1764. }
  1765. };
  1766. }
  1767. if (pick(redraw, true)) {
  1768. axis.chart.redraw();
  1769. }
  1770. };
  1771. return BrokenAxisAdditions;
  1772. }());
  1773. /**
  1774. * Axis with support of broken data rows.
  1775. * @private
  1776. * @class
  1777. */
  1778. var BrokenAxis = /** @class */ (function () {
  1779. function BrokenAxis() {
  1780. }
  1781. /**
  1782. * Adds support for broken axes.
  1783. * @private
  1784. */
  1785. BrokenAxis.compose = function (AxisClass, SeriesClass) {
  1786. AxisClass.keepProps.push('brokenAxis');
  1787. var seriesProto = Series.prototype;
  1788. /**
  1789. * @private
  1790. */
  1791. seriesProto.drawBreaks = function (axis, keys) {
  1792. var series = this, points = series.points, breaks, threshold, eventName, y;
  1793. if (axis && // #5950
  1794. axis.brokenAxis &&
  1795. axis.brokenAxis.hasBreaks) {
  1796. var brokenAxis_1 = axis.brokenAxis;
  1797. keys.forEach(function (key) {
  1798. breaks = brokenAxis_1 && brokenAxis_1.breakArray || [];
  1799. threshold = axis.isXAxis ?
  1800. axis.min :
  1801. pick(series.options.threshold, axis.min);
  1802. points.forEach(function (point) {
  1803. y = pick(point['stack' + key.toUpperCase()], point[key]);
  1804. breaks.forEach(function (brk) {
  1805. if (isNumber(threshold) && isNumber(y)) {
  1806. eventName = false;
  1807. if ((threshold < brk.from && y > brk.to) ||
  1808. (threshold > brk.from && y < brk.from)) {
  1809. eventName = 'pointBreak';
  1810. }
  1811. else if ((threshold < brk.from && y > brk.from && y < brk.to) ||
  1812. (threshold > brk.from && y > brk.to && y < brk.from)) {
  1813. eventName = 'pointInBreak';
  1814. }
  1815. if (eventName) {
  1816. fireEvent(axis, eventName, { point: point, brk: brk });
  1817. }
  1818. }
  1819. });
  1820. });
  1821. });
  1822. }
  1823. };
  1824. /**
  1825. * Extend getGraphPath by identifying gaps in the data so that we can
  1826. * draw a gap in the line or area. This was moved from ordinal axis
  1827. * module to broken axis module as of #5045.
  1828. *
  1829. * @private
  1830. * @function Highcharts.Series#gappedPath
  1831. *
  1832. * @return {Highcharts.SVGPathArray}
  1833. * Gapped path
  1834. */
  1835. seriesProto.gappedPath = function () {
  1836. var currentDataGrouping = this.currentDataGrouping, groupingSize = currentDataGrouping && currentDataGrouping.gapSize, gapSize = this.options.gapSize, points = this.points.slice(), i = points.length - 1, yAxis = this.yAxis, stack;
  1837. /**
  1838. * Defines when to display a gap in the graph, together with the
  1839. * [gapUnit](plotOptions.series.gapUnit) option.
  1840. *
  1841. * In case when `dataGrouping` is enabled, points can be grouped
  1842. * into a larger time span. This can make the grouped points to have
  1843. * a greater distance than the absolute value of `gapSize` property,
  1844. * which will result in disappearing graph completely. To prevent
  1845. * this situation the mentioned distance between grouped points is
  1846. * used instead of previously defined `gapSize`.
  1847. *
  1848. * In practice, this option is most often used to visualize gaps in
  1849. * time series. In a stock chart, intraday data is available for
  1850. * daytime hours, while gaps will appear in nights and weekends.
  1851. *
  1852. * @see [gapUnit](plotOptions.series.gapUnit)
  1853. * @see [xAxis.breaks](#xAxis.breaks)
  1854. *
  1855. * @sample {highstock} stock/plotoptions/series-gapsize/
  1856. * Setting the gap size to 2 introduces gaps for weekends
  1857. * in daily datasets.
  1858. *
  1859. * @type {number}
  1860. * @default 0
  1861. * @product highstock
  1862. * @requires modules/broken-axis
  1863. * @apioption plotOptions.series.gapSize
  1864. */
  1865. /**
  1866. * Together with [gapSize](plotOptions.series.gapSize), this option
  1867. * defines where to draw gaps in the graph.
  1868. *
  1869. * When the `gapUnit` is `"relative"` (default), a gap size of 5
  1870. * means that if the distance between two points is greater than
  1871. * 5 times that of the two closest points, the graph will be broken.
  1872. *
  1873. * When the `gapUnit` is `"value"`, the gap is based on absolute
  1874. * axis values, which on a datetime axis is milliseconds. This also
  1875. * applies to the navigator series that inherits gap options from
  1876. * the base series.
  1877. *
  1878. * @see [gapSize](plotOptions.series.gapSize)
  1879. *
  1880. * @type {string}
  1881. * @default relative
  1882. * @since 5.0.13
  1883. * @product highstock
  1884. * @validvalue ["relative", "value"]
  1885. * @requires modules/broken-axis
  1886. * @apioption plotOptions.series.gapUnit
  1887. */
  1888. if (gapSize && i > 0) { // #5008
  1889. // Gap unit is relative
  1890. if (this.options.gapUnit !== 'value') {
  1891. gapSize *= this.basePointRange;
  1892. }
  1893. // Setting a new gapSize in case dataGrouping is enabled (#7686)
  1894. if (groupingSize &&
  1895. groupingSize > gapSize &&
  1896. // Except when DG is forced (e.g. from other series)
  1897. // and has lower granularity than actual points (#11351)
  1898. groupingSize >= this.basePointRange) {
  1899. gapSize = groupingSize;
  1900. }
  1901. // extension for ordinal breaks
  1902. var current = void 0, next = void 0;
  1903. while (i--) {
  1904. // Reassign next if it is not visible
  1905. if (!(next && next.visible !== false)) {
  1906. next = points[i + 1];
  1907. }
  1908. current = points[i];
  1909. // Skip iteration if one of the points is not visible
  1910. if (next.visible === false || current.visible === false) {
  1911. continue;
  1912. }
  1913. if (next.x - current.x > gapSize) {
  1914. var xRange = (current.x + next.x) / 2;
  1915. points.splice(// insert after this one
  1916. i + 1, 0, {
  1917. isNull: true,
  1918. x: xRange
  1919. });
  1920. // For stacked chart generate empty stack items, #6546
  1921. if (yAxis.stacking && this.options.stacking) {
  1922. stack = yAxis.stacking.stacks[this.stackKey][xRange] =
  1923. new StackItem(yAxis, yAxis.options
  1924. .stackLabels, false, xRange, this.stack);
  1925. stack.total = 0;
  1926. }
  1927. }
  1928. // Assign current to next for the upcoming iteration
  1929. next = current;
  1930. }
  1931. }
  1932. // Call base method
  1933. return this.getGraphPath(points);
  1934. };
  1935. /* eslint-disable no-invalid-this */
  1936. addEvent(AxisClass, 'init', function () {
  1937. var axis = this;
  1938. if (!axis.brokenAxis) {
  1939. axis.brokenAxis = new BrokenAxisAdditions(axis);
  1940. }
  1941. });
  1942. addEvent(AxisClass, 'afterInit', function () {
  1943. if (typeof this.brokenAxis !== 'undefined') {
  1944. this.brokenAxis.setBreaks(this.options.breaks, false);
  1945. }
  1946. });
  1947. addEvent(AxisClass, 'afterSetTickPositions', function () {
  1948. var axis = this;
  1949. var brokenAxis = axis.brokenAxis;
  1950. if (brokenAxis &&
  1951. brokenAxis.hasBreaks) {
  1952. var tickPositions = this.tickPositions, info = this.tickPositions.info, newPositions = [], i;
  1953. for (i = 0; i < tickPositions.length; i++) {
  1954. if (!brokenAxis.isInAnyBreak(tickPositions[i])) {
  1955. newPositions.push(tickPositions[i]);
  1956. }
  1957. }
  1958. this.tickPositions = newPositions;
  1959. this.tickPositions.info = info;
  1960. }
  1961. });
  1962. // Force Axis to be not-ordinal when breaks are defined
  1963. addEvent(AxisClass, 'afterSetOptions', function () {
  1964. if (this.brokenAxis && this.brokenAxis.hasBreaks) {
  1965. this.options.ordinal = false;
  1966. }
  1967. });
  1968. addEvent(SeriesClass, 'afterGeneratePoints', function () {
  1969. var _a = this, isDirty = _a.isDirty, connectNulls = _a.options.connectNulls, points = _a.points, xAxis = _a.xAxis, yAxis = _a.yAxis;
  1970. // Set, or reset visibility of the points. Axis.setBreaks marks the
  1971. // series as isDirty
  1972. if (isDirty) {
  1973. var i = points.length;
  1974. while (i--) {
  1975. var point = points[i];
  1976. // Respect nulls inside the break (#4275)
  1977. var nullGap = point.y === null && connectNulls === false;
  1978. var isPointInBreak = (!nullGap && ((xAxis &&
  1979. xAxis.brokenAxis &&
  1980. xAxis.brokenAxis.isInAnyBreak(point.x, true)) || (yAxis &&
  1981. yAxis.brokenAxis &&
  1982. yAxis.brokenAxis.isInAnyBreak(point.y, true))));
  1983. // Set point.visible if in any break.
  1984. // If not in break, reset visible to original value.
  1985. point.visible = isPointInBreak ?
  1986. false :
  1987. point.options.visible !== false;
  1988. }
  1989. }
  1990. });
  1991. addEvent(SeriesClass, 'afterRender', function drawPointsWrapped() {
  1992. this.drawBreaks(this.xAxis, ['x']);
  1993. this.drawBreaks(this.yAxis, pick(this.pointArrayMap, ['y']));
  1994. });
  1995. };
  1996. return BrokenAxis;
  1997. }());
  1998. BrokenAxis.compose(Axis, Series); // @todo remove automatism
  1999. return BrokenAxis;
  2000. });
  2001. _registerModule(_modules, 'parts-gantt/TreeGridAxis.js', [_modules['parts/Axis.js'], _modules['parts/Tick.js'], _modules['parts-gantt/Tree.js'], _modules['parts-gantt/TreeGridTick.js'], _modules['mixins/tree-series.js'], _modules['parts/Utilities.js']], function (Axis, Tick, Tree, TreeGridTick, TreeSeriesMixin, U) {
  2002. /* *
  2003. *
  2004. * (c) 2016 Highsoft AS
  2005. * Authors: Jon Arild Nygard
  2006. *
  2007. * License: www.highcharts.com/license
  2008. *
  2009. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  2010. *
  2011. * */
  2012. var addEvent = U.addEvent, find = U.find, fireEvent = U.fireEvent, isNumber = U.isNumber, isObject = U.isObject, isString = U.isString, merge = U.merge, pick = U.pick, wrap = U.wrap;
  2013. /**
  2014. * @private
  2015. */
  2016. var TreeGridAxis;
  2017. (function (TreeGridAxis) {
  2018. /* *
  2019. *
  2020. * Interfaces
  2021. *
  2022. * */
  2023. /* *
  2024. *
  2025. * Variables
  2026. *
  2027. * */
  2028. var applied = false;
  2029. /* *
  2030. *
  2031. * Functions
  2032. *
  2033. * */
  2034. /**
  2035. * @private
  2036. */
  2037. function compose(AxisClass) {
  2038. if (!applied) {
  2039. wrap(AxisClass.prototype, 'generateTick', wrapGenerateTick);
  2040. wrap(AxisClass.prototype, 'getMaxLabelDimensions', wrapGetMaxLabelDimensions);
  2041. wrap(AxisClass.prototype, 'init', wrapInit);
  2042. wrap(AxisClass.prototype, 'setTickInterval', wrapSetTickInterval);
  2043. TreeGridTick.compose(Tick);
  2044. applied = true;
  2045. }
  2046. }
  2047. TreeGridAxis.compose = compose;
  2048. /**
  2049. * @private
  2050. */
  2051. function getBreakFromNode(node, max) {
  2052. var from = node.collapseStart || 0, to = node.collapseEnd || 0;
  2053. // In broken-axis, the axis.max is minimized until it is not within a
  2054. // break. Therefore, if break.to is larger than axis.max, the axis.to
  2055. // should not add the 0.5 axis.tickMarkOffset, to avoid adding a break
  2056. // larger than axis.max.
  2057. // TODO consider simplifying broken-axis and this might solve itself
  2058. if (to >= max) {
  2059. from -= 0.5;
  2060. }
  2061. return {
  2062. from: from,
  2063. to: to,
  2064. showPoints: false
  2065. };
  2066. }
  2067. /**
  2068. * Creates a tree structure of the data, and the treegrid. Calculates
  2069. * categories, and y-values of points based on the tree.
  2070. *
  2071. * @private
  2072. * @function getTreeGridFromData
  2073. *
  2074. * @param {Array<Highcharts.GanttPointOptions>} data
  2075. * All the data points to display in the axis.
  2076. *
  2077. * @param {boolean} uniqueNames
  2078. * Wether or not the data node with the same name should share grid cell. If
  2079. * true they do share cell. False by default.
  2080. *
  2081. * @param {number} numberOfSeries
  2082. *
  2083. * @return {object}
  2084. * Returns an object containing categories, mapOfIdToNode,
  2085. * mapOfPosToGridNode, and tree.
  2086. *
  2087. * @todo There should be only one point per line.
  2088. * @todo It should be optional to have one category per point, or merge
  2089. * cells
  2090. * @todo Add unit-tests.
  2091. */
  2092. function getTreeGridFromData(data, uniqueNames, numberOfSeries) {
  2093. var categories = [], collapsedNodes = [], mapOfIdToNode = {}, mapOfPosToGridNode = {}, posIterator = -1, uniqueNamesEnabled = typeof uniqueNames === 'boolean' ? uniqueNames : false, tree;
  2094. // Build the tree from the series data.
  2095. var treeParams = {
  2096. // After the children has been created.
  2097. after: function (node) {
  2098. var gridNode = mapOfPosToGridNode[node.pos], height = 0, descendants = 0;
  2099. gridNode.children.forEach(function (child) {
  2100. descendants += (child.descendants || 0) + 1;
  2101. height = Math.max((child.height || 0) + 1, height);
  2102. });
  2103. gridNode.descendants = descendants;
  2104. gridNode.height = height;
  2105. if (gridNode.collapsed) {
  2106. collapsedNodes.push(gridNode);
  2107. }
  2108. },
  2109. // Before the children has been created.
  2110. before: function (node) {
  2111. var data = isObject(node.data, true) ? node.data : {}, name = isString(data.name) ? data.name : '', parentNode = mapOfIdToNode[node.parent], parentGridNode = (isObject(parentNode, true) ?
  2112. mapOfPosToGridNode[parentNode.pos] :
  2113. null), hasSameName = function (x) {
  2114. return x.name === name;
  2115. }, gridNode, pos;
  2116. // If not unique names, look for sibling node with the same name
  2117. if (uniqueNamesEnabled &&
  2118. isObject(parentGridNode, true) &&
  2119. !!(gridNode = find(parentGridNode.children, hasSameName))) {
  2120. // If there is a gridNode with the same name, reuse position
  2121. pos = gridNode.pos;
  2122. // Add data node to list of nodes in the grid node.
  2123. gridNode.nodes.push(node);
  2124. }
  2125. else {
  2126. // If it is a new grid node, increment position.
  2127. pos = posIterator++;
  2128. }
  2129. // Add new grid node to map.
  2130. if (!mapOfPosToGridNode[pos]) {
  2131. mapOfPosToGridNode[pos] = gridNode = {
  2132. depth: parentGridNode ? parentGridNode.depth + 1 : 0,
  2133. name: name,
  2134. nodes: [node],
  2135. children: [],
  2136. pos: pos
  2137. };
  2138. // If not root, then add name to categories.
  2139. if (pos !== -1) {
  2140. categories.push(name);
  2141. }
  2142. // Add name to list of children.
  2143. if (isObject(parentGridNode, true)) {
  2144. parentGridNode.children.push(gridNode);
  2145. }
  2146. }
  2147. // Add data node to map
  2148. if (isString(node.id)) {
  2149. mapOfIdToNode[node.id] = node;
  2150. }
  2151. // If one of the points are collapsed, then start the grid node
  2152. // in collapsed state.
  2153. if (gridNode &&
  2154. data.collapsed === true) {
  2155. gridNode.collapsed = true;
  2156. }
  2157. // Assign pos to data node
  2158. node.pos = pos;
  2159. }
  2160. };
  2161. var updateYValuesAndTickPos = function (map, numberOfSeries) {
  2162. var setValues = function (gridNode, start, result) {
  2163. var nodes = gridNode.nodes, end = start + (start === -1 ? 0 : numberOfSeries - 1), diff = (end - start) / 2, padding = 0.5, pos = start + diff;
  2164. nodes.forEach(function (node) {
  2165. var data = node.data;
  2166. if (isObject(data, true)) {
  2167. // Update point
  2168. data.y = start + (data.seriesIndex || 0);
  2169. // Remove the property once used
  2170. delete data.seriesIndex;
  2171. }
  2172. node.pos = pos;
  2173. });
  2174. result[pos] = gridNode;
  2175. gridNode.pos = pos;
  2176. gridNode.tickmarkOffset = diff + padding;
  2177. gridNode.collapseStart = end + padding;
  2178. gridNode.children.forEach(function (child) {
  2179. setValues(child, end + 1, result);
  2180. end = (child.collapseEnd || 0) - padding;
  2181. });
  2182. // Set collapseEnd to the end of the last child node.
  2183. gridNode.collapseEnd = end + padding;
  2184. return result;
  2185. };
  2186. return setValues(map['-1'], -1, {});
  2187. };
  2188. // Create tree from data
  2189. tree = Tree.getTree(data, treeParams);
  2190. // Update y values of data, and set calculate tick positions.
  2191. mapOfPosToGridNode = updateYValuesAndTickPos(mapOfPosToGridNode, numberOfSeries);
  2192. // Return the resulting data.
  2193. return {
  2194. categories: categories,
  2195. mapOfIdToNode: mapOfIdToNode,
  2196. mapOfPosToGridNode: mapOfPosToGridNode,
  2197. collapsedNodes: collapsedNodes,
  2198. tree: tree
  2199. };
  2200. }
  2201. /**
  2202. * Builds the tree of categories and calculates its positions.
  2203. * @private
  2204. * @param {object} e Event object
  2205. * @param {object} e.target The chart instance which the event was fired on.
  2206. * @param {object[]} e.target.axes The axes of the chart.
  2207. */
  2208. function onBeforeRender(e) {
  2209. var chart = e.target, axes = chart.axes;
  2210. axes.filter(function (axis) {
  2211. return axis.options.type === 'treegrid';
  2212. }).forEach(function (axis) {
  2213. var options = axis.options || {}, labelOptions = options.labels, uniqueNames = options.uniqueNames, numberOfSeries = 0, isDirty, data, treeGrid;
  2214. // Check whether any of series is rendering for the first time,
  2215. // visibility has changed, or its data is dirty,
  2216. // and only then update. #10570, #10580
  2217. // Also check if mapOfPosToGridNode exists. #10887
  2218. isDirty = (!axis.treeGrid.mapOfPosToGridNode ||
  2219. axis.series.some(function (series) {
  2220. return !series.hasRendered ||
  2221. series.isDirtyData ||
  2222. series.isDirty;
  2223. }));
  2224. if (isDirty) {
  2225. // Concatenate data from all series assigned to this axis.
  2226. data = axis.series.reduce(function (arr, s) {
  2227. if (s.visible) {
  2228. // Push all data to array
  2229. (s.options.data || []).forEach(function (data) {
  2230. if (isObject(data, true)) {
  2231. // Set series index on data. Removed again
  2232. // after use.
  2233. data.seriesIndex = numberOfSeries;
  2234. arr.push(data);
  2235. }
  2236. });
  2237. // Increment series index
  2238. if (uniqueNames === true) {
  2239. numberOfSeries++;
  2240. }
  2241. }
  2242. return arr;
  2243. }, []);
  2244. // setScale is fired after all the series is initialized,
  2245. // which is an ideal time to update the axis.categories.
  2246. treeGrid = getTreeGridFromData(data, uniqueNames || false, (uniqueNames === true) ? numberOfSeries : 1);
  2247. // Assign values to the axis.
  2248. axis.categories = treeGrid.categories;
  2249. axis.treeGrid.mapOfPosToGridNode = treeGrid.mapOfPosToGridNode;
  2250. axis.hasNames = true;
  2251. axis.treeGrid.tree = treeGrid.tree;
  2252. // Update yData now that we have calculated the y values
  2253. axis.series.forEach(function (series) {
  2254. var data = (series.options.data || []).map(function (d) {
  2255. return isObject(d, true) ? merge(d) : d;
  2256. });
  2257. // Avoid destroying points when series is not visible
  2258. if (series.visible) {
  2259. series.setData(data, false);
  2260. }
  2261. });
  2262. // Calculate the label options for each level in the tree.
  2263. axis.treeGrid.mapOptionsToLevel =
  2264. TreeSeriesMixin.getLevelOptions({
  2265. defaults: labelOptions,
  2266. from: 1,
  2267. levels: labelOptions && labelOptions.levels,
  2268. to: axis.treeGrid.tree && axis.treeGrid.tree.height
  2269. });
  2270. // Setting initial collapsed nodes
  2271. if (e.type === 'beforeRender') {
  2272. axis.treeGrid.collapsedNodes = treeGrid.collapsedNodes;
  2273. }
  2274. }
  2275. });
  2276. }
  2277. /**
  2278. * Generates a tick for initial positioning.
  2279. *
  2280. * @private
  2281. * @function Highcharts.GridAxis#generateTick
  2282. *
  2283. * @param {Function} proceed
  2284. * The original generateTick function.
  2285. *
  2286. * @param {number} pos
  2287. * The tick position in axis values.
  2288. */
  2289. function wrapGenerateTick(proceed, pos) {
  2290. var axis = this, mapOptionsToLevel = axis.treeGrid.mapOptionsToLevel || {}, isTreeGrid = axis.options.type === 'treegrid', ticks = axis.ticks;
  2291. var tick = ticks[pos], levelOptions, options, gridNode;
  2292. if (isTreeGrid &&
  2293. axis.treeGrid.mapOfPosToGridNode) {
  2294. gridNode = axis.treeGrid.mapOfPosToGridNode[pos];
  2295. levelOptions = mapOptionsToLevel[gridNode.depth];
  2296. if (levelOptions) {
  2297. options = {
  2298. labels: levelOptions
  2299. };
  2300. }
  2301. if (!tick) {
  2302. ticks[pos] = tick =
  2303. new Tick(axis, pos, void 0, void 0, {
  2304. category: gridNode.name,
  2305. tickmarkOffset: gridNode.tickmarkOffset,
  2306. options: options
  2307. });
  2308. }
  2309. else {
  2310. // update labels depending on tick interval
  2311. tick.parameters.category = gridNode.name;
  2312. tick.options = options;
  2313. tick.addLabel();
  2314. }
  2315. }
  2316. else {
  2317. proceed.apply(axis, Array.prototype.slice.call(arguments, 1));
  2318. }
  2319. }
  2320. /**
  2321. * Override to add indentation to axis.maxLabelDimensions.
  2322. *
  2323. * @private
  2324. * @function Highcharts.GridAxis#getMaxLabelDimensions
  2325. *
  2326. * @param {Function} proceed
  2327. * The original function
  2328. */
  2329. function wrapGetMaxLabelDimensions(proceed) {
  2330. var axis = this, options = axis.options, labelOptions = options && options.labels, indentation = (labelOptions && isNumber(labelOptions.indentation) ?
  2331. labelOptions.indentation :
  2332. 0), retVal = proceed.apply(axis, Array.prototype.slice.call(arguments, 1)), isTreeGrid = axis.options.type === 'treegrid';
  2333. var treeDepth;
  2334. if (isTreeGrid && axis.treeGrid.mapOfPosToGridNode) {
  2335. treeDepth = axis.treeGrid.mapOfPosToGridNode[-1].height || 0;
  2336. retVal.width += indentation * (treeDepth - 1);
  2337. }
  2338. return retVal;
  2339. }
  2340. /**
  2341. * @private
  2342. */
  2343. function wrapInit(proceed, chart, userOptions) {
  2344. var axis = this, isTreeGrid = userOptions.type === 'treegrid';
  2345. if (!axis.treeGrid) {
  2346. axis.treeGrid = new Additions(axis);
  2347. }
  2348. // Set default and forced options for TreeGrid
  2349. if (isTreeGrid) {
  2350. // Add event for updating the categories of a treegrid.
  2351. // NOTE Preferably these events should be set on the axis.
  2352. addEvent(chart, 'beforeRender', onBeforeRender);
  2353. addEvent(chart, 'beforeRedraw', onBeforeRender);
  2354. // Add new collapsed nodes on addseries
  2355. addEvent(chart, 'addSeries', function (e) {
  2356. if (e.options.data) {
  2357. var treeGrid = getTreeGridFromData(e.options.data, userOptions.uniqueNames || false, 1);
  2358. axis.treeGrid.collapsedNodes = (axis.treeGrid.collapsedNodes || []).concat(treeGrid.collapsedNodes);
  2359. }
  2360. });
  2361. // Collapse all nodes in axis.treegrid.collapsednodes
  2362. // where collapsed equals true.
  2363. addEvent(axis, 'foundExtremes', function () {
  2364. if (axis.treeGrid.collapsedNodes) {
  2365. axis.treeGrid.collapsedNodes.forEach(function (node) {
  2366. var breaks = axis.treeGrid.collapse(node);
  2367. if (axis.brokenAxis) {
  2368. axis.brokenAxis.setBreaks(breaks, false);
  2369. // remove the node from the axis collapsedNodes
  2370. if (axis.treeGrid.collapsedNodes) {
  2371. axis.treeGrid.collapsedNodes = axis.treeGrid.collapsedNodes.filter(function (n) {
  2372. return node.collapseStart !== n.collapseStart ||
  2373. node.collapseEnd !== n.collapseEnd;
  2374. });
  2375. }
  2376. }
  2377. });
  2378. }
  2379. });
  2380. // If staticScale is not defined on the yAxis
  2381. // and chart height is set, set axis.isDirty
  2382. // to ensure collapsing works (#12012)
  2383. addEvent(axis, 'afterBreaks', function () {
  2384. var _a;
  2385. if (axis.coll === 'yAxis' && !axis.staticScale && ((_a = axis.chart.options.chart) === null || _a === void 0 ? void 0 : _a.height)) {
  2386. axis.isDirty = true;
  2387. }
  2388. });
  2389. userOptions = merge({
  2390. // Default options
  2391. grid: {
  2392. enabled: true
  2393. },
  2394. // TODO: add support for align in treegrid.
  2395. labels: {
  2396. align: 'left',
  2397. /**
  2398. * Set options on specific levels in a tree grid axis. Takes
  2399. * precedence over labels options.
  2400. *
  2401. * @sample {gantt} gantt/treegrid-axis/labels-levels
  2402. * Levels on TreeGrid Labels
  2403. *
  2404. * @type {Array<*>}
  2405. * @product gantt
  2406. * @apioption yAxis.labels.levels
  2407. *
  2408. * @private
  2409. */
  2410. levels: [{
  2411. /**
  2412. * Specify the level which the options within this object
  2413. * applies to.
  2414. *
  2415. * @type {number}
  2416. * @product gantt
  2417. * @apioption yAxis.labels.levels.level
  2418. *
  2419. * @private
  2420. */
  2421. level: void 0
  2422. }, {
  2423. level: 1,
  2424. /**
  2425. * @type {Highcharts.CSSObject}
  2426. * @product gantt
  2427. * @apioption yAxis.labels.levels.style
  2428. *
  2429. * @private
  2430. */
  2431. style: {
  2432. /** @ignore-option */
  2433. fontWeight: 'bold'
  2434. }
  2435. }],
  2436. /**
  2437. * The symbol for the collapse and expand icon in a
  2438. * treegrid.
  2439. *
  2440. * @product gantt
  2441. * @optionparent yAxis.labels.symbol
  2442. *
  2443. * @private
  2444. */
  2445. symbol: {
  2446. /**
  2447. * The symbol type. Points to a definition function in
  2448. * the `Highcharts.Renderer.symbols` collection.
  2449. *
  2450. * @type {Highcharts.SymbolKeyValue}
  2451. *
  2452. * @private
  2453. */
  2454. type: 'triangle',
  2455. x: -5,
  2456. y: -5,
  2457. height: 10,
  2458. width: 10,
  2459. padding: 5
  2460. }
  2461. },
  2462. uniqueNames: false
  2463. }, userOptions, {
  2464. // Forced options
  2465. reversed: true,
  2466. // grid.columns is not supported in treegrid
  2467. grid: {
  2468. columns: void 0
  2469. }
  2470. });
  2471. }
  2472. // Now apply the original function with the original arguments,
  2473. // which are sliced off this function's arguments
  2474. proceed.apply(axis, [chart, userOptions]);
  2475. if (isTreeGrid) {
  2476. axis.hasNames = true;
  2477. axis.options.showLastLabel = true;
  2478. }
  2479. }
  2480. /**
  2481. * Set the tick positions, tickInterval, axis min and max.
  2482. *
  2483. * @private
  2484. * @function Highcharts.GridAxis#setTickInterval
  2485. *
  2486. * @param {Function} proceed
  2487. * The original setTickInterval function.
  2488. */
  2489. function wrapSetTickInterval(proceed) {
  2490. var axis = this, options = axis.options, isTreeGrid = options.type === 'treegrid';
  2491. if (isTreeGrid) {
  2492. axis.min = pick(axis.userMin, options.min, axis.dataMin);
  2493. axis.max = pick(axis.userMax, options.max, axis.dataMax);
  2494. fireEvent(axis, 'foundExtremes');
  2495. // setAxisTranslation modifies the min and max according to
  2496. // axis breaks.
  2497. axis.setAxisTranslation(true);
  2498. axis.tickmarkOffset = 0.5;
  2499. axis.tickInterval = 1;
  2500. axis.tickPositions = axis.treeGrid.mapOfPosToGridNode ?
  2501. axis.treeGrid.getTickPositions() :
  2502. [];
  2503. }
  2504. else {
  2505. proceed.apply(axis, Array.prototype.slice.call(arguments, 1));
  2506. }
  2507. }
  2508. /* *
  2509. *
  2510. * Classes
  2511. *
  2512. * */
  2513. /**
  2514. * @private
  2515. * @class
  2516. */
  2517. var Additions = /** @class */ (function () {
  2518. /* *
  2519. *
  2520. * Constructors
  2521. *
  2522. * */
  2523. /**
  2524. * @private
  2525. */
  2526. function Additions(axis) {
  2527. this.axis = axis;
  2528. }
  2529. /* *
  2530. *
  2531. * Functions
  2532. *
  2533. * */
  2534. /**
  2535. * Calculates the new axis breaks to collapse a node.
  2536. *
  2537. * @private
  2538. *
  2539. * @param {Highcharts.Axis} axis
  2540. * The axis to check against.
  2541. *
  2542. * @param {Highcharts.GridNode} node
  2543. * The node to collapse.
  2544. *
  2545. * @param {number} pos
  2546. * The tick position to collapse.
  2547. *
  2548. * @return {Array<object>}
  2549. * Returns an array of the new breaks for the axis.
  2550. */
  2551. Additions.prototype.collapse = function (node) {
  2552. var axis = this.axis, breaks = (axis.options.breaks || []), obj = getBreakFromNode(node, axis.max);
  2553. breaks.push(obj);
  2554. return breaks;
  2555. };
  2556. /**
  2557. * Calculates the new axis breaks to expand a node.
  2558. *
  2559. * @private
  2560. *
  2561. * @param {Highcharts.Axis} axis
  2562. * The axis to check against.
  2563. *
  2564. * @param {Highcharts.GridNode} node
  2565. * The node to expand.
  2566. *
  2567. * @param {number} pos
  2568. * The tick position to expand.
  2569. *
  2570. * @return {Array<object>}
  2571. * Returns an array of the new breaks for the axis.
  2572. */
  2573. Additions.prototype.expand = function (node) {
  2574. var axis = this.axis, breaks = (axis.options.breaks || []), obj = getBreakFromNode(node, axis.max);
  2575. // Remove the break from the axis breaks array.
  2576. return breaks.reduce(function (arr, b) {
  2577. if (b.to !== obj.to || b.from !== obj.from) {
  2578. arr.push(b);
  2579. }
  2580. return arr;
  2581. }, []);
  2582. };
  2583. /**
  2584. * Creates a list of positions for the ticks on the axis. Filters out
  2585. * positions that are outside min and max, or is inside an axis break.
  2586. *
  2587. * @private
  2588. *
  2589. * @return {Array<number>}
  2590. * List of positions.
  2591. */
  2592. Additions.prototype.getTickPositions = function () {
  2593. var axis = this.axis;
  2594. return Object.keys(axis.treeGrid.mapOfPosToGridNode || {}).reduce(function (arr, key) {
  2595. var pos = +key;
  2596. if (axis.min <= pos &&
  2597. axis.max >= pos &&
  2598. !(axis.brokenAxis && axis.brokenAxis.isInAnyBreak(pos))) {
  2599. arr.push(pos);
  2600. }
  2601. return arr;
  2602. }, []);
  2603. };
  2604. /**
  2605. * Check if a node is collapsed.
  2606. *
  2607. * @private
  2608. *
  2609. * @param {Highcharts.Axis} axis
  2610. * The axis to check against.
  2611. *
  2612. * @param {object} node
  2613. * The node to check if is collapsed.
  2614. *
  2615. * @param {number} pos
  2616. * The tick position to collapse.
  2617. *
  2618. * @return {boolean}
  2619. * Returns true if collapsed, false if expanded.
  2620. */
  2621. Additions.prototype.isCollapsed = function (node) {
  2622. var axis = this.axis, breaks = (axis.options.breaks || []), obj = getBreakFromNode(node, axis.max);
  2623. return breaks.some(function (b) {
  2624. return b.from === obj.from && b.to === obj.to;
  2625. });
  2626. };
  2627. /**
  2628. * Calculates the new axis breaks after toggling the collapse/expand
  2629. * state of a node. If it is collapsed it will be expanded, and if it is
  2630. * exapended it will be collapsed.
  2631. *
  2632. * @private
  2633. *
  2634. * @param {Highcharts.Axis} axis
  2635. * The axis to check against.
  2636. *
  2637. * @param {Highcharts.GridNode} node
  2638. * The node to toggle.
  2639. *
  2640. * @return {Array<object>}
  2641. * Returns an array of the new breaks for the axis.
  2642. */
  2643. Additions.prototype.toggleCollapse = function (node) {
  2644. return (this.isCollapsed(node) ?
  2645. this.expand(node) :
  2646. this.collapse(node));
  2647. };
  2648. return Additions;
  2649. }());
  2650. TreeGridAxis.Additions = Additions;
  2651. })(TreeGridAxis || (TreeGridAxis = {}));
  2652. // Make utility functions available for testing.
  2653. Axis.prototype.utils = {
  2654. getNode: Tree.getNode
  2655. };
  2656. TreeGridAxis.compose(Axis);
  2657. return TreeGridAxis;
  2658. });
  2659. _registerModule(_modules, 'masters/modules/treegrid.src.js', [], function () {
  2660. });
  2661. }));