StockToolsGui.js 52 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386
  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 D from '../Core/DefaultOptions.js';
  16. var setOptions = D.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. }, void 0, 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. }, void 0, target);
  1010. // single button
  1011. mainButton = createElement(SPAN, {
  1012. className: PREFIX + 'menu-item-btn'
  1013. }, void 0, 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. }, void 0, buttonWrapper);
  1021. submenuArrow.style.backgroundImage = 'url(' +
  1022. this.iconsURL + 'arrow-bottom.svg)';
  1023. }
  1024. else {
  1025. mainButton.style.backgroundImage = '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. }, void 0, stockToolbar.arrowWrapper);
  1047. stockToolbar.arrowUp.style.backgroundImage =
  1048. 'url(' + this.iconsURL + 'arrow-right.svg)';
  1049. stockToolbar.arrowDown = createElement(DIV, {
  1050. className: PREFIX + 'arrow-down'
  1051. }, void 0, stockToolbar.arrowWrapper);
  1052. stockToolbar.arrowDown.style.backgroundImage =
  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.marginTop = -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.marginTop = -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;
  1085. // create main container
  1086. var wrapper = stockToolbar.wrapper = createElement(DIV, {
  1087. className: PREFIX + 'stocktools-wrapper ' +
  1088. guiOptions.className + ' ' + bindingsClassName
  1089. });
  1090. container.appendChild(wrapper);
  1091. // Mimic event behaviour of being outside chart.container
  1092. [
  1093. 'mousemove',
  1094. 'click',
  1095. 'touchstart'
  1096. ].forEach(function (eventType) {
  1097. addEvent(wrapper, eventType, function (e) {
  1098. return e.stopPropagation();
  1099. });
  1100. });
  1101. addEvent(wrapper, 'mouseover', function (e) {
  1102. return chart.pointer.onContainerMouseLeave(e);
  1103. });
  1104. // toolbar
  1105. stockToolbar.toolbar = toolbar = createElement(UL, {
  1106. className: PREFIX + 'stocktools-toolbar ' +
  1107. guiOptions.toolbarClassName
  1108. });
  1109. // add container for list of buttons
  1110. stockToolbar.listWrapper = listWrapper = createElement(DIV, {
  1111. className: PREFIX + 'menu-wrapper'
  1112. });
  1113. wrapper.insertBefore(listWrapper, wrapper.childNodes[0]);
  1114. listWrapper.insertBefore(toolbar, listWrapper.childNodes[0]);
  1115. stockToolbar.showHideToolbar();
  1116. // add navigation which allows user to scroll down / top GUI buttons
  1117. stockToolbar.addNavigation();
  1118. };
  1119. /**
  1120. * Function called in redraw verifies if the navigation should be visible.
  1121. * @private
  1122. */
  1123. Toolbar.prototype.showHideNavigatorion = function () {
  1124. // arrows
  1125. // 50px space for arrows
  1126. if (this.visible &&
  1127. this.toolbar.offsetHeight > (this.wrapper.offsetHeight - 50)) {
  1128. this.arrowWrapper.style.display = 'block';
  1129. }
  1130. else {
  1131. // reset margin if whole toolbar is visible
  1132. this.toolbar.style.marginTop = '0px';
  1133. // hide arrows
  1134. this.arrowWrapper.style.display = 'none';
  1135. }
  1136. };
  1137. /**
  1138. * Create button which shows or hides GUI toolbar.
  1139. * @private
  1140. */
  1141. Toolbar.prototype.showHideToolbar = function () {
  1142. var stockToolbar = this, chart = this.chart, wrapper = stockToolbar.wrapper, toolbar = this.listWrapper, submenu = this.submenu, visible = this.visible, showhideBtn;
  1143. // Show hide toolbar
  1144. this.showhideBtn = showhideBtn = createElement(DIV, {
  1145. className: PREFIX + 'toggle-toolbar ' + PREFIX + 'arrow-left'
  1146. }, void 0, wrapper);
  1147. showhideBtn.style.backgroundImage =
  1148. 'url(' + this.iconsURL + 'arrow-right.svg)';
  1149. if (!visible) {
  1150. // hide
  1151. if (submenu) {
  1152. submenu.style.display = 'none';
  1153. }
  1154. showhideBtn.style.left = '0px';
  1155. stockToolbar.visible = visible = false;
  1156. toolbar.classList.add(PREFIX + 'hide');
  1157. showhideBtn.classList.toggle(PREFIX + 'arrow-right');
  1158. wrapper.style.height = showhideBtn.offsetHeight + 'px';
  1159. }
  1160. else {
  1161. wrapper.style.height = '100%';
  1162. showhideBtn.style.top = getStyle(toolbar, 'padding-top') + 'px';
  1163. showhideBtn.style.left = (wrapper.offsetWidth +
  1164. getStyle(toolbar, 'padding-left')) + 'px';
  1165. }
  1166. // Toggle menu
  1167. stockToolbar.eventsToUnbind.push(addEvent(showhideBtn, 'click', function () {
  1168. chart.update({
  1169. stockTools: {
  1170. gui: {
  1171. visible: !visible,
  1172. placed: true
  1173. }
  1174. }
  1175. });
  1176. }));
  1177. };
  1178. /*
  1179. * In main GUI button, replace icon and class with submenu button's
  1180. * class / symbol.
  1181. *
  1182. * @param {HTMLDOMElement} - submenu button
  1183. * @param {Boolean} - true or false
  1184. *
  1185. */
  1186. Toolbar.prototype.switchSymbol = function (button, redraw) {
  1187. var buttonWrapper = button.parentNode, buttonWrapperClass = buttonWrapper.classList.value,
  1188. // main button in first level og GUI
  1189. mainNavButton = buttonWrapper.parentNode.parentNode;
  1190. // if the button is disabled, don't do anything
  1191. if (buttonWrapperClass.indexOf('highcharts-disabled-btn') > -1) {
  1192. return;
  1193. }
  1194. // set class
  1195. mainNavButton.className = '';
  1196. if (buttonWrapperClass) {
  1197. mainNavButton.classList.add(buttonWrapperClass.trim());
  1198. }
  1199. // set icon
  1200. mainNavButton
  1201. .querySelectorAll('.' + PREFIX + 'menu-item-btn')[0]
  1202. .style.backgroundImage =
  1203. button.style.backgroundImage;
  1204. // set active class
  1205. if (redraw) {
  1206. this.selectButton(mainNavButton);
  1207. }
  1208. };
  1209. /*
  1210. * Set select state (active class) on button.
  1211. *
  1212. * @param {HTMLDOMElement} - button
  1213. *
  1214. */
  1215. Toolbar.prototype.selectButton = function (button) {
  1216. if (button.className.indexOf(activeClass) >= 0) {
  1217. button.classList.remove(activeClass);
  1218. }
  1219. else {
  1220. button.classList.add(activeClass);
  1221. }
  1222. };
  1223. /*
  1224. * Remove active class from all buttons except defined.
  1225. *
  1226. * @param {HTMLDOMElement} - button which should not be deactivated
  1227. *
  1228. */
  1229. Toolbar.prototype.unselectAllButtons = function (button) {
  1230. var activeButtons = button.parentNode
  1231. .querySelectorAll('.' + activeClass);
  1232. [].forEach.call(activeButtons, function (activeBtn) {
  1233. if (activeBtn !== button) {
  1234. activeBtn.classList.remove(activeClass);
  1235. }
  1236. });
  1237. };
  1238. /*
  1239. * Update GUI with given options.
  1240. *
  1241. * @param {Object} - general options for Stock Tools
  1242. */
  1243. Toolbar.prototype.update = function (options, redraw) {
  1244. merge(true, this.chart.options.stockTools, options);
  1245. this.destroy();
  1246. this.chart.setStockTools(options);
  1247. // If Stock Tools are updated, then bindings should be updated too:
  1248. if (this.chart.navigationBindings) {
  1249. this.chart.navigationBindings.update();
  1250. }
  1251. this.chart.isDirtyBox = true;
  1252. if (pick(redraw, true)) {
  1253. this.chart.redraw();
  1254. }
  1255. };
  1256. /**
  1257. * Destroy all HTML GUI elements.
  1258. * @private
  1259. */
  1260. Toolbar.prototype.destroy = function () {
  1261. var stockToolsDiv = this.wrapper, parent = stockToolsDiv && stockToolsDiv.parentNode;
  1262. this.eventsToUnbind.forEach(function (unbinder) {
  1263. unbinder();
  1264. });
  1265. // Remove the empty element
  1266. if (parent) {
  1267. parent.removeChild(stockToolsDiv);
  1268. }
  1269. };
  1270. /**
  1271. * Redraw, GUI requires to verify if the navigation should be visible.
  1272. * @private
  1273. */
  1274. Toolbar.prototype.redraw = function () {
  1275. this.showHideNavigatorion();
  1276. };
  1277. Toolbar.prototype.getIconsURL = function () {
  1278. return this.chart.options.navigation.iconsURL ||
  1279. this.options.iconsURL ||
  1280. 'https://code.highcharts.com/9.1.1/gfx/stock-icons/';
  1281. };
  1282. return Toolbar;
  1283. }());
  1284. /**
  1285. * Mapping JSON fields to CSS classes.
  1286. * @private
  1287. */
  1288. Toolbar.prototype.classMapping = {
  1289. circle: PREFIX + 'circle-annotation',
  1290. rectangle: PREFIX + 'rectangle-annotation',
  1291. label: PREFIX + 'label-annotation',
  1292. segment: PREFIX + 'segment',
  1293. arrowSegment: PREFIX + 'arrow-segment',
  1294. ray: PREFIX + 'ray',
  1295. arrowRay: PREFIX + 'arrow-ray',
  1296. line: PREFIX + 'infinity-line',
  1297. arrowLine: PREFIX + 'arrow-infinity-line',
  1298. verticalLine: PREFIX + 'vertical-line',
  1299. horizontalLine: PREFIX + 'horizontal-line',
  1300. crooked3: PREFIX + 'crooked3',
  1301. crooked5: PREFIX + 'crooked5',
  1302. elliott3: PREFIX + 'elliott3',
  1303. elliott5: PREFIX + 'elliott5',
  1304. pitchfork: PREFIX + 'pitchfork',
  1305. fibonacci: PREFIX + 'fibonacci',
  1306. parallelChannel: PREFIX + 'parallel-channel',
  1307. measureX: PREFIX + 'measure-x',
  1308. measureY: PREFIX + 'measure-y',
  1309. measureXY: PREFIX + 'measure-xy',
  1310. verticalCounter: PREFIX + 'vertical-counter',
  1311. verticalLabel: PREFIX + 'vertical-label',
  1312. verticalArrow: PREFIX + 'vertical-arrow',
  1313. currentPriceIndicator: PREFIX + 'current-price-indicator',
  1314. indicators: PREFIX + 'indicators',
  1315. flagCirclepin: PREFIX + 'flag-circlepin',
  1316. flagDiamondpin: PREFIX + 'flag-diamondpin',
  1317. flagSquarepin: PREFIX + 'flag-squarepin',
  1318. flagSimplepin: PREFIX + 'flag-simplepin',
  1319. zoomX: PREFIX + 'zoom-x',
  1320. zoomY: PREFIX + 'zoom-y',
  1321. zoomXY: PREFIX + 'zoom-xy',
  1322. typeLine: PREFIX + 'series-type-line',
  1323. typeOHLC: PREFIX + 'series-type-ohlc',
  1324. typeCandlestick: PREFIX + 'series-type-candlestick',
  1325. fullScreen: PREFIX + 'full-screen',
  1326. toggleAnnotations: PREFIX + 'toggle-annotations',
  1327. saveChart: PREFIX + 'save-chart',
  1328. separator: PREFIX + 'separator'
  1329. };
  1330. extend(Chart.prototype, {
  1331. /**
  1332. * Verify if Toolbar should be added.
  1333. * @private
  1334. * @param {Highcharts.StockToolsOptions} - chart options
  1335. */
  1336. setStockTools: function (options) {
  1337. var chartOptions = this.options, lang = chartOptions.lang, guiOptions = merge(chartOptions.stockTools && chartOptions.stockTools.gui, options && options.gui), langOptions = lang && lang.stockTools && lang.stockTools.gui;
  1338. this.stockTools = new Toolbar(guiOptions, langOptions, this);
  1339. if (this.stockTools.guiEnabled) {
  1340. this.isDirtyBox = true;
  1341. }
  1342. }
  1343. });
  1344. // Comunication with bindings:
  1345. addEvent(NavigationBindings, 'selectButton', function (event) {
  1346. var button = event.button, className = PREFIX + 'submenu-wrapper', gui = this.chart.stockTools;
  1347. if (gui && gui.guiEnabled) {
  1348. // Unslect other active buttons
  1349. gui.unselectAllButtons(event.button);
  1350. // If clicked on a submenu, select state for it's parent
  1351. if (button.parentNode.className.indexOf(className) >= 0) {
  1352. button = button.parentNode.parentNode;
  1353. }
  1354. // Set active class on the current button
  1355. gui.selectButton(button);
  1356. }
  1357. });
  1358. addEvent(NavigationBindings, 'deselectButton', function (event) {
  1359. var button = event.button, className = PREFIX + 'submenu-wrapper', gui = this.chart.stockTools;
  1360. if (gui && gui.guiEnabled) {
  1361. // If deselecting a button from a submenu, select state for it's parent
  1362. if (button.parentNode.className.indexOf(className) >= 0) {
  1363. button = button.parentNode.parentNode;
  1364. }
  1365. gui.selectButton(button);
  1366. }
  1367. });
  1368. // Check if the correct price indicator button is displayed, #15029.
  1369. addEvent(Chart, 'render', function () {
  1370. var chart = this, stockTools = chart.stockTools, button = stockTools &&
  1371. stockTools.toolbar &&
  1372. stockTools.toolbar.querySelector('.highcharts-current-price-indicator');
  1373. // Change the initial button background.
  1374. if (stockTools && chart.navigationBindings && chart.options.series && button) {
  1375. if (chart.navigationBindings.constructor.prototype.utils.isPriceIndicatorEnabled(chart.series)) {
  1376. button.firstChild.style['background-image'] =
  1377. 'url("' + stockTools.getIconsURL() + 'current-price-hide.svg")';
  1378. }
  1379. else {
  1380. button.firstChild.style['background-image'] =
  1381. 'url("' + stockTools.getIconsURL() + 'current-price-show.svg")';
  1382. }
  1383. }
  1384. });
  1385. H.Toolbar = Toolbar;
  1386. export default H.Toolbar;