123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386 |
- /* *
- *
- * GUI generator for Stock tools
- *
- * (c) 2009-2021 Sebastian Bochan
- *
- * License: www.highcharts.com/license
- *
- * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
- *
- * */
- import Chart from '../Core/Chart/Chart.js';
- import H from '../Core/Globals.js';
- import NavigationBindings from '../Extensions/Annotations/NavigationBindings.js';
- import D from '../Core/DefaultOptions.js';
- var setOptions = D.setOptions;
- import U from '../Core/Utilities.js';
- 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;
- var DIV = 'div', SPAN = 'span', UL = 'ul', LI = 'li', PREFIX = 'highcharts-', activeClass = PREFIX + 'active';
- setOptions({
- /**
- * @optionparent lang
- */
- lang: {
- /**
- * Configure the stockTools GUI titles(hints) in the chart. Requires
- * the `stock-tools.js` module to be loaded.
- *
- * @product highstock
- * @since 7.0.0
- */
- stockTools: {
- gui: {
- // Main buttons:
- simpleShapes: 'Simple shapes',
- lines: 'Lines',
- crookedLines: 'Crooked lines',
- measure: 'Measure',
- advanced: 'Advanced',
- toggleAnnotations: 'Toggle annotations',
- verticalLabels: 'Vertical labels',
- flags: 'Flags',
- zoomChange: 'Zoom change',
- typeChange: 'Type change',
- saveChart: 'Save chart',
- indicators: 'Indicators',
- currentPriceIndicator: 'Current Price Indicators',
- // Other features:
- zoomX: 'Zoom X',
- zoomY: 'Zoom Y',
- zoomXY: 'Zooom XY',
- fullScreen: 'Fullscreen',
- typeOHLC: 'OHLC',
- typeLine: 'Line',
- typeCandlestick: 'Candlestick',
- // Basic shapes:
- circle: 'Circle',
- label: 'Label',
- rectangle: 'Rectangle',
- // Flags:
- flagCirclepin: 'Flag circle',
- flagDiamondpin: 'Flag diamond',
- flagSquarepin: 'Flag square',
- flagSimplepin: 'Flag simple',
- // Measures:
- measureXY: 'Measure XY',
- measureX: 'Measure X',
- measureY: 'Measure Y',
- // Segment, ray and line:
- segment: 'Segment',
- arrowSegment: 'Arrow segment',
- ray: 'Ray',
- arrowRay: 'Arrow ray',
- line: 'Line',
- arrowLine: 'Arrow line',
- horizontalLine: 'Horizontal line',
- verticalLine: 'Vertical line',
- infinityLine: 'Infinity line',
- // Crooked lines:
- crooked3: 'Crooked 3 line',
- crooked5: 'Crooked 5 line',
- elliott3: 'Elliott 3 line',
- elliott5: 'Elliott 5 line',
- // Counters:
- verticalCounter: 'Vertical counter',
- verticalLabel: 'Vertical label',
- verticalArrow: 'Vertical arrow',
- // Advanced:
- fibonacci: 'Fibonacci',
- pitchfork: 'Pitchfork',
- parallelChannel: 'Parallel channel'
- }
- },
- navigation: {
- popup: {
- // Annotations:
- circle: 'Circle',
- rectangle: 'Rectangle',
- label: 'Label',
- segment: 'Segment',
- arrowSegment: 'Arrow segment',
- ray: 'Ray',
- arrowRay: 'Arrow ray',
- line: 'Line',
- arrowLine: 'Arrow line',
- horizontalLine: 'Horizontal line',
- verticalLine: 'Vertical line',
- crooked3: 'Crooked 3 line',
- crooked5: 'Crooked 5 line',
- elliott3: 'Elliott 3 line',
- elliott5: 'Elliott 5 line',
- verticalCounter: 'Vertical counter',
- verticalLabel: 'Vertical label',
- verticalArrow: 'Vertical arrow',
- fibonacci: 'Fibonacci',
- pitchfork: 'Pitchfork',
- parallelChannel: 'Parallel channel',
- infinityLine: 'Infinity line',
- measure: 'Measure',
- measureXY: 'Measure XY',
- measureX: 'Measure X',
- measureY: 'Measure Y',
- // Flags:
- flags: 'Flags',
- // GUI elements:
- addButton: 'add',
- saveButton: 'save',
- editButton: 'edit',
- removeButton: 'remove',
- series: 'Series',
- volume: 'Volume',
- connector: 'Connector',
- // Field names:
- innerBackground: 'Inner background',
- outerBackground: 'Outer background',
- crosshairX: 'Crosshair X',
- crosshairY: 'Crosshair Y',
- tunnel: 'Tunnel',
- background: 'Background',
- // Indicators' params (#15170):
- index: 'Index',
- period: 'Period',
- standardDeviation: 'Standard deviation',
- periodTenkan: 'Tenkan period',
- periodSenkouSpanB: 'Senkou Span B period',
- periodATR: 'ATR period',
- multiplierATR: 'ATR multiplier',
- shortPeriod: 'Short period',
- longPeriod: 'Long period',
- signalPeriod: 'Signal period',
- decimals: 'Decimals',
- algorithm: 'Algorithm',
- topBand: 'Top band',
- bottomBand: 'Bottom band',
- initialAccelerationFactor: 'Initial acceleration factor',
- maxAccelerationFactor: 'Max acceleration factor',
- increment: 'Increment',
- multiplier: 'Multiplier',
- ranges: 'Ranges',
- highIndex: 'High index',
- lowIndex: 'Low index',
- deviation: 'Deviation',
- xAxisUnit: 'x-axis unit',
- factor: 'Factor',
- fastAvgPeriod: 'Fast average period',
- slowAvgPeriod: 'Slow average period',
- average: 'Average'
- }
- }
- },
- /**
- * Configure the stockTools gui strings in the chart. Requires the
- * [stockTools module]() to be loaded. For a description of the module
- * and information on its features, see [Highcharts StockTools]().
- *
- * @product highstock
- *
- * @sample stock/demo/stock-tools-gui Stock Tools GUI
- *
- * @sample stock/demo/stock-tools-custom-gui Stock Tools customized GUI
- *
- * @since 7.0.0
- * @optionparent stockTools
- */
- stockTools: {
- /**
- * Definitions of buttons in Stock Tools GUI.
- */
- gui: {
- /**
- * Path where Highcharts will look for icons. Change this to use
- * icons from a different server.
- *
- * Since 7.1.3 use [iconsURL](#navigation.iconsURL) for popup and
- * stock tools.
- *
- * @deprecated
- * @apioption stockTools.gui.iconsURL
- *
- */
- /**
- * Enable or disable the stockTools gui.
- */
- enabled: true,
- /**
- * A CSS class name to apply to the stocktools' div,
- * allowing unique CSS styling for each chart.
- */
- className: 'highcharts-bindings-wrapper',
- /**
- * A CSS class name to apply to the container of buttons,
- * allowing unique CSS styling for each chart.
- */
- toolbarClassName: 'stocktools-toolbar',
- /**
- * A collection of strings pointing to config options for the
- * toolbar items. Each name refers to a unique key from the
- * definitions object.
- *
- * @type {Array<string>}
- * @default [
- * 'indicators',
- * 'separator',
- * 'simpleShapes',
- * 'lines',
- * 'crookedLines',
- * 'measure',
- * 'advanced',
- * 'toggleAnnotations',
- * 'separator',
- * 'verticalLabels',
- * 'flags',
- * 'separator',
- * 'zoomChange',
- * 'fullScreen',
- * 'typeChange',
- * 'separator',
- * 'currentPriceIndicator',
- * 'saveChart'
- * ]
- */
- buttons: [
- 'indicators',
- 'separator',
- 'simpleShapes',
- 'lines',
- 'crookedLines',
- 'measure',
- 'advanced',
- 'toggleAnnotations',
- 'separator',
- 'verticalLabels',
- 'flags',
- 'separator',
- 'zoomChange',
- 'fullScreen',
- 'typeChange',
- 'separator',
- 'currentPriceIndicator',
- 'saveChart'
- ],
- /**
- * An options object of the buttons definitions. Each name refers to
- * unique key from buttons array.
- */
- definitions: {
- separator: {
- /**
- * A predefined background symbol for the button.
- */
- symbol: 'separator.svg'
- },
- simpleShapes: {
- /**
- * A collection of strings pointing to config options for
- * the items.
- *
- * @type {array}
- * @default [
- * 'label',
- * 'circle',
- * 'rectangle'
- * ]
- *
- */
- items: [
- 'label',
- 'circle',
- 'rectangle'
- ],
- circle: {
- /**
- * A predefined background symbol for the button.
- *
- * @type {string}
- *
- */
- symbol: 'circle.svg'
- },
- rectangle: {
- /**
- * A predefined background symbol for the button.
- *
- * @type {string}
- *
- */
- symbol: 'rectangle.svg'
- },
- label: {
- /**
- * A predefined background symbol for the button.
- *
- * @type {string}
- *
- */
- symbol: 'label.svg'
- }
- },
- flags: {
- /**
- * A collection of strings pointing to config options for
- * the items.
- *
- * @type {array}
- * @default [
- * 'flagCirclepin',
- * 'flagDiamondpin',
- * 'flagSquarepin',
- * 'flagSimplepin'
- * ]
- *
- */
- items: [
- 'flagCirclepin',
- 'flagDiamondpin',
- 'flagSquarepin',
- 'flagSimplepin'
- ],
- flagSimplepin: {
- /**
- * A predefined background symbol for the button.
- *
- * @type {string}
- *
- */
- symbol: 'flag-basic.svg'
- },
- flagDiamondpin: {
- /**
- * A predefined background symbol for the button.
- *
- * @type {string}
- *
- */
- symbol: 'flag-diamond.svg'
- },
- flagSquarepin: {
- /**
- * A predefined background symbol for the button.
- *
- * @type {string}
- */
- symbol: 'flag-trapeze.svg'
- },
- flagCirclepin: {
- /**
- * A predefined background symbol for the button.
- *
- * @type {string}
- */
- symbol: 'flag-elipse.svg'
- }
- },
- lines: {
- /**
- * A collection of strings pointing to config options for
- * the items.
- *
- * @type {array}
- * @default [
- * 'segment',
- * 'arrowSegment',
- * 'ray',
- * 'arrowRay',
- * 'line',
- * 'arrowLine',
- * 'horizontalLine',
- * 'verticalLine'
- * ]
- */
- items: [
- 'segment',
- 'arrowSegment',
- 'ray',
- 'arrowRay',
- 'line',
- 'arrowLine',
- 'horizontalLine',
- 'verticalLine'
- ],
- segment: {
- /**
- * A predefined background symbol for the button.
- *
- * @type {string}
- */
- symbol: 'segment.svg'
- },
- arrowSegment: {
- /**
- * A predefined background symbol for the button.
- *
- * @type {string}
- */
- symbol: 'arrow-segment.svg'
- },
- ray: {
- /**
- * A predefined background symbol for the button.
- *
- * @type {string}
- */
- symbol: 'ray.svg'
- },
- arrowRay: {
- /**
- * A predefined background symbol for the button.
- *
- * @type {string}
- */
- symbol: 'arrow-ray.svg'
- },
- line: {
- /**
- * A predefined background symbol for the button.
- *
- * @type {string}
- */
- symbol: 'line.svg'
- },
- arrowLine: {
- /**
- * A predefined background symbol for the button.
- *
- * @type {string}
- */
- symbol: 'arrow-line.svg'
- },
- verticalLine: {
- /**
- * A predefined background symbol for the button.
- *
- * @type {string}
- */
- symbol: 'vertical-line.svg'
- },
- horizontalLine: {
- /**
- * A predefined background symbol for the button.
- *
- * @type {string}
- */
- symbol: 'horizontal-line.svg'
- }
- },
- crookedLines: {
- /**
- * A collection of strings pointing to config options for
- * the items.
- *
- * @type {array}
- * @default [
- * 'elliott3',
- * 'elliott5',
- * 'crooked3',
- * 'crooked5'
- * ]
- *
- */
- items: [
- 'elliott3',
- 'elliott5',
- 'crooked3',
- 'crooked5'
- ],
- crooked3: {
- /**
- * A predefined background symbol for the button.
- *
- * @type {string}
- */
- symbol: 'crooked-3.svg'
- },
- crooked5: {
- /**
- * A predefined background symbol for the button.
- *
- * @type {string}
- */
- symbol: 'crooked-5.svg'
- },
- elliott3: {
- /**
- * A predefined background symbol for the button.
- *
- * @type {string}
- */
- symbol: 'elliott-3.svg'
- },
- elliott5: {
- /**
- * A predefined background symbol for the button.
- *
- * @type {string}
- */
- symbol: 'elliott-5.svg'
- }
- },
- verticalLabels: {
- /**
- * A collection of strings pointing to config options for
- * the items.
- *
- * @type {array}
- * @default [
- * 'verticalCounter',
- * 'verticalLabel',
- * 'verticalArrow'
- * ]
- */
- items: [
- 'verticalCounter',
- 'verticalLabel',
- 'verticalArrow'
- ],
- verticalCounter: {
- /**
- * A predefined background symbol for the button.
- *
- * @type {string}
- */
- symbol: 'vertical-counter.svg'
- },
- verticalLabel: {
- /**
- * A predefined background symbol for the button.
- *
- * @type {string}
- */
- symbol: 'vertical-label.svg'
- },
- verticalArrow: {
- /**
- * A predefined background symbol for the button.
- *
- * @type {string}
- */
- symbol: 'vertical-arrow.svg'
- }
- },
- advanced: {
- /**
- * A collection of strings pointing to config options for
- * the items.
- *
- * @type {array}
- * @default [
- * 'fibonacci',
- * 'pitchfork',
- * 'parallelChannel'
- * ]
- */
- items: [
- 'fibonacci',
- 'pitchfork',
- 'parallelChannel'
- ],
- pitchfork: {
- /**
- * A predefined background symbol for the button.
- *
- * @type {string}
- */
- symbol: 'pitchfork.svg'
- },
- fibonacci: {
- /**
- * A predefined background symbol for the button.
- *
- * @type {string}
- */
- symbol: 'fibonacci.svg'
- },
- parallelChannel: {
- /**
- * A predefined background symbol for the button.
- *
- * @type {string}
- */
- symbol: 'parallel-channel.svg'
- }
- },
- measure: {
- /**
- * A collection of strings pointing to config options for
- * the items.
- *
- * @type {array}
- * @default [
- * 'measureXY',
- * 'measureX',
- * 'measureY'
- * ]
- */
- items: [
- 'measureXY',
- 'measureX',
- 'measureY'
- ],
- measureX: {
- /**
- * A predefined background symbol for the button.
- *
- * @type {string}
- */
- symbol: 'measure-x.svg'
- },
- measureY: {
- /**
- * A predefined background symbol for the button.
- *
- * @type {string}
- */
- symbol: 'measure-y.svg'
- },
- measureXY: {
- /**
- * A predefined background symbol for the button.
- *
- * @type {string}
- */
- symbol: 'measure-xy.svg'
- }
- },
- toggleAnnotations: {
- /**
- * A predefined background symbol for the button.
- *
- * @type {string}
- */
- symbol: 'annotations-visible.svg'
- },
- currentPriceIndicator: {
- /**
- * A predefined background symbol for the button.
- *
- * @type {string}
- */
- symbol: 'current-price-show.svg'
- },
- indicators: {
- /**
- * A predefined background symbol for the button.
- *
- * @type {string}
- */
- symbol: 'indicators.svg'
- },
- zoomChange: {
- /**
- * A collection of strings pointing to config options for
- * the items.
- *
- * @type {array}
- * @default [
- * 'zoomX',
- * 'zoomY',
- * 'zoomXY'
- * ]
- */
- items: [
- 'zoomX',
- 'zoomY',
- 'zoomXY'
- ],
- zoomX: {
- /**
- * A predefined background symbol for the button.
- *
- * @type {string}
- */
- symbol: 'zoom-x.svg'
- },
- zoomY: {
- /**
- * A predefined background symbol for the button.
- *
- * @type {string}
- */
- symbol: 'zoom-y.svg'
- },
- zoomXY: {
- /**
- * A predefined background symbol for the button.
- *
- * @type {string}
- */
- symbol: 'zoom-xy.svg'
- }
- },
- typeChange: {
- /**
- * A collection of strings pointing to config options for
- * the items.
- *
- * @type {array}
- * @default [
- * 'typeOHLC',
- * 'typeLine',
- * 'typeCandlestick'
- * ]
- */
- items: [
- 'typeOHLC',
- 'typeLine',
- 'typeCandlestick'
- ],
- typeOHLC: {
- /**
- * A predefined background symbol for the button.
- *
- * @type {string}
- */
- symbol: 'series-ohlc.svg'
- },
- typeLine: {
- /**
- * A predefined background symbol for the button.
- *
- * @type {string}
- */
- symbol: 'series-line.svg'
- },
- typeCandlestick: {
- /**
- * A predefined background symbol for the button.
- *
- * @type {string}
- */
- symbol: 'series-candlestick.svg'
- }
- },
- fullScreen: {
- /**
- * A predefined background symbol for the button.
- *
- * @type {string}
- */
- symbol: 'fullscreen.svg'
- },
- saveChart: {
- /**
- * A predefined background symbol for the button.
- *
- * @type {string}
- */
- symbol: 'save-chart.svg'
- }
- }
- }
- }
- });
- /* eslint-disable no-invalid-this, valid-jsdoc */
- // Run HTML generator
- addEvent(Chart, 'afterGetContainer', function () {
- this.setStockTools();
- });
- addEvent(Chart, 'getMargins', function () {
- var listWrapper = this.stockTools && this.stockTools.listWrapper, offsetWidth = listWrapper && ((listWrapper.startWidth +
- getStyle(listWrapper, 'padding-left') +
- getStyle(listWrapper, 'padding-right')) || listWrapper.offsetWidth);
- if (offsetWidth && offsetWidth < this.plotWidth) {
- this.plotLeft += offsetWidth;
- this.spacing[3] += offsetWidth;
- }
- }, {
- order: 0
- });
- ['beforeRender', 'beforeRedraw'].forEach(function (event) {
- addEvent(Chart, event, function () {
- if (this.stockTools) {
- var optionsChart = this.options.chart;
- var listWrapper = this.stockTools.listWrapper, offsetWidth = listWrapper && ((listWrapper.startWidth +
- getStyle(listWrapper, 'padding-left') +
- getStyle(listWrapper, 'padding-right')) || listWrapper.offsetWidth);
- var dirty = false;
- if (offsetWidth && offsetWidth < this.plotWidth) {
- var nextX = pick(optionsChart.spacingLeft, optionsChart.spacing && optionsChart.spacing[3], 0) + offsetWidth;
- var diff = nextX - this.spacingBox.x;
- this.spacingBox.x = nextX;
- this.spacingBox.width -= diff;
- dirty = true;
- }
- else if (offsetWidth === 0) {
- dirty = true;
- }
- if (offsetWidth !== this.stockTools.prevOffsetWidth) {
- this.stockTools.prevOffsetWidth = offsetWidth;
- if (dirty) {
- this.isDirtyLegend = true;
- }
- }
- }
- });
- });
- addEvent(Chart, 'destroy', function () {
- if (this.stockTools) {
- this.stockTools.destroy();
- }
- });
- addEvent(Chart, 'redraw', function () {
- if (this.stockTools && this.stockTools.guiEnabled) {
- this.stockTools.redraw();
- }
- });
- /**
- * Toolbar Class
- * @private
- * @constructor
- * @param {Object} - options of toolbar
- * @param {Chart} - Reference to chart
- */
- var Toolbar = /** @class */ (function () {
- function Toolbar(options, langOptions, chart) {
- this.arrowDown = void 0;
- this.arrowUp = void 0;
- this.arrowWrapper = void 0;
- this.listWrapper = void 0;
- this.showhideBtn = void 0;
- this.submenu = void 0;
- this.toolbar = void 0;
- this.wrapper = void 0;
- this.chart = chart;
- this.options = options;
- this.lang = langOptions;
- // set url for icons.
- this.iconsURL = this.getIconsURL();
- this.guiEnabled = options.enabled;
- this.visible = pick(options.visible, true);
- this.placed = pick(options.placed, false);
- // General events collection which should be removed upon
- // destroy/update:
- this.eventsToUnbind = [];
- if (this.guiEnabled) {
- this.createHTML();
- this.init();
- this.showHideNavigatorion();
- }
- fireEvent(this, 'afterInit');
- }
- /**
- * Initialize the toolbar. Create buttons and submenu for each option
- * defined in `stockTools.gui`.
- * @private
- */
- Toolbar.prototype.init = function () {
- 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;
- // create buttons
- buttons.forEach(function (btnName) {
- button = _self.addButton(toolbar, defs, btnName, lang);
- _self.eventsToUnbind.push(addEvent(button.buttonWrapper, 'click', function () {
- _self.eraseActiveButtons(allButtons, button.buttonWrapper);
- }));
- if (isArray(defs[btnName].items)) {
- // create submenu buttons
- addSubmenu.call(_self, button, defs[btnName]);
- }
- });
- };
- /**
- * Create submenu (list of buttons) for the option. In example main button
- * is Line, in submenu will be buttons with types of lines.
- * @private
- * @param {Highcharts.Dictionary<Highcharts.HTMLDOMElement>}
- * button which has submenu
- * @param {Highcharts.StockToolsGuiDefinitionsButtonsOptions}
- * list of all buttons
- */
- Toolbar.prototype.addSubmenu = function (parentBtn, button) {
- 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;
- // create submenu container
- this.submenu = submenuWrapper = createElement(UL, {
- className: PREFIX + 'submenu-wrapper'
- }, void 0, buttonWrapper);
- // create submenu buttons and select the first one
- this.addSubmenuItems(buttonWrapper, button);
- // show / hide submenu
- _self.eventsToUnbind.push(addEvent(submenuArrow, 'click', function (e) {
- e.stopPropagation();
- // Erase active class on all other buttons
- _self.eraseActiveButtons(allButtons, buttonWrapper);
- // hide menu
- if (buttonWrapper.className.indexOf(PREFIX + 'current') >= 0) {
- menuWrapper.style.width =
- menuWrapper.startWidth + 'px';
- buttonWrapper.classList.remove(PREFIX + 'current');
- submenuWrapper.style.display = 'none';
- }
- else {
- // show menu
- // to calculate height of element
- submenuWrapper.style.display = 'block';
- topMargin = submenuWrapper.offsetHeight -
- buttonWrapper.offsetHeight - 3;
- // calculate position of submenu in the box
- // if submenu is inside, reset top margin
- if (
- // cut on the bottom
- !(submenuWrapper.offsetHeight +
- buttonWrapper.offsetTop >
- wrapper.offsetHeight &&
- // cut on the top
- buttonWrapper.offsetTop > topMargin)) {
- topMargin = 0;
- }
- // apply calculated styles
- css(submenuWrapper, {
- top: -topMargin + 'px',
- left: buttonWidth + 3 + 'px'
- });
- buttonWrapper.className += ' ' + PREFIX + 'current';
- menuWrapper.startWidth = wrapper.offsetWidth;
- menuWrapper.style.width = menuWrapper.startWidth +
- getStyle(menuWrapper, 'padding-left') +
- submenuWrapper.offsetWidth + 3 + 'px';
- }
- }));
- };
- /**
- * Create buttons in submenu
- * @private
- * @param {Highcharts.HTMLDOMElement}
- * button where submenu is placed
- * @param {Highcharts.StockToolsGuiDefinitionsButtonsOptions}
- * list of all buttons options
- *
- */
- Toolbar.prototype.addSubmenuItems = function (buttonWrapper, button) {
- var _self = this, submenuWrapper = this.submenu, lang = this.lang, menuWrapper = this.listWrapper, items = button.items, firstSubmenuItem, submenuBtn;
- // add items to submenu
- items.forEach(function (btnName) {
- // add buttons to submenu
- submenuBtn = _self.addButton(submenuWrapper, button, btnName, lang);
- _self.eventsToUnbind.push(addEvent(submenuBtn.mainButton, 'click', function () {
- _self.switchSymbol(this, buttonWrapper, true);
- menuWrapper.style.width =
- menuWrapper.startWidth + 'px';
- submenuWrapper.style.display = 'none';
- }));
- });
- // select first submenu item
- firstSubmenuItem = submenuWrapper
- .querySelectorAll('li > .' + PREFIX + 'menu-item-btn')[0];
- // replace current symbol, in main button, with submenu's button style
- _self.switchSymbol(firstSubmenuItem, false);
- };
- /*
- * Erase active class on all other buttons.
- *
- * @param {Array} - Array of HTML buttons
- * @param {HTMLDOMElement} - Current HTML button
- *
- */
- Toolbar.prototype.eraseActiveButtons = function (buttons, currentButton, submenuItems) {
- [].forEach.call(buttons, function (btn) {
- if (btn !== currentButton) {
- btn.classList.remove(PREFIX + 'current');
- btn.classList.remove(PREFIX + 'active');
- submenuItems =
- btn.querySelectorAll('.' + PREFIX + 'submenu-wrapper');
- // hide submenu
- if (submenuItems.length > 0) {
- submenuItems[0].style.display = 'none';
- }
- }
- });
- };
- /**
- * Create single button. Consist of HTML elements `li`, `span`, and (if
- * exists) submenu container.
- * @private
- * @param {Highcharts.HTMLDOMElement} target
- * HTML reference, where button should be added
- * @param {Highcharts.StockToolsGuiDefinitionsButtonsOptions|Highcharts.StockToolsGuiDefinitionsOptions} options
- * All options, by btnName refer to particular button
- * @param {string} btnName
- * of functionality mapped for specific class
- * @param {Highcharts.Dictionary<string>} lang
- * All titles, by btnName refer to particular button
- * @return {Object} - references to all created HTML elements
- */
- Toolbar.prototype.addButton = function (target, options, btnName, lang) {
- if (lang === void 0) { lang = {}; }
- var btnOptions = options[btnName], items = btnOptions.items, classMapping = Toolbar.prototype.classMapping, userClassName = btnOptions.className || '', mainButton, submenuArrow, buttonWrapper;
- // main button wrapper
- buttonWrapper = createElement(LI, {
- className: pick(classMapping[btnName], '') + ' ' + userClassName,
- title: lang[btnName] || btnName
- }, void 0, target);
- // single button
- mainButton = createElement(SPAN, {
- className: PREFIX + 'menu-item-btn'
- }, void 0, buttonWrapper);
- // submenu
- if (items && items.length) {
- // arrow is a hook to show / hide submenu
- submenuArrow = createElement(SPAN, {
- className: PREFIX + 'submenu-item-arrow ' +
- PREFIX + 'arrow-right'
- }, void 0, buttonWrapper);
- submenuArrow.style.backgroundImage = 'url(' +
- this.iconsURL + 'arrow-bottom.svg)';
- }
- else {
- mainButton.style.backgroundImage = 'url(' +
- this.iconsURL + btnOptions.symbol + ')';
- }
- return {
- buttonWrapper: buttonWrapper,
- mainButton: mainButton,
- submenuArrow: submenuArrow
- };
- };
- /*
- * Create navigation's HTML elements: container and arrows.
- *
- */
- Toolbar.prototype.addNavigation = function () {
- var stockToolbar = this, wrapper = stockToolbar.wrapper;
- // arrow wrapper
- stockToolbar.arrowWrapper = createElement(DIV, {
- className: PREFIX + 'arrow-wrapper'
- });
- stockToolbar.arrowUp = createElement(DIV, {
- className: PREFIX + 'arrow-up'
- }, void 0, stockToolbar.arrowWrapper);
- stockToolbar.arrowUp.style.backgroundImage =
- 'url(' + this.iconsURL + 'arrow-right.svg)';
- stockToolbar.arrowDown = createElement(DIV, {
- className: PREFIX + 'arrow-down'
- }, void 0, stockToolbar.arrowWrapper);
- stockToolbar.arrowDown.style.backgroundImage =
- 'url(' + this.iconsURL + 'arrow-right.svg)';
- wrapper.insertBefore(stockToolbar.arrowWrapper, wrapper.childNodes[0]);
- // attach scroll events
- stockToolbar.scrollButtons();
- };
- /*
- * Add events to navigation (two arrows) which allows user to scroll
- * top/down GUI buttons, if container's height is not enough.
- *
- */
- Toolbar.prototype.scrollButtons = function () {
- var targetY = 0, _self = this, wrapper = _self.wrapper, toolbar = _self.toolbar, step = 0.1 * wrapper.offsetHeight; // 0.1 = 10%
- _self.eventsToUnbind.push(addEvent(_self.arrowUp, 'click', function () {
- if (targetY > 0) {
- targetY -= step;
- toolbar.style.marginTop = -targetY + 'px';
- }
- }));
- _self.eventsToUnbind.push(addEvent(_self.arrowDown, 'click', function () {
- if (wrapper.offsetHeight + targetY <=
- toolbar.offsetHeight + step) {
- targetY += step;
- toolbar.style.marginTop = -targetY + 'px';
- }
- }));
- };
- /*
- * Create stockTools HTML main elements.
- *
- */
- Toolbar.prototype.createHTML = function () {
- var stockToolbar = this, chart = stockToolbar.chart, guiOptions = stockToolbar.options, container = chart.container, navigation = chart.options.navigation, bindingsClassName = navigation && navigation.bindingsClassName, listWrapper, toolbar;
- // create main container
- var wrapper = stockToolbar.wrapper = createElement(DIV, {
- className: PREFIX + 'stocktools-wrapper ' +
- guiOptions.className + ' ' + bindingsClassName
- });
- container.appendChild(wrapper);
- // Mimic event behaviour of being outside chart.container
- [
- 'mousemove',
- 'click',
- 'touchstart'
- ].forEach(function (eventType) {
- addEvent(wrapper, eventType, function (e) {
- return e.stopPropagation();
- });
- });
- addEvent(wrapper, 'mouseover', function (e) {
- return chart.pointer.onContainerMouseLeave(e);
- });
- // toolbar
- stockToolbar.toolbar = toolbar = createElement(UL, {
- className: PREFIX + 'stocktools-toolbar ' +
- guiOptions.toolbarClassName
- });
- // add container for list of buttons
- stockToolbar.listWrapper = listWrapper = createElement(DIV, {
- className: PREFIX + 'menu-wrapper'
- });
- wrapper.insertBefore(listWrapper, wrapper.childNodes[0]);
- listWrapper.insertBefore(toolbar, listWrapper.childNodes[0]);
- stockToolbar.showHideToolbar();
- // add navigation which allows user to scroll down / top GUI buttons
- stockToolbar.addNavigation();
- };
- /**
- * Function called in redraw verifies if the navigation should be visible.
- * @private
- */
- Toolbar.prototype.showHideNavigatorion = function () {
- // arrows
- // 50px space for arrows
- if (this.visible &&
- this.toolbar.offsetHeight > (this.wrapper.offsetHeight - 50)) {
- this.arrowWrapper.style.display = 'block';
- }
- else {
- // reset margin if whole toolbar is visible
- this.toolbar.style.marginTop = '0px';
- // hide arrows
- this.arrowWrapper.style.display = 'none';
- }
- };
- /**
- * Create button which shows or hides GUI toolbar.
- * @private
- */
- Toolbar.prototype.showHideToolbar = function () {
- var stockToolbar = this, chart = this.chart, wrapper = stockToolbar.wrapper, toolbar = this.listWrapper, submenu = this.submenu, visible = this.visible, showhideBtn;
- // Show hide toolbar
- this.showhideBtn = showhideBtn = createElement(DIV, {
- className: PREFIX + 'toggle-toolbar ' + PREFIX + 'arrow-left'
- }, void 0, wrapper);
- showhideBtn.style.backgroundImage =
- 'url(' + this.iconsURL + 'arrow-right.svg)';
- if (!visible) {
- // hide
- if (submenu) {
- submenu.style.display = 'none';
- }
- showhideBtn.style.left = '0px';
- stockToolbar.visible = visible = false;
- toolbar.classList.add(PREFIX + 'hide');
- showhideBtn.classList.toggle(PREFIX + 'arrow-right');
- wrapper.style.height = showhideBtn.offsetHeight + 'px';
- }
- else {
- wrapper.style.height = '100%';
- showhideBtn.style.top = getStyle(toolbar, 'padding-top') + 'px';
- showhideBtn.style.left = (wrapper.offsetWidth +
- getStyle(toolbar, 'padding-left')) + 'px';
- }
- // Toggle menu
- stockToolbar.eventsToUnbind.push(addEvent(showhideBtn, 'click', function () {
- chart.update({
- stockTools: {
- gui: {
- visible: !visible,
- placed: true
- }
- }
- });
- }));
- };
- /*
- * In main GUI button, replace icon and class with submenu button's
- * class / symbol.
- *
- * @param {HTMLDOMElement} - submenu button
- * @param {Boolean} - true or false
- *
- */
- Toolbar.prototype.switchSymbol = function (button, redraw) {
- var buttonWrapper = button.parentNode, buttonWrapperClass = buttonWrapper.classList.value,
- // main button in first level og GUI
- mainNavButton = buttonWrapper.parentNode.parentNode;
- // if the button is disabled, don't do anything
- if (buttonWrapperClass.indexOf('highcharts-disabled-btn') > -1) {
- return;
- }
- // set class
- mainNavButton.className = '';
- if (buttonWrapperClass) {
- mainNavButton.classList.add(buttonWrapperClass.trim());
- }
- // set icon
- mainNavButton
- .querySelectorAll('.' + PREFIX + 'menu-item-btn')[0]
- .style.backgroundImage =
- button.style.backgroundImage;
- // set active class
- if (redraw) {
- this.selectButton(mainNavButton);
- }
- };
- /*
- * Set select state (active class) on button.
- *
- * @param {HTMLDOMElement} - button
- *
- */
- Toolbar.prototype.selectButton = function (button) {
- if (button.className.indexOf(activeClass) >= 0) {
- button.classList.remove(activeClass);
- }
- else {
- button.classList.add(activeClass);
- }
- };
- /*
- * Remove active class from all buttons except defined.
- *
- * @param {HTMLDOMElement} - button which should not be deactivated
- *
- */
- Toolbar.prototype.unselectAllButtons = function (button) {
- var activeButtons = button.parentNode
- .querySelectorAll('.' + activeClass);
- [].forEach.call(activeButtons, function (activeBtn) {
- if (activeBtn !== button) {
- activeBtn.classList.remove(activeClass);
- }
- });
- };
- /*
- * Update GUI with given options.
- *
- * @param {Object} - general options for Stock Tools
- */
- Toolbar.prototype.update = function (options, redraw) {
- merge(true, this.chart.options.stockTools, options);
- this.destroy();
- this.chart.setStockTools(options);
- // If Stock Tools are updated, then bindings should be updated too:
- if (this.chart.navigationBindings) {
- this.chart.navigationBindings.update();
- }
- this.chart.isDirtyBox = true;
- if (pick(redraw, true)) {
- this.chart.redraw();
- }
- };
- /**
- * Destroy all HTML GUI elements.
- * @private
- */
- Toolbar.prototype.destroy = function () {
- var stockToolsDiv = this.wrapper, parent = stockToolsDiv && stockToolsDiv.parentNode;
- this.eventsToUnbind.forEach(function (unbinder) {
- unbinder();
- });
- // Remove the empty element
- if (parent) {
- parent.removeChild(stockToolsDiv);
- }
- };
- /**
- * Redraw, GUI requires to verify if the navigation should be visible.
- * @private
- */
- Toolbar.prototype.redraw = function () {
- this.showHideNavigatorion();
- };
- Toolbar.prototype.getIconsURL = function () {
- return this.chart.options.navigation.iconsURL ||
- this.options.iconsURL ||
- 'https://code.highcharts.com/9.1.1/gfx/stock-icons/';
- };
- return Toolbar;
- }());
- /**
- * Mapping JSON fields to CSS classes.
- * @private
- */
- Toolbar.prototype.classMapping = {
- circle: PREFIX + 'circle-annotation',
- rectangle: PREFIX + 'rectangle-annotation',
- label: PREFIX + 'label-annotation',
- segment: PREFIX + 'segment',
- arrowSegment: PREFIX + 'arrow-segment',
- ray: PREFIX + 'ray',
- arrowRay: PREFIX + 'arrow-ray',
- line: PREFIX + 'infinity-line',
- arrowLine: PREFIX + 'arrow-infinity-line',
- verticalLine: PREFIX + 'vertical-line',
- horizontalLine: PREFIX + 'horizontal-line',
- crooked3: PREFIX + 'crooked3',
- crooked5: PREFIX + 'crooked5',
- elliott3: PREFIX + 'elliott3',
- elliott5: PREFIX + 'elliott5',
- pitchfork: PREFIX + 'pitchfork',
- fibonacci: PREFIX + 'fibonacci',
- parallelChannel: PREFIX + 'parallel-channel',
- measureX: PREFIX + 'measure-x',
- measureY: PREFIX + 'measure-y',
- measureXY: PREFIX + 'measure-xy',
- verticalCounter: PREFIX + 'vertical-counter',
- verticalLabel: PREFIX + 'vertical-label',
- verticalArrow: PREFIX + 'vertical-arrow',
- currentPriceIndicator: PREFIX + 'current-price-indicator',
- indicators: PREFIX + 'indicators',
- flagCirclepin: PREFIX + 'flag-circlepin',
- flagDiamondpin: PREFIX + 'flag-diamondpin',
- flagSquarepin: PREFIX + 'flag-squarepin',
- flagSimplepin: PREFIX + 'flag-simplepin',
- zoomX: PREFIX + 'zoom-x',
- zoomY: PREFIX + 'zoom-y',
- zoomXY: PREFIX + 'zoom-xy',
- typeLine: PREFIX + 'series-type-line',
- typeOHLC: PREFIX + 'series-type-ohlc',
- typeCandlestick: PREFIX + 'series-type-candlestick',
- fullScreen: PREFIX + 'full-screen',
- toggleAnnotations: PREFIX + 'toggle-annotations',
- saveChart: PREFIX + 'save-chart',
- separator: PREFIX + 'separator'
- };
- extend(Chart.prototype, {
- /**
- * Verify if Toolbar should be added.
- * @private
- * @param {Highcharts.StockToolsOptions} - chart options
- */
- setStockTools: function (options) {
- var chartOptions = this.options, lang = chartOptions.lang, guiOptions = merge(chartOptions.stockTools && chartOptions.stockTools.gui, options && options.gui), langOptions = lang && lang.stockTools && lang.stockTools.gui;
- this.stockTools = new Toolbar(guiOptions, langOptions, this);
- if (this.stockTools.guiEnabled) {
- this.isDirtyBox = true;
- }
- }
- });
- // Comunication with bindings:
- addEvent(NavigationBindings, 'selectButton', function (event) {
- var button = event.button, className = PREFIX + 'submenu-wrapper', gui = this.chart.stockTools;
- if (gui && gui.guiEnabled) {
- // Unslect other active buttons
- gui.unselectAllButtons(event.button);
- // If clicked on a submenu, select state for it's parent
- if (button.parentNode.className.indexOf(className) >= 0) {
- button = button.parentNode.parentNode;
- }
- // Set active class on the current button
- gui.selectButton(button);
- }
- });
- addEvent(NavigationBindings, 'deselectButton', function (event) {
- var button = event.button, className = PREFIX + 'submenu-wrapper', gui = this.chart.stockTools;
- if (gui && gui.guiEnabled) {
- // If deselecting a button from a submenu, select state for it's parent
- if (button.parentNode.className.indexOf(className) >= 0) {
- button = button.parentNode.parentNode;
- }
- gui.selectButton(button);
- }
- });
- // Check if the correct price indicator button is displayed, #15029.
- addEvent(Chart, 'render', function () {
- var chart = this, stockTools = chart.stockTools, button = stockTools &&
- stockTools.toolbar &&
- stockTools.toolbar.querySelector('.highcharts-current-price-indicator');
- // Change the initial button background.
- if (stockTools && chart.navigationBindings && chart.options.series && button) {
- if (chart.navigationBindings.constructor.prototype.utils.isPriceIndicatorEnabled(chart.series)) {
- button.firstChild.style['background-image'] =
- 'url("' + stockTools.getIconsURL() + 'current-price-hide.svg")';
- }
- else {
- button.firstChild.style['background-image'] =
- 'url("' + stockTools.getIconsURL() + 'current-price-show.svg")';
- }
- }
- });
- H.Toolbar = Toolbar;
- export default H.Toolbar;
|