StockToolsGui.js 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372
  1. /* *
  2. *
  3. * GUI generator for Stock tools
  4. *
  5. * (c) 2009-2021 Sebastian Bochan
  6. *
  7. * License: www.highcharts.com/license
  8. *
  9. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  10. *
  11. * */
  12. import Chart from '../Core/Chart/Chart.js';
  13. import H from '../Core/Globals.js';
  14. import NavigationBindings from '../Extensions/Annotations/NavigationBindings.js';
  15. import O from '../Core/Options.js';
  16. var setOptions = O.setOptions;
  17. import U from '../Core/Utilities.js';
  18. var addEvent = U.addEvent, createElement = U.createElement, css = U.css, extend = U.extend, fireEvent = U.fireEvent, getStyle = U.getStyle, isArray = U.isArray, merge = U.merge, pick = U.pick;
  19. var DIV = 'div', SPAN = 'span', UL = 'ul', LI = 'li', PREFIX = 'highcharts-', activeClass = PREFIX + 'active';
  20. setOptions({
  21. /**
  22. * @optionparent lang
  23. */
  24. lang: {
  25. /**
  26. * Configure the stockTools GUI titles(hints) in the chart. Requires
  27. * the `stock-tools.js` module to be loaded.
  28. *
  29. * @product highstock
  30. * @since 7.0.0
  31. */
  32. stockTools: {
  33. gui: {
  34. // Main buttons:
  35. simpleShapes: 'Simple shapes',
  36. lines: 'Lines',
  37. crookedLines: 'Crooked lines',
  38. measure: 'Measure',
  39. advanced: 'Advanced',
  40. toggleAnnotations: 'Toggle annotations',
  41. verticalLabels: 'Vertical labels',
  42. flags: 'Flags',
  43. zoomChange: 'Zoom change',
  44. typeChange: 'Type change',
  45. saveChart: 'Save chart',
  46. indicators: 'Indicators',
  47. currentPriceIndicator: 'Current Price Indicators',
  48. // Other features:
  49. zoomX: 'Zoom X',
  50. zoomY: 'Zoom Y',
  51. zoomXY: 'Zooom XY',
  52. fullScreen: 'Fullscreen',
  53. typeOHLC: 'OHLC',
  54. typeLine: 'Line',
  55. typeCandlestick: 'Candlestick',
  56. // Basic shapes:
  57. circle: 'Circle',
  58. label: 'Label',
  59. rectangle: 'Rectangle',
  60. // Flags:
  61. flagCirclepin: 'Flag circle',
  62. flagDiamondpin: 'Flag diamond',
  63. flagSquarepin: 'Flag square',
  64. flagSimplepin: 'Flag simple',
  65. // Measures:
  66. measureXY: 'Measure XY',
  67. measureX: 'Measure X',
  68. measureY: 'Measure Y',
  69. // Segment, ray and line:
  70. segment: 'Segment',
  71. arrowSegment: 'Arrow segment',
  72. ray: 'Ray',
  73. arrowRay: 'Arrow ray',
  74. line: 'Line',
  75. arrowLine: 'Arrow line',
  76. horizontalLine: 'Horizontal line',
  77. verticalLine: 'Vertical line',
  78. infinityLine: 'Infinity line',
  79. // Crooked lines:
  80. crooked3: 'Crooked 3 line',
  81. crooked5: 'Crooked 5 line',
  82. elliott3: 'Elliott 3 line',
  83. elliott5: 'Elliott 5 line',
  84. // Counters:
  85. verticalCounter: 'Vertical counter',
  86. verticalLabel: 'Vertical label',
  87. verticalArrow: 'Vertical arrow',
  88. // Advanced:
  89. fibonacci: 'Fibonacci',
  90. pitchfork: 'Pitchfork',
  91. parallelChannel: 'Parallel channel'
  92. }
  93. },
  94. navigation: {
  95. popup: {
  96. // Annotations:
  97. circle: 'Circle',
  98. rectangle: 'Rectangle',
  99. label: 'Label',
  100. segment: 'Segment',
  101. arrowSegment: 'Arrow segment',
  102. ray: 'Ray',
  103. arrowRay: 'Arrow ray',
  104. line: 'Line',
  105. arrowLine: 'Arrow line',
  106. horizontalLine: 'Horizontal line',
  107. verticalLine: 'Vertical line',
  108. crooked3: 'Crooked 3 line',
  109. crooked5: 'Crooked 5 line',
  110. elliott3: 'Elliott 3 line',
  111. elliott5: 'Elliott 5 line',
  112. verticalCounter: 'Vertical counter',
  113. verticalLabel: 'Vertical label',
  114. verticalArrow: 'Vertical arrow',
  115. fibonacci: 'Fibonacci',
  116. pitchfork: 'Pitchfork',
  117. parallelChannel: 'Parallel channel',
  118. infinityLine: 'Infinity line',
  119. measure: 'Measure',
  120. measureXY: 'Measure XY',
  121. measureX: 'Measure X',
  122. measureY: 'Measure Y',
  123. // Flags:
  124. flags: 'Flags',
  125. // GUI elements:
  126. addButton: 'add',
  127. saveButton: 'save',
  128. editButton: 'edit',
  129. removeButton: 'remove',
  130. series: 'Series',
  131. volume: 'Volume',
  132. connector: 'Connector',
  133. // Field names:
  134. innerBackground: 'Inner background',
  135. outerBackground: 'Outer background',
  136. crosshairX: 'Crosshair X',
  137. crosshairY: 'Crosshair Y',
  138. tunnel: 'Tunnel',
  139. background: 'Background',
  140. // Indicators' params (#15170):
  141. index: 'Index',
  142. period: 'Period',
  143. standardDeviation: 'Standard deviation',
  144. periodTenkan: 'Tenkan period',
  145. periodSenkouSpanB: 'Senkou Span B period',
  146. periodATR: 'ATR period',
  147. multiplierATR: 'ATR multiplier',
  148. shortPeriod: 'Short period',
  149. longPeriod: 'Long period',
  150. signalPeriod: 'Signal period',
  151. decimals: 'Decimals',
  152. algorithm: 'Algorithm',
  153. topBand: 'Top band',
  154. bottomBand: 'Bottom band',
  155. initialAccelerationFactor: 'Initial acceleration factor',
  156. maxAccelerationFactor: 'Max acceleration factor',
  157. increment: 'Increment',
  158. multiplier: 'Multiplier',
  159. ranges: 'Ranges',
  160. highIndex: 'High index',
  161. lowIndex: 'Low index',
  162. deviation: 'Deviation',
  163. xAxisUnit: 'x-axis unit',
  164. factor: 'Factor',
  165. fastAvgPeriod: 'Fast average period',
  166. slowAvgPeriod: 'Slow average period',
  167. average: 'Average'
  168. }
  169. }
  170. },
  171. /**
  172. * Configure the stockTools gui strings in the chart. Requires the
  173. * [stockTools module]() to be loaded. For a description of the module
  174. * and information on its features, see [Highcharts StockTools]().
  175. *
  176. * @product highstock
  177. *
  178. * @sample stock/demo/stock-tools-gui Stock Tools GUI
  179. *
  180. * @sample stock/demo/stock-tools-custom-gui Stock Tools customized GUI
  181. *
  182. * @since 7.0.0
  183. * @optionparent stockTools
  184. */
  185. stockTools: {
  186. /**
  187. * Definitions of buttons in Stock Tools GUI.
  188. */
  189. gui: {
  190. /**
  191. * Path where Highcharts will look for icons. Change this to use
  192. * icons from a different server.
  193. *
  194. * Since 7.1.3 use [iconsURL](#navigation.iconsURL) for popup and
  195. * stock tools.
  196. *
  197. * @deprecated
  198. * @apioption stockTools.gui.iconsURL
  199. *
  200. */
  201. /**
  202. * Enable or disable the stockTools gui.
  203. */
  204. enabled: true,
  205. /**
  206. * A CSS class name to apply to the stocktools' div,
  207. * allowing unique CSS styling for each chart.
  208. */
  209. className: 'highcharts-bindings-wrapper',
  210. /**
  211. * A CSS class name to apply to the container of buttons,
  212. * allowing unique CSS styling for each chart.
  213. */
  214. toolbarClassName: 'stocktools-toolbar',
  215. /**
  216. * A collection of strings pointing to config options for the
  217. * toolbar items. Each name refers to a unique key from the
  218. * definitions object.
  219. *
  220. * @type {Array<string>}
  221. * @default [
  222. * 'indicators',
  223. * 'separator',
  224. * 'simpleShapes',
  225. * 'lines',
  226. * 'crookedLines',
  227. * 'measure',
  228. * 'advanced',
  229. * 'toggleAnnotations',
  230. * 'separator',
  231. * 'verticalLabels',
  232. * 'flags',
  233. * 'separator',
  234. * 'zoomChange',
  235. * 'fullScreen',
  236. * 'typeChange',
  237. * 'separator',
  238. * 'currentPriceIndicator',
  239. * 'saveChart'
  240. * ]
  241. */
  242. buttons: [
  243. 'indicators',
  244. 'separator',
  245. 'simpleShapes',
  246. 'lines',
  247. 'crookedLines',
  248. 'measure',
  249. 'advanced',
  250. 'toggleAnnotations',
  251. 'separator',
  252. 'verticalLabels',
  253. 'flags',
  254. 'separator',
  255. 'zoomChange',
  256. 'fullScreen',
  257. 'typeChange',
  258. 'separator',
  259. 'currentPriceIndicator',
  260. 'saveChart'
  261. ],
  262. /**
  263. * An options object of the buttons definitions. Each name refers to
  264. * unique key from buttons array.
  265. */
  266. definitions: {
  267. separator: {
  268. /**
  269. * A predefined background symbol for the button.
  270. */
  271. symbol: 'separator.svg'
  272. },
  273. simpleShapes: {
  274. /**
  275. * A collection of strings pointing to config options for
  276. * the items.
  277. *
  278. * @type {array}
  279. * @default [
  280. * 'label',
  281. * 'circle',
  282. * 'rectangle'
  283. * ]
  284. *
  285. */
  286. items: [
  287. 'label',
  288. 'circle',
  289. 'rectangle'
  290. ],
  291. circle: {
  292. /**
  293. * A predefined background symbol for the button.
  294. *
  295. * @type {string}
  296. *
  297. */
  298. symbol: 'circle.svg'
  299. },
  300. rectangle: {
  301. /**
  302. * A predefined background symbol for the button.
  303. *
  304. * @type {string}
  305. *
  306. */
  307. symbol: 'rectangle.svg'
  308. },
  309. label: {
  310. /**
  311. * A predefined background symbol for the button.
  312. *
  313. * @type {string}
  314. *
  315. */
  316. symbol: 'label.svg'
  317. }
  318. },
  319. flags: {
  320. /**
  321. * A collection of strings pointing to config options for
  322. * the items.
  323. *
  324. * @type {array}
  325. * @default [
  326. * 'flagCirclepin',
  327. * 'flagDiamondpin',
  328. * 'flagSquarepin',
  329. * 'flagSimplepin'
  330. * ]
  331. *
  332. */
  333. items: [
  334. 'flagCirclepin',
  335. 'flagDiamondpin',
  336. 'flagSquarepin',
  337. 'flagSimplepin'
  338. ],
  339. flagSimplepin: {
  340. /**
  341. * A predefined background symbol for the button.
  342. *
  343. * @type {string}
  344. *
  345. */
  346. symbol: 'flag-basic.svg'
  347. },
  348. flagDiamondpin: {
  349. /**
  350. * A predefined background symbol for the button.
  351. *
  352. * @type {string}
  353. *
  354. */
  355. symbol: 'flag-diamond.svg'
  356. },
  357. flagSquarepin: {
  358. /**
  359. * A predefined background symbol for the button.
  360. *
  361. * @type {string}
  362. */
  363. symbol: 'flag-trapeze.svg'
  364. },
  365. flagCirclepin: {
  366. /**
  367. * A predefined background symbol for the button.
  368. *
  369. * @type {string}
  370. */
  371. symbol: 'flag-elipse.svg'
  372. }
  373. },
  374. lines: {
  375. /**
  376. * A collection of strings pointing to config options for
  377. * the items.
  378. *
  379. * @type {array}
  380. * @default [
  381. * 'segment',
  382. * 'arrowSegment',
  383. * 'ray',
  384. * 'arrowRay',
  385. * 'line',
  386. * 'arrowLine',
  387. * 'horizontalLine',
  388. * 'verticalLine'
  389. * ]
  390. */
  391. items: [
  392. 'segment',
  393. 'arrowSegment',
  394. 'ray',
  395. 'arrowRay',
  396. 'line',
  397. 'arrowLine',
  398. 'horizontalLine',
  399. 'verticalLine'
  400. ],
  401. segment: {
  402. /**
  403. * A predefined background symbol for the button.
  404. *
  405. * @type {string}
  406. */
  407. symbol: 'segment.svg'
  408. },
  409. arrowSegment: {
  410. /**
  411. * A predefined background symbol for the button.
  412. *
  413. * @type {string}
  414. */
  415. symbol: 'arrow-segment.svg'
  416. },
  417. ray: {
  418. /**
  419. * A predefined background symbol for the button.
  420. *
  421. * @type {string}
  422. */
  423. symbol: 'ray.svg'
  424. },
  425. arrowRay: {
  426. /**
  427. * A predefined background symbol for the button.
  428. *
  429. * @type {string}
  430. */
  431. symbol: 'arrow-ray.svg'
  432. },
  433. line: {
  434. /**
  435. * A predefined background symbol for the button.
  436. *
  437. * @type {string}
  438. */
  439. symbol: 'line.svg'
  440. },
  441. arrowLine: {
  442. /**
  443. * A predefined background symbol for the button.
  444. *
  445. * @type {string}
  446. */
  447. symbol: 'arrow-line.svg'
  448. },
  449. verticalLine: {
  450. /**
  451. * A predefined background symbol for the button.
  452. *
  453. * @type {string}
  454. */
  455. symbol: 'vertical-line.svg'
  456. },
  457. horizontalLine: {
  458. /**
  459. * A predefined background symbol for the button.
  460. *
  461. * @type {string}
  462. */
  463. symbol: 'horizontal-line.svg'
  464. }
  465. },
  466. crookedLines: {
  467. /**
  468. * A collection of strings pointing to config options for
  469. * the items.
  470. *
  471. * @type {array}
  472. * @default [
  473. * 'elliott3',
  474. * 'elliott5',
  475. * 'crooked3',
  476. * 'crooked5'
  477. * ]
  478. *
  479. */
  480. items: [
  481. 'elliott3',
  482. 'elliott5',
  483. 'crooked3',
  484. 'crooked5'
  485. ],
  486. crooked3: {
  487. /**
  488. * A predefined background symbol for the button.
  489. *
  490. * @type {string}
  491. */
  492. symbol: 'crooked-3.svg'
  493. },
  494. crooked5: {
  495. /**
  496. * A predefined background symbol for the button.
  497. *
  498. * @type {string}
  499. */
  500. symbol: 'crooked-5.svg'
  501. },
  502. elliott3: {
  503. /**
  504. * A predefined background symbol for the button.
  505. *
  506. * @type {string}
  507. */
  508. symbol: 'elliott-3.svg'
  509. },
  510. elliott5: {
  511. /**
  512. * A predefined background symbol for the button.
  513. *
  514. * @type {string}
  515. */
  516. symbol: 'elliott-5.svg'
  517. }
  518. },
  519. verticalLabels: {
  520. /**
  521. * A collection of strings pointing to config options for
  522. * the items.
  523. *
  524. * @type {array}
  525. * @default [
  526. * 'verticalCounter',
  527. * 'verticalLabel',
  528. * 'verticalArrow'
  529. * ]
  530. */
  531. items: [
  532. 'verticalCounter',
  533. 'verticalLabel',
  534. 'verticalArrow'
  535. ],
  536. verticalCounter: {
  537. /**
  538. * A predefined background symbol for the button.
  539. *
  540. * @type {string}
  541. */
  542. symbol: 'vertical-counter.svg'
  543. },
  544. verticalLabel: {
  545. /**
  546. * A predefined background symbol for the button.
  547. *
  548. * @type {string}
  549. */
  550. symbol: 'vertical-label.svg'
  551. },
  552. verticalArrow: {
  553. /**
  554. * A predefined background symbol for the button.
  555. *
  556. * @type {string}
  557. */
  558. symbol: 'vertical-arrow.svg'
  559. }
  560. },
  561. advanced: {
  562. /**
  563. * A collection of strings pointing to config options for
  564. * the items.
  565. *
  566. * @type {array}
  567. * @default [
  568. * 'fibonacci',
  569. * 'pitchfork',
  570. * 'parallelChannel'
  571. * ]
  572. */
  573. items: [
  574. 'fibonacci',
  575. 'pitchfork',
  576. 'parallelChannel'
  577. ],
  578. pitchfork: {
  579. /**
  580. * A predefined background symbol for the button.
  581. *
  582. * @type {string}
  583. */
  584. symbol: 'pitchfork.svg'
  585. },
  586. fibonacci: {
  587. /**
  588. * A predefined background symbol for the button.
  589. *
  590. * @type {string}
  591. */
  592. symbol: 'fibonacci.svg'
  593. },
  594. parallelChannel: {
  595. /**
  596. * A predefined background symbol for the button.
  597. *
  598. * @type {string}
  599. */
  600. symbol: 'parallel-channel.svg'
  601. }
  602. },
  603. measure: {
  604. /**
  605. * A collection of strings pointing to config options for
  606. * the items.
  607. *
  608. * @type {array}
  609. * @default [
  610. * 'measureXY',
  611. * 'measureX',
  612. * 'measureY'
  613. * ]
  614. */
  615. items: [
  616. 'measureXY',
  617. 'measureX',
  618. 'measureY'
  619. ],
  620. measureX: {
  621. /**
  622. * A predefined background symbol for the button.
  623. *
  624. * @type {string}
  625. */
  626. symbol: 'measure-x.svg'
  627. },
  628. measureY: {
  629. /**
  630. * A predefined background symbol for the button.
  631. *
  632. * @type {string}
  633. */
  634. symbol: 'measure-y.svg'
  635. },
  636. measureXY: {
  637. /**
  638. * A predefined background symbol for the button.
  639. *
  640. * @type {string}
  641. */
  642. symbol: 'measure-xy.svg'
  643. }
  644. },
  645. toggleAnnotations: {
  646. /**
  647. * A predefined background symbol for the button.
  648. *
  649. * @type {string}
  650. */
  651. symbol: 'annotations-visible.svg'
  652. },
  653. currentPriceIndicator: {
  654. /**
  655. * A predefined background symbol for the button.
  656. *
  657. * @type {string}
  658. */
  659. symbol: 'current-price-show.svg'
  660. },
  661. indicators: {
  662. /**
  663. * A predefined background symbol for the button.
  664. *
  665. * @type {string}
  666. */
  667. symbol: 'indicators.svg'
  668. },
  669. zoomChange: {
  670. /**
  671. * A collection of strings pointing to config options for
  672. * the items.
  673. *
  674. * @type {array}
  675. * @default [
  676. * 'zoomX',
  677. * 'zoomY',
  678. * 'zoomXY'
  679. * ]
  680. */
  681. items: [
  682. 'zoomX',
  683. 'zoomY',
  684. 'zoomXY'
  685. ],
  686. zoomX: {
  687. /**
  688. * A predefined background symbol for the button.
  689. *
  690. * @type {string}
  691. */
  692. symbol: 'zoom-x.svg'
  693. },
  694. zoomY: {
  695. /**
  696. * A predefined background symbol for the button.
  697. *
  698. * @type {string}
  699. */
  700. symbol: 'zoom-y.svg'
  701. },
  702. zoomXY: {
  703. /**
  704. * A predefined background symbol for the button.
  705. *
  706. * @type {string}
  707. */
  708. symbol: 'zoom-xy.svg'
  709. }
  710. },
  711. typeChange: {
  712. /**
  713. * A collection of strings pointing to config options for
  714. * the items.
  715. *
  716. * @type {array}
  717. * @default [
  718. * 'typeOHLC',
  719. * 'typeLine',
  720. * 'typeCandlestick'
  721. * ]
  722. */
  723. items: [
  724. 'typeOHLC',
  725. 'typeLine',
  726. 'typeCandlestick'
  727. ],
  728. typeOHLC: {
  729. /**
  730. * A predefined background symbol for the button.
  731. *
  732. * @type {string}
  733. */
  734. symbol: 'series-ohlc.svg'
  735. },
  736. typeLine: {
  737. /**
  738. * A predefined background symbol for the button.
  739. *
  740. * @type {string}
  741. */
  742. symbol: 'series-line.svg'
  743. },
  744. typeCandlestick: {
  745. /**
  746. * A predefined background symbol for the button.
  747. *
  748. * @type {string}
  749. */
  750. symbol: 'series-candlestick.svg'
  751. }
  752. },
  753. fullScreen: {
  754. /**
  755. * A predefined background symbol for the button.
  756. *
  757. * @type {string}
  758. */
  759. symbol: 'fullscreen.svg'
  760. },
  761. saveChart: {
  762. /**
  763. * A predefined background symbol for the button.
  764. *
  765. * @type {string}
  766. */
  767. symbol: 'save-chart.svg'
  768. }
  769. }
  770. }
  771. }
  772. });
  773. /* eslint-disable no-invalid-this, valid-jsdoc */
  774. // Run HTML generator
  775. addEvent(Chart, 'afterGetContainer', function () {
  776. this.setStockTools();
  777. });
  778. addEvent(Chart, 'getMargins', function () {
  779. var listWrapper = this.stockTools && this.stockTools.listWrapper, offsetWidth = listWrapper && ((listWrapper.startWidth +
  780. getStyle(listWrapper, 'padding-left') +
  781. getStyle(listWrapper, 'padding-right')) || listWrapper.offsetWidth);
  782. if (offsetWidth && offsetWidth < this.plotWidth) {
  783. this.plotLeft += offsetWidth;
  784. this.spacing[3] += offsetWidth;
  785. }
  786. }, {
  787. order: 0
  788. });
  789. ['beforeRender', 'beforeRedraw'].forEach(function (event) {
  790. addEvent(Chart, event, function () {
  791. if (this.stockTools) {
  792. var optionsChart = this.options.chart;
  793. var listWrapper = this.stockTools.listWrapper, offsetWidth = listWrapper && ((listWrapper.startWidth +
  794. getStyle(listWrapper, 'padding-left') +
  795. getStyle(listWrapper, 'padding-right')) || listWrapper.offsetWidth);
  796. var dirty = false;
  797. if (offsetWidth && offsetWidth < this.plotWidth) {
  798. var nextX = pick(optionsChart.spacingLeft, optionsChart.spacing && optionsChart.spacing[3], 0) + offsetWidth;
  799. var diff = nextX - this.spacingBox.x;
  800. this.spacingBox.x = nextX;
  801. this.spacingBox.width -= diff;
  802. dirty = true;
  803. }
  804. else if (offsetWidth === 0) {
  805. dirty = true;
  806. }
  807. if (offsetWidth !== this.stockTools.prevOffsetWidth) {
  808. this.stockTools.prevOffsetWidth = offsetWidth;
  809. if (dirty) {
  810. this.isDirtyLegend = true;
  811. }
  812. }
  813. }
  814. });
  815. });
  816. addEvent(Chart, 'destroy', function () {
  817. if (this.stockTools) {
  818. this.stockTools.destroy();
  819. }
  820. });
  821. addEvent(Chart, 'redraw', function () {
  822. if (this.stockTools && this.stockTools.guiEnabled) {
  823. this.stockTools.redraw();
  824. }
  825. });
  826. /**
  827. * Toolbar Class
  828. * @private
  829. * @constructor
  830. * @param {Object} - options of toolbar
  831. * @param {Chart} - Reference to chart
  832. */
  833. var Toolbar = /** @class */ (function () {
  834. function Toolbar(options, langOptions, chart) {
  835. this.arrowDown = void 0;
  836. this.arrowUp = void 0;
  837. this.arrowWrapper = void 0;
  838. this.listWrapper = void 0;
  839. this.showhideBtn = void 0;
  840. this.submenu = void 0;
  841. this.toolbar = void 0;
  842. this.wrapper = void 0;
  843. this.chart = chart;
  844. this.options = options;
  845. this.lang = langOptions;
  846. // set url for icons.
  847. this.iconsURL = this.getIconsURL();
  848. this.guiEnabled = options.enabled;
  849. this.visible = pick(options.visible, true);
  850. this.placed = pick(options.placed, false);
  851. // General events collection which should be removed upon
  852. // destroy/update:
  853. this.eventsToUnbind = [];
  854. if (this.guiEnabled) {
  855. this.createHTML();
  856. this.init();
  857. this.showHideNavigatorion();
  858. }
  859. fireEvent(this, 'afterInit');
  860. }
  861. /**
  862. * Initialize the toolbar. Create buttons and submenu for each option
  863. * defined in `stockTools.gui`.
  864. * @private
  865. */
  866. Toolbar.prototype.init = function () {
  867. var _self = this, lang = this.lang, guiOptions = this.options, toolbar = this.toolbar, addSubmenu = _self.addSubmenu, buttons = guiOptions.buttons, defs = guiOptions.definitions, allButtons = toolbar.childNodes, button;
  868. // create buttons
  869. buttons.forEach(function (btnName) {
  870. button = _self.addButton(toolbar, defs, btnName, lang);
  871. _self.eventsToUnbind.push(addEvent(button.buttonWrapper, 'click', function () {
  872. _self.eraseActiveButtons(allButtons, button.buttonWrapper);
  873. }));
  874. if (isArray(defs[btnName].items)) {
  875. // create submenu buttons
  876. addSubmenu.call(_self, button, defs[btnName]);
  877. }
  878. });
  879. };
  880. /**
  881. * Create submenu (list of buttons) for the option. In example main button
  882. * is Line, in submenu will be buttons with types of lines.
  883. * @private
  884. * @param {Highcharts.Dictionary<Highcharts.HTMLDOMElement>}
  885. * button which has submenu
  886. * @param {Highcharts.StockToolsGuiDefinitionsButtonsOptions}
  887. * list of all buttons
  888. */
  889. Toolbar.prototype.addSubmenu = function (parentBtn, button) {
  890. var _self = this, submenuArrow = parentBtn.submenuArrow, buttonWrapper = parentBtn.buttonWrapper, buttonWidth = getStyle(buttonWrapper, 'width'), wrapper = this.wrapper, menuWrapper = this.listWrapper, allButtons = this.toolbar.childNodes, topMargin = 0, submenuWrapper;
  891. // create submenu container
  892. this.submenu = submenuWrapper = createElement(UL, {
  893. className: PREFIX + 'submenu-wrapper'
  894. }, null, buttonWrapper);
  895. // create submenu buttons and select the first one
  896. this.addSubmenuItems(buttonWrapper, button);
  897. // show / hide submenu
  898. _self.eventsToUnbind.push(addEvent(submenuArrow, 'click', function (e) {
  899. e.stopPropagation();
  900. // Erase active class on all other buttons
  901. _self.eraseActiveButtons(allButtons, buttonWrapper);
  902. // hide menu
  903. if (buttonWrapper.className.indexOf(PREFIX + 'current') >= 0) {
  904. menuWrapper.style.width =
  905. menuWrapper.startWidth + 'px';
  906. buttonWrapper.classList.remove(PREFIX + 'current');
  907. submenuWrapper.style.display = 'none';
  908. }
  909. else {
  910. // show menu
  911. // to calculate height of element
  912. submenuWrapper.style.display = 'block';
  913. topMargin = submenuWrapper.offsetHeight -
  914. buttonWrapper.offsetHeight - 3;
  915. // calculate position of submenu in the box
  916. // if submenu is inside, reset top margin
  917. if (
  918. // cut on the bottom
  919. !(submenuWrapper.offsetHeight +
  920. buttonWrapper.offsetTop >
  921. wrapper.offsetHeight &&
  922. // cut on the top
  923. buttonWrapper.offsetTop > topMargin)) {
  924. topMargin = 0;
  925. }
  926. // apply calculated styles
  927. css(submenuWrapper, {
  928. top: -topMargin + 'px',
  929. left: buttonWidth + 3 + 'px'
  930. });
  931. buttonWrapper.className += ' ' + PREFIX + 'current';
  932. menuWrapper.startWidth = wrapper.offsetWidth;
  933. menuWrapper.style.width = menuWrapper.startWidth +
  934. getStyle(menuWrapper, 'padding-left') +
  935. submenuWrapper.offsetWidth + 3 + 'px';
  936. }
  937. }));
  938. };
  939. /**
  940. * Create buttons in submenu
  941. * @private
  942. * @param {Highcharts.HTMLDOMElement}
  943. * button where submenu is placed
  944. * @param {Highcharts.StockToolsGuiDefinitionsButtonsOptions}
  945. * list of all buttons options
  946. *
  947. */
  948. Toolbar.prototype.addSubmenuItems = function (buttonWrapper, button) {
  949. var _self = this, submenuWrapper = this.submenu, lang = this.lang, menuWrapper = this.listWrapper, items = button.items, firstSubmenuItem, submenuBtn;
  950. // add items to submenu
  951. items.forEach(function (btnName) {
  952. // add buttons to submenu
  953. submenuBtn = _self.addButton(submenuWrapper, button, btnName, lang);
  954. _self.eventsToUnbind.push(addEvent(submenuBtn.mainButton, 'click', function () {
  955. _self.switchSymbol(this, buttonWrapper, true);
  956. menuWrapper.style.width =
  957. menuWrapper.startWidth + 'px';
  958. submenuWrapper.style.display = 'none';
  959. }));
  960. });
  961. // select first submenu item
  962. firstSubmenuItem = submenuWrapper
  963. .querySelectorAll('li > .' + PREFIX + 'menu-item-btn')[0];
  964. // replace current symbol, in main button, with submenu's button style
  965. _self.switchSymbol(firstSubmenuItem, false);
  966. };
  967. /*
  968. * Erase active class on all other buttons.
  969. *
  970. * @param {Array} - Array of HTML buttons
  971. * @param {HTMLDOMElement} - Current HTML button
  972. *
  973. */
  974. Toolbar.prototype.eraseActiveButtons = function (buttons, currentButton, submenuItems) {
  975. [].forEach.call(buttons, function (btn) {
  976. if (btn !== currentButton) {
  977. btn.classList.remove(PREFIX + 'current');
  978. btn.classList.remove(PREFIX + 'active');
  979. submenuItems =
  980. btn.querySelectorAll('.' + PREFIX + 'submenu-wrapper');
  981. // hide submenu
  982. if (submenuItems.length > 0) {
  983. submenuItems[0].style.display = 'none';
  984. }
  985. }
  986. });
  987. };
  988. /**
  989. * Create single button. Consist of HTML elements `li`, `span`, and (if
  990. * exists) submenu container.
  991. * @private
  992. * @param {Highcharts.HTMLDOMElement} target
  993. * HTML reference, where button should be added
  994. * @param {Highcharts.StockToolsGuiDefinitionsButtonsOptions|Highcharts.StockToolsGuiDefinitionsOptions} options
  995. * All options, by btnName refer to particular button
  996. * @param {string} btnName
  997. * of functionality mapped for specific class
  998. * @param {Highcharts.Dictionary<string>} lang
  999. * All titles, by btnName refer to particular button
  1000. * @return {Object} - references to all created HTML elements
  1001. */
  1002. Toolbar.prototype.addButton = function (target, options, btnName, lang) {
  1003. if (lang === void 0) { lang = {}; }
  1004. var btnOptions = options[btnName], items = btnOptions.items, classMapping = Toolbar.prototype.classMapping, userClassName = btnOptions.className || '', mainButton, submenuArrow, buttonWrapper;
  1005. // main button wrapper
  1006. buttonWrapper = createElement(LI, {
  1007. className: pick(classMapping[btnName], '') + ' ' + userClassName,
  1008. title: lang[btnName] || btnName
  1009. }, null, target);
  1010. // single button
  1011. mainButton = createElement(SPAN, {
  1012. className: PREFIX + 'menu-item-btn'
  1013. }, null, buttonWrapper);
  1014. // submenu
  1015. if (items && items.length) {
  1016. // arrow is a hook to show / hide submenu
  1017. submenuArrow = createElement(SPAN, {
  1018. className: PREFIX + 'submenu-item-arrow ' +
  1019. PREFIX + 'arrow-right'
  1020. }, null, buttonWrapper);
  1021. submenuArrow.style['background-image'] = 'url(' +
  1022. this.iconsURL + 'arrow-bottom.svg)';
  1023. }
  1024. else {
  1025. mainButton.style['background-image'] = 'url(' +
  1026. this.iconsURL + btnOptions.symbol + ')';
  1027. }
  1028. return {
  1029. buttonWrapper: buttonWrapper,
  1030. mainButton: mainButton,
  1031. submenuArrow: submenuArrow
  1032. };
  1033. };
  1034. /*
  1035. * Create navigation's HTML elements: container and arrows.
  1036. *
  1037. */
  1038. Toolbar.prototype.addNavigation = function () {
  1039. var stockToolbar = this, wrapper = stockToolbar.wrapper;
  1040. // arrow wrapper
  1041. stockToolbar.arrowWrapper = createElement(DIV, {
  1042. className: PREFIX + 'arrow-wrapper'
  1043. });
  1044. stockToolbar.arrowUp = createElement(DIV, {
  1045. className: PREFIX + 'arrow-up'
  1046. }, null, stockToolbar.arrowWrapper);
  1047. stockToolbar.arrowUp.style['background-image'] =
  1048. 'url(' + this.iconsURL + 'arrow-right.svg)';
  1049. stockToolbar.arrowDown = createElement(DIV, {
  1050. className: PREFIX + 'arrow-down'
  1051. }, null, stockToolbar.arrowWrapper);
  1052. stockToolbar.arrowDown.style['background-image'] =
  1053. 'url(' + this.iconsURL + 'arrow-right.svg)';
  1054. wrapper.insertBefore(stockToolbar.arrowWrapper, wrapper.childNodes[0]);
  1055. // attach scroll events
  1056. stockToolbar.scrollButtons();
  1057. };
  1058. /*
  1059. * Add events to navigation (two arrows) which allows user to scroll
  1060. * top/down GUI buttons, if container's height is not enough.
  1061. *
  1062. */
  1063. Toolbar.prototype.scrollButtons = function () {
  1064. var targetY = 0, _self = this, wrapper = _self.wrapper, toolbar = _self.toolbar, step = 0.1 * wrapper.offsetHeight; // 0.1 = 10%
  1065. _self.eventsToUnbind.push(addEvent(_self.arrowUp, 'click', function () {
  1066. if (targetY > 0) {
  1067. targetY -= step;
  1068. toolbar.style['margin-top'] = -targetY + 'px';
  1069. }
  1070. }));
  1071. _self.eventsToUnbind.push(addEvent(_self.arrowDown, 'click', function () {
  1072. if (wrapper.offsetHeight + targetY <=
  1073. toolbar.offsetHeight + step) {
  1074. targetY += step;
  1075. toolbar.style['margin-top'] = -targetY + 'px';
  1076. }
  1077. }));
  1078. };
  1079. /*
  1080. * Create stockTools HTML main elements.
  1081. *
  1082. */
  1083. Toolbar.prototype.createHTML = function () {
  1084. var stockToolbar = this, chart = stockToolbar.chart, guiOptions = stockToolbar.options, container = chart.container, navigation = chart.options.navigation, bindingsClassName = navigation && navigation.bindingsClassName, listWrapper, toolbar, wrapper;
  1085. // create main container
  1086. stockToolbar.wrapper = wrapper = createElement(DIV, {
  1087. className: PREFIX + 'stocktools-wrapper ' +
  1088. guiOptions.className + ' ' + bindingsClassName
  1089. });
  1090. container.parentNode.insertBefore(wrapper, container);
  1091. // toolbar
  1092. stockToolbar.toolbar = toolbar = createElement(UL, {
  1093. className: PREFIX + 'stocktools-toolbar ' +
  1094. guiOptions.toolbarClassName
  1095. });
  1096. // add container for list of buttons
  1097. stockToolbar.listWrapper = listWrapper = createElement(DIV, {
  1098. className: PREFIX + 'menu-wrapper'
  1099. });
  1100. wrapper.insertBefore(listWrapper, wrapper.childNodes[0]);
  1101. listWrapper.insertBefore(toolbar, listWrapper.childNodes[0]);
  1102. stockToolbar.showHideToolbar();
  1103. // add navigation which allows user to scroll down / top GUI buttons
  1104. stockToolbar.addNavigation();
  1105. };
  1106. /**
  1107. * Function called in redraw verifies if the navigation should be visible.
  1108. * @private
  1109. */
  1110. Toolbar.prototype.showHideNavigatorion = function () {
  1111. // arrows
  1112. // 50px space for arrows
  1113. if (this.visible &&
  1114. this.toolbar.offsetHeight > (this.wrapper.offsetHeight - 50)) {
  1115. this.arrowWrapper.style.display = 'block';
  1116. }
  1117. else {
  1118. // reset margin if whole toolbar is visible
  1119. this.toolbar.style.marginTop = '0px';
  1120. // hide arrows
  1121. this.arrowWrapper.style.display = 'none';
  1122. }
  1123. };
  1124. /**
  1125. * Create button which shows or hides GUI toolbar.
  1126. * @private
  1127. */
  1128. Toolbar.prototype.showHideToolbar = function () {
  1129. var stockToolbar = this, chart = this.chart, wrapper = stockToolbar.wrapper, toolbar = this.listWrapper, submenu = this.submenu, visible = this.visible, showhideBtn;
  1130. // Show hide toolbar
  1131. this.showhideBtn = showhideBtn = createElement(DIV, {
  1132. className: PREFIX + 'toggle-toolbar ' + PREFIX + 'arrow-left'
  1133. }, null, wrapper);
  1134. showhideBtn.style['background-image'] =
  1135. 'url(' + this.iconsURL + 'arrow-right.svg)';
  1136. if (!visible) {
  1137. // hide
  1138. if (submenu) {
  1139. submenu.style.display = 'none';
  1140. }
  1141. showhideBtn.style.left = '0px';
  1142. stockToolbar.visible = visible = false;
  1143. toolbar.classList.add(PREFIX + 'hide');
  1144. showhideBtn.classList.toggle(PREFIX + 'arrow-right');
  1145. wrapper.style.height = showhideBtn.offsetHeight + 'px';
  1146. }
  1147. else {
  1148. wrapper.style.height = '100%';
  1149. showhideBtn.style.top = getStyle(toolbar, 'padding-top') + 'px';
  1150. showhideBtn.style.left = (wrapper.offsetWidth +
  1151. getStyle(toolbar, 'padding-left')) + 'px';
  1152. }
  1153. // Toggle menu
  1154. stockToolbar.eventsToUnbind.push(addEvent(showhideBtn, 'click', function () {
  1155. chart.update({
  1156. stockTools: {
  1157. gui: {
  1158. visible: !visible,
  1159. placed: true
  1160. }
  1161. }
  1162. });
  1163. }));
  1164. };
  1165. /*
  1166. * In main GUI button, replace icon and class with submenu button's
  1167. * class / symbol.
  1168. *
  1169. * @param {HTMLDOMElement} - submenu button
  1170. * @param {Boolean} - true or false
  1171. *
  1172. */
  1173. Toolbar.prototype.switchSymbol = function (button, redraw) {
  1174. var buttonWrapper = button.parentNode, buttonWrapperClass = buttonWrapper.classList.value,
  1175. // main button in first level og GUI
  1176. mainNavButton = buttonWrapper.parentNode.parentNode;
  1177. // if the button is disabled, don't do anything
  1178. if (buttonWrapperClass.indexOf('highcharts-disabled-btn') > -1) {
  1179. return;
  1180. }
  1181. // set class
  1182. mainNavButton.className = '';
  1183. if (buttonWrapperClass) {
  1184. mainNavButton.classList.add(buttonWrapperClass.trim());
  1185. }
  1186. // set icon
  1187. mainNavButton
  1188. .querySelectorAll('.' + PREFIX + 'menu-item-btn')[0]
  1189. .style['background-image'] =
  1190. button.style['background-image'];
  1191. // set active class
  1192. if (redraw) {
  1193. this.selectButton(mainNavButton);
  1194. }
  1195. };
  1196. /*
  1197. * Set select state (active class) on button.
  1198. *
  1199. * @param {HTMLDOMElement} - button
  1200. *
  1201. */
  1202. Toolbar.prototype.selectButton = function (button) {
  1203. if (button.className.indexOf(activeClass) >= 0) {
  1204. button.classList.remove(activeClass);
  1205. }
  1206. else {
  1207. button.classList.add(activeClass);
  1208. }
  1209. };
  1210. /*
  1211. * Remove active class from all buttons except defined.
  1212. *
  1213. * @param {HTMLDOMElement} - button which should not be deactivated
  1214. *
  1215. */
  1216. Toolbar.prototype.unselectAllButtons = function (button) {
  1217. var activeButtons = button.parentNode
  1218. .querySelectorAll('.' + activeClass);
  1219. [].forEach.call(activeButtons, function (activeBtn) {
  1220. if (activeBtn !== button) {
  1221. activeBtn.classList.remove(activeClass);
  1222. }
  1223. });
  1224. };
  1225. /*
  1226. * Update GUI with given options.
  1227. *
  1228. * @param {Object} - general options for Stock Tools
  1229. */
  1230. Toolbar.prototype.update = function (options) {
  1231. merge(true, this.chart.options.stockTools, options);
  1232. this.destroy();
  1233. this.chart.setStockTools(options);
  1234. // If Stock Tools are updated, then bindings should be updated too:
  1235. if (this.chart.navigationBindings) {
  1236. this.chart.navigationBindings.update();
  1237. }
  1238. };
  1239. /**
  1240. * Destroy all HTML GUI elements.
  1241. * @private
  1242. */
  1243. Toolbar.prototype.destroy = function () {
  1244. var stockToolsDiv = this.wrapper, parent = stockToolsDiv && stockToolsDiv.parentNode;
  1245. this.eventsToUnbind.forEach(function (unbinder) {
  1246. unbinder();
  1247. });
  1248. // Remove the empty element
  1249. if (parent) {
  1250. parent.removeChild(stockToolsDiv);
  1251. }
  1252. // redraw
  1253. this.chart.isDirtyBox = true;
  1254. this.chart.redraw();
  1255. };
  1256. /**
  1257. * Redraw, GUI requires to verify if the navigation should be visible.
  1258. * @private
  1259. */
  1260. Toolbar.prototype.redraw = function () {
  1261. this.showHideNavigatorion();
  1262. };
  1263. Toolbar.prototype.getIconsURL = function () {
  1264. return this.chart.options.navigation.iconsURL ||
  1265. this.options.iconsURL ||
  1266. 'https://code.highcharts.com/9.1.0/gfx/stock-icons/';
  1267. };
  1268. return Toolbar;
  1269. }());
  1270. /**
  1271. * Mapping JSON fields to CSS classes.
  1272. * @private
  1273. */
  1274. Toolbar.prototype.classMapping = {
  1275. circle: PREFIX + 'circle-annotation',
  1276. rectangle: PREFIX + 'rectangle-annotation',
  1277. label: PREFIX + 'label-annotation',
  1278. segment: PREFIX + 'segment',
  1279. arrowSegment: PREFIX + 'arrow-segment',
  1280. ray: PREFIX + 'ray',
  1281. arrowRay: PREFIX + 'arrow-ray',
  1282. line: PREFIX + 'infinity-line',
  1283. arrowLine: PREFIX + 'arrow-infinity-line',
  1284. verticalLine: PREFIX + 'vertical-line',
  1285. horizontalLine: PREFIX + 'horizontal-line',
  1286. crooked3: PREFIX + 'crooked3',
  1287. crooked5: PREFIX + 'crooked5',
  1288. elliott3: PREFIX + 'elliott3',
  1289. elliott5: PREFIX + 'elliott5',
  1290. pitchfork: PREFIX + 'pitchfork',
  1291. fibonacci: PREFIX + 'fibonacci',
  1292. parallelChannel: PREFIX + 'parallel-channel',
  1293. measureX: PREFIX + 'measure-x',
  1294. measureY: PREFIX + 'measure-y',
  1295. measureXY: PREFIX + 'measure-xy',
  1296. verticalCounter: PREFIX + 'vertical-counter',
  1297. verticalLabel: PREFIX + 'vertical-label',
  1298. verticalArrow: PREFIX + 'vertical-arrow',
  1299. currentPriceIndicator: PREFIX + 'current-price-indicator',
  1300. indicators: PREFIX + 'indicators',
  1301. flagCirclepin: PREFIX + 'flag-circlepin',
  1302. flagDiamondpin: PREFIX + 'flag-diamondpin',
  1303. flagSquarepin: PREFIX + 'flag-squarepin',
  1304. flagSimplepin: PREFIX + 'flag-simplepin',
  1305. zoomX: PREFIX + 'zoom-x',
  1306. zoomY: PREFIX + 'zoom-y',
  1307. zoomXY: PREFIX + 'zoom-xy',
  1308. typeLine: PREFIX + 'series-type-line',
  1309. typeOHLC: PREFIX + 'series-type-ohlc',
  1310. typeCandlestick: PREFIX + 'series-type-candlestick',
  1311. fullScreen: PREFIX + 'full-screen',
  1312. toggleAnnotations: PREFIX + 'toggle-annotations',
  1313. saveChart: PREFIX + 'save-chart',
  1314. separator: PREFIX + 'separator'
  1315. };
  1316. extend(Chart.prototype, {
  1317. /**
  1318. * Verify if Toolbar should be added.
  1319. * @private
  1320. * @param {Highcharts.StockToolsOptions} - chart options
  1321. */
  1322. setStockTools: function (options) {
  1323. var chartOptions = this.options, lang = chartOptions.lang, guiOptions = merge(chartOptions.stockTools && chartOptions.stockTools.gui, options && options.gui), langOptions = lang.stockTools && lang.stockTools.gui;
  1324. this.stockTools = new Toolbar(guiOptions, langOptions, this);
  1325. if (this.stockTools.guiEnabled) {
  1326. this.isDirtyBox = true;
  1327. }
  1328. }
  1329. });
  1330. // Comunication with bindings:
  1331. addEvent(NavigationBindings, 'selectButton', function (event) {
  1332. var button = event.button, className = PREFIX + 'submenu-wrapper', gui = this.chart.stockTools;
  1333. if (gui && gui.guiEnabled) {
  1334. // Unslect other active buttons
  1335. gui.unselectAllButtons(event.button);
  1336. // If clicked on a submenu, select state for it's parent
  1337. if (button.parentNode.className.indexOf(className) >= 0) {
  1338. button = button.parentNode.parentNode;
  1339. }
  1340. // Set active class on the current button
  1341. gui.selectButton(button);
  1342. }
  1343. });
  1344. addEvent(NavigationBindings, 'deselectButton', function (event) {
  1345. var button = event.button, className = PREFIX + 'submenu-wrapper', gui = this.chart.stockTools;
  1346. if (gui && gui.guiEnabled) {
  1347. // If deselecting a button from a submenu, select state for it's parent
  1348. if (button.parentNode.className.indexOf(className) >= 0) {
  1349. button = button.parentNode.parentNode;
  1350. }
  1351. gui.selectButton(button);
  1352. }
  1353. });
  1354. // Check if the correct price indicator button is displayed, #15029.
  1355. addEvent(H.Chart, 'render', function () {
  1356. var chart = this, stockTools = chart.stockTools, button = stockTools &&
  1357. stockTools.toolbar &&
  1358. stockTools.toolbar.querySelector('.highcharts-current-price-indicator');
  1359. // Change the initial button background.
  1360. if (stockTools && chart.navigationBindings && chart.options.series && button) {
  1361. if (chart.navigationBindings.constructor.prototype.utils.isPriceIndicatorEnabled(chart.series)) {
  1362. button.firstChild.style['background-image'] =
  1363. 'url("' + stockTools.getIconsURL() + 'current-price-hide.svg")';
  1364. }
  1365. else {
  1366. button.firstChild.style['background-image'] =
  1367. 'url("' + stockTools.getIconsURL() + 'current-price-show.svg")';
  1368. }
  1369. }
  1370. });
  1371. H.Toolbar = Toolbar;
  1372. export default H.Toolbar;