| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949 | /** * *  Events generator for Stock tools * *  (c) 2009-2019 Paweł Fus * *  License: www.highcharts.com/license * * *//** * A config object for bindings in Stock Tools module. * * @interface Highcharts.StockToolsBindingsObject *//** * ClassName of the element for a binding. * @name Highcharts.StockToolsBindingsObject#className * @type {string|undefined} *//** * Last event to be fired after last step event. * @name Highcharts.StockToolsBindingsObject#end * @type {Function|undefined} *//** * Initial event, fired on a button click. * @name Highcharts.StockToolsBindingsObject#init * @type {Function|undefined} *//** * Event fired on first click on a chart. * @name Highcharts.StockToolsBindingsObject#start * @type {Function|undefined} *//** * Last event to be fired after last step event. Array of step events to be * called sequentially after each user click. * @name Highcharts.StockToolsBindingsObject#steps * @type {Array<Function>|undefined} */'use strict';import H from '../parts/Globals.js';var fireEvent = H.fireEvent,    defined = H.defined,    pick = H.pick,    extend = H.extend,    isNumber = H.isNumber,    correctFloat = H.correctFloat,    bindingsUtils = H.NavigationBindings.prototype.utils,    PREFIX = 'highcharts-';/** * Generates function which will add a flag series using modal in GUI. * Method fires an event "showPopup" with config: * `{type, options, callback}`. * * Example: NavigationBindings.utils.addFlagFromForm('url(...)') - will * generate function that shows modal in GUI. * * @private * @function bindingsUtils.addFlagFromForm * * @param {string} type *        Type of flag series, e.g. "squarepin" * * @return {Function} *         Callback to be used in `start` callback */bindingsUtils.addFlagFromForm = function (type) {    return function (e) {        var navigation = this,            chart = navigation.chart,            toolbar = chart.toolbar,            getFieldType = bindingsUtils.getFieldType,            point = bindingsUtils.attractToPoint(e, chart),            pointConfig = {                x: point.x,                y: point.y            },            seriesOptions = {                type: 'flags',                onSeries: point.series.id,                shape: type,                data: [pointConfig],                point: {                    events: {                        click: function () {                            var point = this,                                options = point.options;                            fireEvent(                                navigation,                                'showPopup',                                {                                    point: point,                                    formType: 'annotation-toolbar',                                    options: {                                        langKey: 'flags',                                        type: 'flags',                                        title: [                                            options.title,                                            getFieldType(                                                options.title                                            )                                        ],                                        name: [                                            options.name,                                            getFieldType(                                                options.name                                            )                                        ]                                    },                                    onSubmit: function (updated) {                                        point.update(                                            navigation.fieldsToOptions(                                                updated.fields,                                                {}                                            )                                        );                                    }                                }                            );                        }                    }                }            };        if (!toolbar || !toolbar.guiEnabled) {            chart.addSeries(seriesOptions);        }        fireEvent(            navigation,            'showPopup',            {                formType: 'flag',                // Enabled options:                options: {                    langKey: 'flags',                    type: 'flags',                    title: ['A', getFieldType('A')],                    name: ['Flag A', getFieldType('Flag A')]                },                // Callback on submit:                onSubmit: function (data) {                    navigation.fieldsToOptions(                        data.fields,                        seriesOptions.data[0]                    );                    chart.addSeries(seriesOptions);                }            }        );    };};bindingsUtils.manageIndicators = function (data) {    var navigation = this,        chart = navigation.chart,        seriesConfig = {            linkedTo: data.linkedTo,            type: data.type        },        indicatorsWithVolume = [            'ad',            'cmf',            'mfi',            'vbp',            'vwap'        ],        indicatorsWithAxes = [            'ad',            'atr',            'cci',            'cmf',            'macd',            'mfi',            'roc',            'rsi',            'vwap',            'ao',            'aroon',            'aroonoscillator',            'trix',            'apo',            'dpo',            'ppo',            'natr',            'williamsr',            'linearRegression',            'linearRegressionSlope',            'linearRegressionIntercept',            'linearRegressionAngle'        ],        yAxis,        series;    if (data.actionType === 'edit') {        navigation.fieldsToOptions(data.fields, seriesConfig);        series = chart.get(data.seriesId);        if (series) {            series.update(seriesConfig, false);        }    } else if (data.actionType === 'remove') {        series = chart.get(data.seriesId);        if (series) {            yAxis = series.yAxis;            if (series.linkedSeries) {                series.linkedSeries.forEach(function (linkedSeries) {                    linkedSeries.remove(false);                });            }            series.remove(false);            if (indicatorsWithAxes.indexOf(series.type) >= 0) {                yAxis.remove(false);                navigation.resizeYAxes();            }        }    } else {        seriesConfig.id = H.uniqueKey();        navigation.fieldsToOptions(data.fields, seriesConfig);        if (indicatorsWithAxes.indexOf(data.type) >= 0) {            yAxis = chart.addAxis({                id: H.uniqueKey(),                offset: 0,                opposite: true,                title: {                    text: ''                },                tickPixelInterval: 40,                showLastLabel: false,                labels: {                    align: 'left',                    y: -2                }            }, false, false);            seriesConfig.yAxis = yAxis.options.id;            navigation.resizeYAxes();        }        if (indicatorsWithVolume.indexOf(data.type) >= 0) {            seriesConfig.params.volumeSeriesID = chart.series.filter(                function (series) {                    return series.options.type === 'column';                }            )[0].options.id;        }        chart.addSeries(seriesConfig, false);    }    fireEvent(        navigation,        'deselectButton',        {            button: navigation.selectedButtonElement        }    );    chart.redraw();};/** * Update height for an annotation. Height is calculated as a difference * between last point in `typeOptions` and current position. It's a value, * not pixels height. * * @private * @function bindingsUtils.updateHeight * * @param {global.Event} e *        normalized browser event * * @param {Highcharts.Annotation} annotation *        Annotation to be updated */bindingsUtils.updateHeight = function (e, annotation) {    annotation.update({        typeOptions: {            height: this.chart.yAxis[0].toValue(e.chartY) -                annotation.options.typeOptions.points[1].y        }    });};// @todo// Consider using getHoverData(), but always kdTree (columns?)bindingsUtils.attractToPoint = function (e, chart) {    var x = chart.xAxis[0].toValue(e.chartX),        y = chart.yAxis[0].toValue(e.chartY),        distX = Number.MAX_VALUE,        closestPoint;    chart.series.forEach(function (series) {        series.points.forEach(function (point) {            if (point && distX > Math.abs(point.x - x)) {                distX = Math.abs(point.x - x);                closestPoint = point;            }        });    });    return {        x: closestPoint.x,        y: closestPoint.y,        below: y < closestPoint.y,        series: closestPoint.series,        xAxis: closestPoint.series.xAxis.index || 0,        yAxis: closestPoint.series.yAxis.index || 0    };};/** * Shorthand to check if given yAxis comes from navigator. * * @private * @function bindingsUtils.isNotNavigatorYAxis * * @param {Highcharts.Axis} axis *        Axis * * @return {boolean} */bindingsUtils.isNotNavigatorYAxis = function (axis) {    return axis.userOptions.className !== PREFIX + 'navigator-yaxis';};/** * Update each point after specified index, most of the annotations use * this. For example crooked line: logic behind updating each point is the * same, only index changes when adding an annotation. * * Example: NavigationBindings.utils.updateNthPoint(1) - will generate * function that updates all consecutive points except point with index=0. * * @private * @function bindingsUtils.updateNthPoint * * @param {number} startIndex *        Index from each point should udpated * * @return {Function} *         Callback to be used in steps array */bindingsUtils.updateNthPoint = function (startIndex) {    return function (e, annotation) {        var options = annotation.options.typeOptions,            x = this.chart.xAxis[0].toValue(e.chartX),            y = this.chart.yAxis[0].toValue(e.chartY);        options.points.forEach(function (point, index) {            if (index >= startIndex) {                point.x = x;                point.y = y;            }        });        annotation.update({            typeOptions: {                points: options.points            }        });    };};// Extends NavigationBindigs to support indicators and resizers:extend(H.NavigationBindings.prototype, {    /**     * Get current positions for all yAxes. If new axis does not have position,     * returned is default height and last available top place.     *     * @private     * @function Highcharts.NavigationBindings#getYAxisPositions     *     * @param {Array<Highcharts.Axis>} yAxes     *        Array of yAxes available in the chart.     *     * @param {number} plotHeight     *        Available height in the chart.     *     * @param {number} defaultHeight     *        Default height in percents.     *     * @return {Array}     *         An array of calculated positions in percentages.     *         Format: `{top: Number, height: Number}`     */    getYAxisPositions: function (yAxes, plotHeight, defaultHeight) {        var positions,            allAxesHeight = 0;        function isPercentage(prop) {            return defined(prop) && !isNumber(prop) && prop.match('%');        }        positions = yAxes.map(function (yAxis) {            var height = isPercentage(yAxis.options.height) ?                    parseFloat(yAxis.options.height) / 100 :                    yAxis.height / plotHeight,                top = isPercentage(yAxis.options.top) ?                    parseFloat(yAxis.options.top) / 100 :                    correctFloat(                        yAxis.top - yAxis.chart.plotTop                    ) / plotHeight;            // New yAxis does not contain "height" info yet            if (!isNumber(height)) {                height = defaultHeight / 100;            }            allAxesHeight = correctFloat(allAxesHeight + height);            return {                height: height * 100,                top: top * 100            };        });        positions.allAxesHeight = allAxesHeight;        return positions;    },    /**     * Get current resize options for each yAxis. Note that each resize is     * linked to the next axis, except the last one which shouldn't affect     * axes in the navigator. Because indicator can be removed with it's yAxis     * in the middle of yAxis array, we need to bind closest yAxes back.     *     * @private     * @function Highcharts.NavigationBindings#getYAxisResizers     *     * @param {Array<Highcharts.Axis>} yAxes     *        Array of yAxes available in the chart     *     * @return {Array<object>}     *         An array of resizer options.     *         Format: `{enabled: Boolean, controlledAxis: { next: [String]}}`     */    getYAxisResizers: function (yAxes) {        var resizers = [];        yAxes.forEach(function (yAxis, index) {            var nextYAxis = yAxes[index + 1];            // We have next axis, bind them:            if (nextYAxis) {                resizers[index] = {                    enabled: true,                    controlledAxis: {                        next: [                            pick(                                nextYAxis.options.id,                                nextYAxis.options.index                            )                        ]                    }                };            } else {                // Remove binding:                resizers[index] = {                    enabled: false                };            }        });        return resizers;    },    /**     * Resize all yAxes (except navigator) to fit the plotting height. Method     * checks if new axis is added, then shrinks other main axis up to 5 panes.     * If added is more thatn 5 panes, it rescales all other axes to fit new     * yAxis.     *     * If axis is removed, and we have more than 5 panes, rescales all other     * axes. If chart has less than 5 panes, first pane receives all extra     * space.     *     * @private     * @function Highcharts.NavigationBindings#resizeYAxes     *     * @param {number} defaultHeight     *        Default height for yAxis     */    resizeYAxes: function (defaultHeight) {        defaultHeight = defaultHeight || 20; // in %, but as a number        var chart = this.chart,            // Only non-navigator axes            yAxes = chart.yAxis.filter(this.utils.isNotNavigatorYAxis),            plotHeight = chart.plotHeight,            allAxesLength = yAxes.length,            // Gather current heights (in %)            positions = this.getYAxisPositions(                yAxes,                plotHeight,                defaultHeight            ),            resizers = this.getYAxisResizers(yAxes),            allAxesHeight = positions.allAxesHeight,            changedSpace = defaultHeight;        // More than 100%        if (allAxesHeight > 1) {            // Simple case, add new panes up to 5            if (allAxesLength < 6) {                // Added axis, decrease first pane's height:                positions[0].height = correctFloat(                    positions[0].height - changedSpace                );                // And update all other "top" positions:                positions = this.recalculateYAxisPositions(                    positions,                    changedSpace                );            } else {                // We have more panes, rescale all others to gain some space,                // This is new height for upcoming yAxis:                defaultHeight = 100 / allAxesLength;                // This is how much we need to take from each other yAxis:                changedSpace = defaultHeight / (allAxesLength - 1);                // Now update all positions:                positions = this.recalculateYAxisPositions(                    positions,                    changedSpace,                    true,                    -1                );            }            // Set last position manually:            positions[allAxesLength - 1] = {                top: correctFloat(100 - defaultHeight),                height: defaultHeight            };        } else {            // Less than 100%            changedSpace = correctFloat(1 - allAxesHeight) * 100;            // Simple case, return first pane it's space:            if (allAxesLength < 5) {                positions[0].height = correctFloat(                    positions[0].height + changedSpace                );                positions = this.recalculateYAxisPositions(                    positions,                    changedSpace                );            } else {                // There were more panes, return to each pane a bit of space:                changedSpace /= allAxesLength;                // Removed axis, add extra space to the first pane:                // And update all other positions:                positions = this.recalculateYAxisPositions(                    positions,                    changedSpace,                    true,                    1                );            }        }        positions.forEach(function (position, index) {            // if (index === 0) debugger;            yAxes[index].update({                height: position.height + '%',                top: position.top + '%',                resize: resizers[index]            }, false);        });    },    /**     * Utility to modify calculated positions according to the remaining/needed     * space. Later, these positions are used in `yAxis.update({ top, height })`     *     * @private     * @function Highcharts.NavigationBindings#recalculateYAxisPositions     *     * @param {Array<object>} positions     *        Default positions of all yAxes.     *     * @param {number} changedSpace     *        How much space should be added or removed.     * @param {number} adder     *        `-1` or `1`, to determine whether we should add or remove space.     *     * @param {boolean} modifyHeight     *        Update only `top` or both `top` and `height`.     *     * @return {Array<object>}     *         Modified positions,     */    recalculateYAxisPositions: function (        positions,        changedSpace,        modifyHeight,        adder    ) {        positions.forEach(function (position, index) {            var prevPosition = positions[index - 1];            position.top = !prevPosition ? 0 :                correctFloat(prevPosition.height + prevPosition.top);            if (modifyHeight) {                position.height = correctFloat(                    position.height + adder * changedSpace                );            }        });        return positions;    }});/** * @type         {Highcharts.Dictionary<Highcharts.StockToolsBindingsObject>|*} * @since        7.0.0 * @optionparent navigation.bindings */var stockToolsBindings = {    // Line type annotations:    /**     * A segment annotation bindings. Includes `start` and one event in `steps`     * array.     *     * @type    {Highcharts.StockToolsBindingsObject}     * @product highstock     * @default {"className": "highcharts-segment", "start": function() {}, "steps": [function() {}]}     */    segment: {        /** @ignore */        className: 'highcharts-segment',        /** @ignore */        start: function (e) {            var x = this.chart.xAxis[0].toValue(e.chartX),                y = this.chart.yAxis[0].toValue(e.chartY);            return this.chart.addAnnotation({                langKey: 'segment',                type: 'crookedLine',                typeOptions: {                    points: [{                        x: x,                        y: y                    }, {                        x: x,                        y: y                    }]                }            });        },        /** @ignore */        steps: [            bindingsUtils.updateNthPoint(1)        ]    },    /**     * A segment with an arrow annotation bindings. Includes `start` and one     * event in `steps` array.     *     * @type    {Highcharts.StockToolsBindingsObject}     * @product highstock     * @default {"className": "highcharts-arrow-segment", "start": function() {}, "steps": [function() {}]}     */    arrowSegment: {        /** @ignore */        className: 'highcharts-arrow-segment',        /** @ignore */        start: function (e) {            var x = this.chart.xAxis[0].toValue(e.chartX),                y = this.chart.yAxis[0].toValue(e.chartY);            return this.chart.addAnnotation({                langKey: 'arrowSegment',                type: 'crookedLine',                typeOptions: {                    line: {                        markerEnd: 'arrow'                    },                    points: [{                        x: x,                        y: y                    }, {                        x: x,                        y: y                    }]                }            });        },        /** @ignore */        steps: [            bindingsUtils.updateNthPoint(1)        ]    },    /**     * A ray annotation bindings. Includes `start` and one event in `steps`     * array.     *     * @type    {Highcharts.StockToolsBindingsObject}     * @product highstock     * @default {"className": "highcharts-ray", "start": function() {}, "steps": [function() {}]}     */    ray: {        /** @ignore */        className: 'highcharts-ray',        /** @ignore */        start: function (e) {            var x = this.chart.xAxis[0].toValue(e.chartX),                y = this.chart.yAxis[0].toValue(e.chartY);            return this.chart.addAnnotation({                langKey: 'ray',                type: 'infinityLine',                typeOptions: {                    type: 'ray',                    points: [{                        x: x,                        y: y                    }, {                        x: x,                        y: y                    }]                }            });        },        /** @ignore */        steps: [            bindingsUtils.updateNthPoint(1)        ]    },    /**     * A ray with an arrow annotation bindings. Includes `start` and one event     * in `steps` array.     *     * @type    {Highcharts.StockToolsBindingsObject}     * @product highstock     * @default {"className": "highcharts-arrow-ray", "start": function() {}, "steps": [function() {}]}     */    arrowRay: {        /** @ignore */        className: 'highcharts-arrow-ray',        /** @ignore */        start: function (e) {            var x = this.chart.xAxis[0].toValue(e.chartX),                y = this.chart.yAxis[0].toValue(e.chartY);            return this.chart.addAnnotation({                langKey: 'arrowRay',                type: 'infinityLine',                typeOptions: {                    type: 'ray',                    line: {                        markerEnd: 'arrow'                    },                    points: [{                        x: x,                        y: y                    }, {                        x: x,                        y: y                    }]                }            });        },        /** @ignore */        steps: [            bindingsUtils.updateNthPoint(1)        ]    },    /**     * A line annotation. Includes `start` and one event in `steps` array.     *     * @type    {Highcharts.StockToolsBindingsObject}     * @product highstock     * @default {"className": "highcharts-infinity-line", "start": function() {}, "steps": [function() {}]}     */    infinityLine: {        /** @ignore */        className: 'highcharts-infinity-line',        /** @ignore */        start: function (e) {            var x = this.chart.xAxis[0].toValue(e.chartX),                y = this.chart.yAxis[0].toValue(e.chartY);            return this.chart.addAnnotation({                langKey: 'infinityLine',                type: 'infinityLine',                typeOptions: {                    type: 'line',                    points: [{                        x: x,                        y: y                    }, {                        x: x,                        y: y                    }]                }            });        },        /** @ignore */        steps: [            bindingsUtils.updateNthPoint(1)        ]    },    /**     * A line with arrow annotation. Includes `start` and one event in `steps`     * array.     *     * @type    {Highcharts.StockToolsBindingsObject}     * @product highstock     * @default {"className": "highcharts-arrow-infinity-line", "start": function() {}, "steps": [function() {}]}     */    arrowInfinityLine: {        /** @ignore */        className: 'highcharts-arrow-infinity-line',        /** @ignore */        start: function (e) {            var x = this.chart.xAxis[0].toValue(e.chartX),                y = this.chart.yAxis[0].toValue(e.chartY);            return this.chart.addAnnotation({                langKey: 'arrowInfinityLine',                type: 'infinityLine',                typeOptions: {                    type: 'line',                    line: {                        markerEnd: 'arrow'                    },                    points: [{                        x: x,                        y: y                    }, {                        x: x,                        y: y                    }]                }            });        },        /** @ignore */        steps: [            bindingsUtils.updateNthPoint(1)        ]    },    /**     * A horizontal line annotation. Includes `start` event.     *     * @type    {Highcharts.StockToolsBindingsObject}     * @product highstock     * @default {"className": "highcharts-horizontal-line", "start": function() {}}     */    horizontalLine: {        /** @ignore */        className: 'highcharts-horizontal-line',        /** @ignore */        start: function (e) {            var x = this.chart.xAxis[0].toValue(e.chartX),                y = this.chart.yAxis[0].toValue(e.chartY);            this.chart.addAnnotation({                langKey: 'horizontalLine',                type: 'infinityLine',                typeOptions: {                    type: 'horizontalLine',                    points: [{                        x: x,                        y: y                    }]                }            });        }    },    /**     * A vertical line annotation. Includes `start` event.     *     * @type    {Highcharts.StockToolsBindingsObject}     * @product highstock     * @default {"className": "highcharts-vertical-line", "start": function() {}}     */    verticalLine: {        /** @ignore */        className: 'highcharts-vertical-line',        /** @ignore */        start: function (e) {            var x = this.chart.xAxis[0].toValue(e.chartX),                y = this.chart.yAxis[0].toValue(e.chartY);            this.chart.addAnnotation({                langKey: 'verticalLine',                type: 'infinityLine',                typeOptions: {                    type: 'verticalLine',                    points: [{                        x: x,                        y: y                    }]                }            });        }    },    /**     * Crooked line (three points) annotation bindings. Includes `start` and two     * events in `steps` (for second and third points in crooked line) array.     *     * @type    {Highcharts.StockToolsBindingsObject}     * @product highstock     * @default {"className": "highcharts-crooked3", "start": function() {}, "steps": [function() {}, function() {}]}     */    // Crooked Line type annotations:    crooked3: {        /** @ignore */        className: 'highcharts-crooked3',        /** @ignore */        start: function (e) {            var x = this.chart.xAxis[0].toValue(e.chartX),                y = this.chart.yAxis[0].toValue(e.chartY);            return this.chart.addAnnotation({                langKey: 'crooked3',                type: 'crookedLine',                typeOptions: {                    points: [{                        x: x,                        y: y                    }, {                        x: x,                        y: y                    }, {                        x: x,                        y: y                    }]                }            });        },        /** @ignore */        steps: [            bindingsUtils.updateNthPoint(1),            bindingsUtils.updateNthPoint(2)        ]    },    /**     * Crooked line (five points) annotation bindings. Includes `start` and four     * events in `steps` (for all consequent points in crooked line) array.     *     * @type    {Highcharts.StockToolsBindingsObject}     * @product highstock     * @default {"className": "highcharts-crooked3", "start": function() {}, "steps": [function() {}, function() {}, function() {}, function() {}]}     */    crooked5: {        /** @ignore */        className: 'highcharts-crooked5',        /** @ignore */        start: function (e) {            var x = this.chart.xAxis[0].toValue(e.chartX),                y = this.chart.yAxis[0].toValue(e.chartY);            return this.chart.addAnnotation({                langKey: 'crookedLine',                type: 'crookedLine',                typeOptions: {                    points: [{                        x: x,                        y: y                    }, {                        x: x,                        y: y                    }, {                        x: x,                        y: y                    }, {                        x: x,                        y: y                    }, {                        x: x,                        y: y                    }]                }            });        },        /** @ignore */        steps: [            bindingsUtils.updateNthPoint(1),            bindingsUtils.updateNthPoint(2),            bindingsUtils.updateNthPoint(3),            bindingsUtils.updateNthPoint(4)        ]    },    /**     * Elliott wave (three points) annotation bindings. Includes `start` and two     * events in `steps` (for second and third points) array.     *     * @type    {Highcharts.StockToolsBindingsObject}     * @product highstock     * @default {"className": "highcharts-elliott3", "start": function() {}, "steps": [function() {}, function() {}]}     */    elliott3: {        /** @ignore */        className: 'highcharts-elliott3',        /** @ignore */        start: function (e) {            var x = this.chart.xAxis[0].toValue(e.chartX),                y = this.chart.yAxis[0].toValue(e.chartY);            return this.chart.addAnnotation({                langKey: 'elliott3',                type: 'elliottWave',                typeOptions: {                    points: [{                        x: x,                        y: y                    }, {                        x: x,                        y: y                    }, {                        x: x,                        y: y                    }]                },                labelOptions: {                    style: {                        color: '#666666'                    }                }            });        },        /** @ignore */        steps: [            bindingsUtils.updateNthPoint(1),            bindingsUtils.updateNthPoint(2)        ]    },    /**     * Elliott wave (five points) annotation bindings. Includes `start` and four     * event in `steps` (for all consequent points in Elliott wave) array.     *     * @type    {Highcharts.StockToolsBindingsObject}     * @product highstock     * @default {"className": "highcharts-elliott3", "start": function() {}, "steps": [function() {}, function() {}, function() {}, function() {}]}     */    elliott5: {        /** @ignore */        className: 'highcharts-elliott5',        /** @ignore */        start: function (e) {            var x = this.chart.xAxis[0].toValue(e.chartX),                y = this.chart.yAxis[0].toValue(e.chartY);            return this.chart.addAnnotation({                langKey: 'elliott5',                type: 'elliottWave',                typeOptions: {                    points: [{                        x: x,                        y: y                    }, {                        x: x,                        y: y                    }, {                        x: x,                        y: y                    }, {                        x: x,                        y: y                    }, {                        x: x,                        y: y                    }]                },                labelOptions: {                    style: {                        color: '#666666'                    }                }            });        },        /** @ignore */        steps: [            bindingsUtils.updateNthPoint(1),            bindingsUtils.updateNthPoint(2),            bindingsUtils.updateNthPoint(3),            bindingsUtils.updateNthPoint(4)        ]    },    /**     * A measure (x-dimension) annotation bindings. Includes `start` and one     * event in `steps` array.     *     * @type    {Highcharts.StockToolsBindingsObject}     * @product highstock     * @default {"className": "highcharts-measure-x", "start": function() {}, "steps": [function() {}]}     */    measureX: {        /** @ignore */        className: 'highcharts-measure-x',        /** @ignore */        start: function (e) {            var x = this.chart.xAxis[0].toValue(e.chartX),                y = this.chart.yAxis[0].toValue(e.chartY),                options = {                    langKey: 'measure',                    type: 'measure',                    typeOptions: {                        selectType: 'x',                        point: {                            x: x,                            y: y,                            xAxis: 0,                            yAxis: 0                        },                        crosshairX: {                            strokeWidth: 1,                            stroke: '#000000'                        },                        crosshairY: {                            enabled: false,                            strokeWidth: 0,                            stroke: '#000000'                        },                        background: {                            width: 0,                            height: 0,                            strokeWidth: 0,                            stroke: '#ffffff'                        }                    },                    labelOptions: {                        style: {                            color: '#666666'                        }                    }                };            return this.chart.addAnnotation(options);        },        /** @ignore */        steps: [            bindingsUtils.updateRectSize        ]    },    /**     * A measure (y-dimension) annotation bindings. Includes `start` and one     * event in `steps` array.     *     * @type    {Highcharts.StockToolsBindingsObject}     * @product highstock     * @default {"className": "highcharts-measure-y", "start": function() {}, "steps": [function() {}]}     */    measureY: {        /** @ignore */        className: 'highcharts-measure-y',        /** @ignore */        start: function (e) {            var x = this.chart.xAxis[0].toValue(e.chartX),                y = this.chart.yAxis[0].toValue(e.chartY),                options = {                    langKey: 'measure',                    type: 'measure',                    typeOptions: {                        selectType: 'y',                        point: {                            x: x,                            y: y,                            xAxis: 0,                            yAxis: 0                        },                        crosshairX: {                            enabled: false,                            strokeWidth: 0,                            stroke: '#000000'                        },                        crosshairY: {                            strokeWidth: 1,                            stroke: '#000000'                        },                        background: {                            width: 0,                            height: 0,                            strokeWidth: 0,                            stroke: '#ffffff'                        }                    },                    labelOptions: {                        style: {                            color: '#666666'                        }                    }                };            return this.chart.addAnnotation(options);        },        /** @ignore */        steps: [            bindingsUtils.updateRectSize        ]    },    /**     * A measure (xy-dimension) annotation bindings. Includes `start` and one     * event in `steps` array.     *     * @type    {Highcharts.StockToolsBindingsObject}     * @product highstock     * @default {"className": "highcharts-measure-xy", "start": function() {}, "steps": [function() {}]}     */    measureXY: {        /** @ignore */        className: 'highcharts-measure-xy',        /** @ignore */        start: function (e) {            var x = this.chart.xAxis[0].toValue(e.chartX),                y = this.chart.yAxis[0].toValue(e.chartY),                options = {                    langKey: 'measure',                    type: 'measure',                    typeOptions: {                        selectType: 'xy',                        point: {                            x: x,                            y: y,                            xAxis: 0,                            yAxis: 0                        },                        background: {                            width: 0,                            height: 0,                            strokeWidth: 0,                            stroke: '#000000'                        },                        crosshairX: {                            strokeWidth: 1,                            stroke: '#000000'                        },                        crosshairY: {                            strokeWidth: 1,                            stroke: '#000000'                        }                    },                    labelOptions: {                        style: {                            color: '#666666'                        }                    }                };            return this.chart.addAnnotation(options);        },        /** @ignore */        steps: [            bindingsUtils.updateRectSize        ]    },    // Advanced type annotations:    /**     * A fibonacci annotation bindings. Includes `start` and two events in     * `steps` array (updates second point, then height).     *     * @type    {Highcharts.StockToolsBindingsObject}     * @product highstock     * @default {"className": "highcharts-fibonacci", "start": function() {}, "steps": [function() {}, function() {}]}     */    fibonacci: {        /** @ignore */        className: 'highcharts-fibonacci',        /** @ignore */        start: function (e) {            var x = this.chart.xAxis[0].toValue(e.chartX),                y = this.chart.yAxis[0].toValue(e.chartY);            return this.chart.addAnnotation({                langKey: 'fibonacci',                type: 'fibonacci',                typeOptions: {                    points: [{                        x: x,                        y: y                    }, {                        x: x,                        y: y                    }]                },                labelOptions: {                    style: {                        color: '#666666'                    }                }            });        },        /** @ignore */        steps: [            bindingsUtils.updateNthPoint(1),            bindingsUtils.updateHeight        ]    },    /**     * A parallel channel (tunnel) annotation bindings. Includes `start` and     * two events in `steps` array (updates second point, then height).     *     * @type    {Highcharts.StockToolsBindingsObject}     * @product highstock     * @default {"className": "highcharts-parallel-channel", "start": function() {}, "steps": [function() {}, function() {}]}     */    parallelChannel: {        /** @ignore */        className: 'highcharts-parallel-channel',        /** @ignore */        start: function (e) {            var x = this.chart.xAxis[0].toValue(e.chartX),                y = this.chart.yAxis[0].toValue(e.chartY);            return this.chart.addAnnotation({                langKey: 'parallelChannel',                type: 'tunnel',                typeOptions: {                    points: [{                        x: x,                        y: y                    }, {                        x: x,                        y: y                    }]                }            });        },        /** @ignore */        steps: [            bindingsUtils.updateNthPoint(1),            bindingsUtils.updateHeight        ]    },    /**     * An Andrew's pitchfork annotation bindings. Includes `start` and two     * events in `steps` array (sets second and third control points).     *     * @type    {Highcharts.StockToolsBindingsObject}     * @product highstock     * @default {"className": "highcharts-pitchfork", "start": function() {}, "steps": [function() {}, function() {}]}     */    pitchfork: {        /** @ignore */        className: 'highcharts-pitchfork',        /** @ignore */        start: function (e) {            var x = this.chart.xAxis[0].toValue(e.chartX),                y = this.chart.yAxis[0].toValue(e.chartY);            return this.chart.addAnnotation({                langKey: 'pitchfork',                type: 'pitchfork',                typeOptions: {                    points: [{                        x: x,                        y: y,                        controlPoint: {                            style: {                                fill: 'red'                            }                        }                    }, {                        x: x,                        y: y                    }, {                        x: x,                        y: y                    }],                    innerBackground: {                        fill: 'rgba(100, 170, 255, 0.8)'                    }                },                shapeOptions: {                    strokeWidth: 2                }            });        },        /** @ignore */        steps: [            bindingsUtils.updateNthPoint(1),            bindingsUtils.updateNthPoint(2)        ]    },    // Labels with arrow and auto increments    /**     * A vertical counter annotation bindings. Includes `start` event. On click,     * finds the closest point and marks it with a numeric annotation -     * incrementing counter on each add.     *     * @type    {Highcharts.StockToolsBindingsObject}     * @product highstock     * @default {"className": "highcharts-vertical-counter", "start": function() {}}     */    verticalCounter: {        /** @ignore */        className: 'highcharts-vertical-counter',        /** @ignore */        start: function (e) {            var closestPoint = bindingsUtils.attractToPoint(e, this.chart),                annotation;            if (!defined(this.verticalCounter)) {                this.verticalCounter = 0;            }            annotation = this.chart.addAnnotation({                langKey: 'verticalCounter',                type: 'verticalLine',                typeOptions: {                    point: {                        x: closestPoint.x,                        y: closestPoint.y,                        xAxis: closestPoint.xAxis,                        yAxis: closestPoint.yAxis                    },                    label: {                        offset: closestPoint.below ? 40 : -40,                        text: this.verticalCounter.toString()                    }                },                labelOptions: {                    style: {                        color: '#666666',                        fontSize: '11px'                    }                },                shapeOptions: {                    stroke: 'rgba(0, 0, 0, 0.75)',                    strokeWidth: 1                }            });            this.verticalCounter++;            annotation.options.events.click.call(annotation, {});        }    },    /**     * A vertical arrow annotation bindings. Includes `start` event. On click,     * finds the closest point and marks it with an arrow and a label with     * value.     *     * @type    {Highcharts.StockToolsBindingsObject}     * @product highstock     * @default {"className": "highcharts-vertical-label", "start": function() {}}     */    verticalLabel: {        /** @ignore */        className: 'highcharts-vertical-label',        /** @ignore */        start: function (e) {            var closestPoint = bindingsUtils.attractToPoint(e, this.chart),                annotation;            annotation = this.chart.addAnnotation({                langKey: 'verticalLabel',                type: 'verticalLine',                typeOptions: {                    point: {                        x: closestPoint.x,                        y: closestPoint.y,                        xAxis: closestPoint.xAxis,                        yAxis: closestPoint.yAxis                    },                    label: {                        offset: closestPoint.below ? 40 : -40                    }                },                labelOptions: {                    style: {                        color: '#666666',                        fontSize: '11px'                    }                },                shapeOptions: {                    stroke: 'rgba(0, 0, 0, 0.75)',                    strokeWidth: 1                }            });            annotation.options.events.click.call(annotation, {});        }    },    /**     * A vertical arrow annotation bindings. Includes `start` event. On click,     * finds the closest point and marks it with an arrow. Green arrow when     * pointing from above, red when pointing from below the point.     *     * @type    {Highcharts.StockToolsBindingsObject}     * @product highstock     * @default {"className": "highcharts-vertical-arrow", "start": function() {}}     */    verticalArrow: {        /** @ignore */        className: 'highcharts-vertical-arrow',        /** @ignore */        start: function (e) {            var closestPoint = bindingsUtils.attractToPoint(e, this.chart),                annotation;            annotation = this.chart.addAnnotation({                langKey: 'verticalArrow',                type: 'verticalLine',                typeOptions: {                    point: {                        x: closestPoint.x,                        y: closestPoint.y,                        xAxis: closestPoint.xAxis,                        yAxis: closestPoint.yAxis                    },                    label: {                        offset: closestPoint.below ? 40 : -40,                        format: ' '                    },                    connector: {                        fill: 'none',                        stroke: closestPoint.below ? 'red' : 'green'                    }                },                shapeOptions: {                    stroke: 'rgba(0, 0, 0, 0.75)',                    strokeWidth: 1                }            });            annotation.options.events.click.call(annotation, {});        }    },    // Flag types:    /**     * A flag series bindings. Includes `start` event. On click, finds the     * closest point and marks it with a flag with `'circlepin'` shape.     *     * @type    {Highcharts.StockToolsBindingsObject}     * @product highstock     * @default {"className": "highcharts-flag-circlepin", "start": function() {}}     */    flagCirclepin: {        /** @ignore */        className: 'highcharts-flag-circlepin',        /** @ignore */        start: bindingsUtils            .addFlagFromForm('circlepin')    },    /**     * A flag series bindings. Includes `start` event. On click, finds the     * closest point and marks it with a flag with `'diamondpin'` shape.     *     * @type    {Highcharts.StockToolsBindingsObject}     * @product highstock     * @default {"className": "highcharts-flag-diamondpin", "start": function() {}}     */    flagDiamondpin: {        /** @ignore */        className: 'highcharts-flag-diamondpin',        /** @ignore */        start: bindingsUtils            .addFlagFromForm('flag')    },    /**     * A flag series bindings. Includes `start` event.     * On click, finds the closest point and marks it with a flag with     * `'squarepin'` shape.     *     * @type    {Highcharts.StockToolsBindingsObject}     * @product highstock     * @default {"className": "highcharts-flag-squarepin", "start": function() {}}     */    flagSquarepin: {        /** @ignore */        className: 'highcharts-flag-squarepin',        /** @ignore */        start: bindingsUtils            .addFlagFromForm('squarepin')    },    /**     * A flag series bindings. Includes `start` event.     * On click, finds the closest point and marks it with a flag without pin     * shape.     *     * @type    {Highcharts.StockToolsBindingsObject}     * @product highstock     * @default {"className": "highcharts-flag-simplepin", "start": function() {}}     */    flagSimplepin: {        /** @ignore */        className: 'highcharts-flag-simplepin',        /** @ignore */        start: bindingsUtils            .addFlagFromForm('nopin')    },    // Other tools:    /**     * Enables zooming in xAxis on a chart. Includes `start` event which     * changes [chart.zoomType](#chart.zoomType).     *     * @type    {Highcharts.StockToolsBindingsObject}     * @product highstock     * @default {"className": "highcharts-zoom-x", "init": function() {}}     */    zoomX: {        /** @ignore */        className: 'highcharts-zoom-x',        /** @ignore */        init: function (button) {            this.chart.update({                chart: {                    zoomType: 'x'                }            });            fireEvent(                this,                'deselectButton',                { button: button }            );        }    },    /**     * Enables zooming in yAxis on a chart. Includes `start` event which     * changes [chart.zoomType](#chart.zoomType).     *     * @type    {Highcharts.StockToolsBindingsObject}     * @product highstock     * @default {"className": "highcharts-zoom-y", "init": function() {}}     */    zoomY: {        /** @ignore */        className: 'highcharts-zoom-y',        /** @ignore */        init: function (button) {            this.chart.update({                chart: {                    zoomType: 'y'                }            });            fireEvent(                this,                'deselectButton',                { button: button }            );        }    },    /**     * Enables zooming in xAxis and yAxis on a chart. Includes `start` event     * which changes [chart.zoomType](#chart.zoomType).     *     * @type    {Highcharts.StockToolsBindingsObject}     * @product highstock     * @default {"className": "highcharts-zoom-xy", "init": function() {}}     */    zoomXY: {        /** @ignore */        className: 'highcharts-zoom-xy',        /** @ignore */        init: function (button) {            this.chart.update({                chart: {                    zoomType: 'xy'                }            });            fireEvent(                this,                'deselectButton',                { button: button }            );        }    },    /**     * Changes main series to `'line'` type.     *     * @type    {Highcharts.StockToolsBindingsObject}     * @product highstock     * @default {"className": "highcharts-series-type-line", "init": function() {}}     */    seriesTypeLine: {        /** @ignore */        className: 'highcharts-series-type-line',        /** @ignore */        init: function (button) {            this.chart.series[0].update({                type: 'line'            });            fireEvent(                this,                'deselectButton',                { button: button }            );        }    },    /**     * Changes main series to `'ohlc'` type.     *     * @type    {Highcharts.StockToolsBindingsObject}     * @product highstock     * @default {"className": "highcharts-series-type-ohlc", "init": function() {}}     */    seriesTypeOhlc: {        /** @ignore */        className: 'highcharts-series-type-ohlc',        /** @ignore */        init: function (button) {            this.chart.series[0].update({                type: 'ohlc'            });            fireEvent(                this,                'deselectButton',                { button: button }            );        }    },    /**     * Changes main series to `'candlestick'` type.     *     * @type    {Highcharts.StockToolsBindingsObject}     * @product highstock     * @default {"className": "highcharts-series-type-candlestick", "init": function() {}}     */    seriesTypeCandlestick: {        /** @ignore */        className: 'highcharts-series-type-candlestick',        /** @ignore */        init: function (button) {            this.chart.series[0].update({                type: 'candlestick'            });            fireEvent(                this,                'deselectButton',                { button: button }            );        }    },    /**     * Displays chart in fullscreen.     *     * @type    {Highcharts.StockToolsBindingsObject}     * @product highstock     * @default {"className": "highcharts-full-screen", "init": function() {}}     */    fullScreen: {        /** @ignore */        className: 'highcharts-full-screen',        /** @ignore */        init: function (button) {            var chart = this.chart;            chart.fullScreen = new H.FullScreen(chart.container);            fireEvent(                this,                'deselectButton',                { button: button }            );        }    },    /**     * Hides/shows two price indicators:     * - last price in the dataset     * - last price in the selected range     *     * @type    {Highcharts.StockToolsBindingsObject}     * @product highstock     * @default {"className": "highcharts-current-price-indicator", "init": function() {}}     */    currentPriceIndicator: {        /** @ignore */        className: 'highcharts-current-price-indicator',        /** @ignore */        init: function (button) {            var series = this.chart.series[0],                options = series.options,                lastVisiblePrice = options.lastVisiblePrice &&                                options.lastVisiblePrice.enabled,                lastPrice = options.lastPrice && options.lastPrice.enabled,                gui = this.chart.stockToolbar;            if (gui && gui.guiEnabled) {                if (lastPrice) {                    button.firstChild.style['background-image'] =                        'url("' + gui.options.iconsURL +                        'current-price-show.svg")';                } else {                    button.firstChild.style['background-image'] =                        'url("' + gui.options.iconsURL +                        'current-price-hide.svg")';                }            }            series.update({                // line                lastPrice: {                    enabled: !lastPrice,                    color: 'red'                },                // label                lastVisiblePrice: {                    enabled: !lastVisiblePrice,                    label: {                        enabled: true                    }                }            });            fireEvent(                this,                'deselectButton',                { button: button }            );        }    },    /**     * Indicators bindings. Includes `init` event to show a popup.     *     * @type    {Highcharts.StockToolsBindingsObject}     * @product highstock     * @default {"className": "highcharts-indicators", "init": function() {}}     */    indicators: {        /** @ignore */        className: 'highcharts-indicators',        /** @ignore */        init: function () {            var navigation = this;            fireEvent(                navigation,                'showPopup',                {                    formType: 'indicators',                    options: {},                    // Callback on submit:                    onSubmit: function (data) {                        navigation.utils.manageIndicators.call(                            navigation,                            data                        );                    }                }            );        }    },    /**     * Hides/shows all annotations on a chart.     *     * @type    {Highcharts.StockToolsBindingsObject}     * @product highstock     * @default {"className": "highcharts-toggle-annotations", "init": function() {}}     */    toggleAnnotations: {        /** @ignore */        className: 'highcharts-toggle-annotations',        /** @ignore */        init: function (button) {            var gui = this.chart.stockToolbar;            this.toggledAnnotations = !this.toggledAnnotations;            (this.chart.annotations || []).forEach(function (annotation) {                annotation.setVisibility(!this.toggledAnnotations);            }, this);            if (gui && gui.guiEnabled) {                if (this.toggledAnnotations) {                    button.firstChild.style['background-image'] =                        'url("' + gui.options.iconsURL +                            'annotations-hidden.svg")';                } else {                    button.firstChild.style['background-image'] =                        'url("' + gui.options.iconsURL +                            'annotations-visible.svg")';                }            }            fireEvent(                this,                'deselectButton',                { button: button }            );        }    },    /**     * Save a chart in localStorage under `highcharts-chart` key.     * Stored items:     * - annotations     * - indicators (with yAxes)     * - flags     *     * @type    {Highcharts.StockToolsBindingsObject}     * @product highstock     * @default {"className": "highcharts-save-chart", "init": function() {}}     */    saveChart: {        /** @ignore */        className: 'highcharts-save-chart',        /** @ignore */        init: function (button) {            var navigation = this,                chart = navigation.chart,                annotations = [],                indicators = [],                flags = [],                yAxes = [];            chart.annotations.forEach(function (annotation, index) {                annotations[index] = annotation.userOptions;            });            chart.series.forEach(function (series) {                if (series instanceof H.seriesTypes.sma) {                    indicators.push(series.userOptions);                } else if (series.type === 'flags') {                    flags.push(series.userOptions);                }            });            chart.yAxis.forEach(function (yAxis) {                if (navigation.utils.isNotNavigatorYAxis(yAxis)) {                    yAxes.push(yAxis.options);                }            });            H.win.localStorage.setItem(                PREFIX + 'chart',                JSON.stringify({                    annotations: annotations,                    indicators: indicators,                    flags: flags,                    yAxes: yAxes                })            );            fireEvent(                this,                'deselectButton',                { button: button }            );        }    }};H.setOptions({    navigation: {        bindings: stockToolsBindings    }});
 |