12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434 |
- /**
- * @license Highcharts JS v7.0.2 (2019-01-17)
- * Advanced Highstock tools
- *
- * (c) 2010-2019 Highsoft AS
- * Author: Torstein Honsi
- *
- * License: www.highcharts.com/license
- */
- 'use strict';
- (function (factory) {
- if (typeof module === 'object' && module.exports) {
- factory['default'] = factory;
- module.exports = factory;
- } else if (typeof define === 'function' && define.amd) {
- define(function () {
- return factory;
- });
- } else {
- factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined);
- }
- }(function (Highcharts) {
- (function (H) {
- /**
- *
- * 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}
- */
- 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
- }
- });
- }(Highcharts));
- (function (H) {
- /**
- * GUI generator for Stock tools
- *
- * (c) 2009-2017 Sebastian Bochan
- *
- * License: www.highcharts.com/license
- */
- var addEvent = H.addEvent,
- createElement = H.createElement,
- pick = H.pick,
- isArray = H.isArray,
- fireEvent = H.fireEvent,
- getStyle = H.getStyle,
- merge = H.merge,
- css = H.css,
- win = H.win,
- DIV = 'div',
- SPAN = 'span',
- UL = 'ul',
- LI = 'li',
- PREFIX = 'highcharts-',
- activeClass = PREFIX + 'active';
- H.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
- * @type {Object}
- */
- 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'
- }
- }
- },
- /**
- * 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
- * @type {Object}
- * @optionparent stockTools
- */
- stockTools: {
- /**
- * Definitions of buttons in Stock Tools GUI.
- */
- gui: {
- /**
- * Enable or disable the stockTools gui.
- *
- * @type {boolean}
- * @default true
- */
- enabled: true,
- /**
- * A CSS class name to apply to the stocktools' div,
- * allowing unique CSS styling for each chart.
- *
- * @type {string}
- * @default 'highcharts-bindings-wrapper'
- *
- */
- className: 'highcharts-bindings-wrapper',
- /**
- * A CSS class name to apply to the container of buttons,
- * allowing unique CSS styling for each chart.
- *
- * @type {string}
- * @default 'stocktools-toolbar'
- *
- */
- toolbarClassName: 'stocktools-toolbar',
- /**
- * Path where Highcharts will look for icons. Change this to use
- * icons from a different server.
- */
- iconsURL: 'https://code.highcharts.com/7.0.2/gfx/stock-icons/',
- /**
- * A collection of strings pointing to config options for the
- * toolbar items. Each name refers to unique key from definitions
- * object.
- *
- * @type {array}
- *
- * @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.
- *
- * @type {object}
- *
- */
- definitions: {
- separator: {
- /**
- * A predefined background symbol for the button.
- *
- * @type {string}
- */
- 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'
- }
- }
- }
- }
- });
- // Run HTML generator
- addEvent(H.Chart, 'afterGetContainer', function () {
- this.setStockTools();
- });
- addEvent(H.Chart, 'getMargins', function () {
- var offsetWidth = (
- this.stockTools &&
- this.stockTools.listWrapper &&
- this.stockTools.listWrapper.offsetWidth
- );
- if (offsetWidth && offsetWidth < this.plotWidth) {
- this.plotLeft += offsetWidth;
- }
- });
- addEvent(H.Chart, 'destroy', function () {
- if (this.stockTools) {
- this.stockTools.destroy();
- }
- });
- addEvent(H.Chart, 'redraw', function () {
- if (this.stockTools && this.stockTools.guiEnabled) {
- this.stockTools.redraw();
- }
- });
- /*
- * Toolbar Class
- *
- * @param {Object} - options of toolbar
- * @param {Chart} - Reference to chart
- *
- */
- H.Toolbar = function (options, langOptions, chart) {
- this.chart = chart;
- this.options = options;
- this.lang = langOptions;
- 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');
- };
- H.extend(H.Chart.prototype, {
- /*
- * Verify if Toolbar should be added.
- *
- * @param {Object} - chart options
- *
- */
- setStockTools: function (options) {
- var chartOptions = this.options,
- lang = chartOptions.lang,
- guiOptions = merge(
- chartOptions.stockTools && chartOptions.stockTools.gui,
- options && options.gui
- ),
- langOptions = lang.stockTools && lang.stockTools.gui;
- this.stockTools = new H.Toolbar(guiOptions, langOptions, this);
- if (this.stockTools.guiEnabled) {
- this.isDirtyBox = true;
- }
- }
- });
- H.Toolbar.prototype = {
- /*
- * Initialize the toolbar. Create buttons and submenu for each option
- * defined in `stockTools.gui`.
- *
- */
- 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,
- inIframe = this.inIframe(),
- button;
- // create buttons
- buttons.forEach(function (btnName) {
- button = _self.addButton(toolbar, defs, btnName, lang);
- if (inIframe && btnName === 'fullScreen') {
- button.buttonWrapper.className += ' ' + PREFIX + 'disabled-btn';
- }
- ['click', 'touchstart'].forEach(function (eventName) {
- addEvent(button.buttonWrapper, eventName, 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.
- *
- * @param {Object} - button which has submenu
- * @param {Array} - list of all buttons
- *
- */
- 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'
- }, null, buttonWrapper);
- // create submenu buttons and select the first one
- this.addSubmenuItems(buttonWrapper, button);
- // show / hide submenu
- ['click', 'touchstart'].forEach(function (eventName) {
- addEvent(submenuArrow, eventName, 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 +
- H.getStyle(menuWrapper, 'padding-left') +
- submenuWrapper.offsetWidth + 3 + 'px';
- }
- });
- });
- },
- /*
- * Create buttons in submenu
- *
- * @param {HTMLDOMElement} - button where submenu is placed
- * @param {Array} - list of all buttons options
- *
- */
- 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
- );
- ['click', 'touchstart'].forEach(function (eventName) {
- addEvent(submenuBtn.mainButton, eventName, 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
- *
- */
- 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 `<li>` , `<span>` and (if exists)
- * submenu container.
- *
- * @param {HTMLDOMElement} - HTML reference, where button should be added
- * @param {Object} - all options, by btnName refer to particular button
- * @param {String} - name of functionality mapped for specific class
- * @param {Object} - All titles, by btnName refer to particular button
- *
- * @return {Object} - references to all created HTML elements
- */
- addButton: function (target, options, btnName, lang) {
- var guiOptions = this.options,
- btnOptions = options[btnName],
- items = btnOptions.items,
- classMapping = H.Toolbar.prototype.classMapping,
- userClassName = btnOptions.className || '',
- mainButton,
- submenuArrow,
- buttonWrapper;
- // main button wrapper
- buttonWrapper = createElement(LI, {
- className: pick(classMapping[btnName], '') + ' ' + userClassName,
- title: lang[btnName] || btnName
- }, null, target);
- // single button
- mainButton = createElement(SPAN, {
- className: PREFIX + 'menu-item-btn'
- }, null, buttonWrapper);
- // submenu
- if (items && items.length > 1) {
- // arrow is a hook to show / hide submenu
- submenuArrow = createElement(SPAN, {
- className: PREFIX + 'submenu-item-arrow ' +
- PREFIX + 'arrow-right'
- }, null, buttonWrapper);
- } else {
- mainButton.style['background-image'] = 'url(' +
- guiOptions.iconsURL + btnOptions.symbol + ')';
- }
- return {
- buttonWrapper: buttonWrapper,
- mainButton: mainButton,
- submenuArrow: submenuArrow
- };
- },
- /*
- * Create navigation's HTML elements: container and arrows.
- *
- */
- 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'
- }, null, stockToolbar.arrowWrapper);
- stockToolbar.arrowDown = createElement(DIV, {
- className: PREFIX + 'arrow-down'
- }, null, stockToolbar.arrowWrapper);
- 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.
- *
- */
- scrollButtons: function () {
- var targetY = 0,
- _self = this,
- wrapper = _self.wrapper,
- toolbar = _self.toolbar,
- step = 0.1 * wrapper.offsetHeight; // 0.1 = 10%
- ['click', 'touchstart'].forEach(function (eventName) {
- addEvent(_self.arrowUp, eventName, function () {
- if (targetY > 0) {
- targetY -= step;
- toolbar.style['margin-top'] = -targetY + 'px';
- }
- });
- addEvent(_self.arrowDown, eventName, function () {
- if (
- wrapper.offsetHeight + targetY <=
- toolbar.offsetHeight + step
- ) {
- targetY += step;
- toolbar.style['margin-top'] = -targetY + 'px';
- }
- });
- });
- },
- /*
- * Create stockTools HTML main elements.
- *
- */
- createHTML: function () {
- var stockToolbar = this,
- chart = stockToolbar.chart,
- guiOptions = stockToolbar.options,
- container = chart.container,
- listWrapper,
- toolbar,
- wrapper;
- // create main container
- stockToolbar.wrapper = wrapper = createElement(DIV, {
- className: PREFIX + 'stocktools-wrapper ' +
- guiOptions.className
- });
- container.parentNode.insertBefore(wrapper, container);
- // 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.
- *
- */
- 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.
- *
- */
- 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'
- }, null, wrapper);
- 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');
- } else {
- showhideBtn.style.top = H.getStyle(toolbar, 'padding-top') + 'px';
- showhideBtn.style.left = (
- wrapper.offsetWidth +
- H.getStyle(toolbar, 'padding-left')
- ) + 'px';
- }
- // toggle menu
- ['click', 'touchstart'].forEach(function (eventName) {
- addEvent(showhideBtn, eventName, 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
- *
- */
- switchSymbol: function (button, redraw) {
- var buttonWrapper = button.parentNode,
- buttonWrapperClass = buttonWrapper.classList.value,
- // main button in first level og GUI
- mainNavButton = buttonWrapper.parentNode.parentNode;
- // set class
- mainNavButton.className = '';
- if (buttonWrapperClass) {
- mainNavButton.classList.add(buttonWrapperClass.trim());
- }
- // set icon
- mainNavButton.querySelectorAll('.' + PREFIX + 'menu-item-btn')[0]
- .style['background-image'] = button.style['background-image'];
- // set active class
- if (redraw) {
- this.selectButton(mainNavButton);
- }
- },
- /*
- * Set select state (active class) on button.
- *
- * @param {HTMLDOMElement} - button
- *
- */
- selectButton: function (btn) {
- if (btn.className.indexOf(activeClass) >= 0) {
- btn.classList.remove(activeClass);
- } else {
- btn.classList.add(activeClass);
- }
- },
- /*
- * Remove active class from all buttons except defined.
- *
- * @param {HTMLDOMElement} - button which should not be deactivated
- *
- */
- unselectAllButtons: function (btn) {
- var activeButtons = btn.parentNode.querySelectorAll('.' + activeClass);
- [].forEach.call(activeButtons, function (activeBtn) {
- if (activeBtn !== btn) {
- activeBtn.classList.remove(activeClass);
- }
- });
- },
- /*
- * Verify if chart is in iframe.
- *
- * @return {Object} - elements translations.
- */
- inIframe: function () {
- try {
- return win.self !== win.top;
- } catch (e) {
- return true;
- }
- },
- /*
- * Update GUI with given options.
- *
- * @param {Object} - general options for Stock Tools
- */
- update: function (options) {
- 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();
- }
- },
- /*
- * Destroy all HTML GUI elements.
- *
- */
- 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
- this.chart.isDirtyBox = true;
- this.chart.redraw();
- },
- /*
- * Redraw, GUI requires to verify if the navigation should be visible.
- *
- */
- redraw: function () {
- this.showHideNavigatorion();
- },
- /*
- * Mapping JSON fields to CSS classes.
- *
- */
- 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'
- }
- };
- // Comunication with bindings:
- addEvent(H.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(H.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);
- }
- });
- }(Highcharts));
- return (function () {
- }());
- }));
|