highcharts-more.src.js 173 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489
  1. /**
  2. * @license Highcharts JS v6.1.0 (2018-04-13)
  3. *
  4. * (c) 2009-2016 Torstein Honsi
  5. *
  6. * License: www.highcharts.com/license
  7. */
  8. 'use strict';
  9. (function (factory) {
  10. if (typeof module === 'object' && module.exports) {
  11. module.exports = factory;
  12. } else {
  13. factory(Highcharts);
  14. }
  15. }(function (Highcharts) {
  16. (function (H) {
  17. /**
  18. * (c) 2010-2017 Torstein Honsi
  19. *
  20. * License: www.highcharts.com/license
  21. */
  22. var CenteredSeriesMixin = H.CenteredSeriesMixin,
  23. each = H.each,
  24. extend = H.extend,
  25. merge = H.merge,
  26. splat = H.splat;
  27. /**
  28. * The Pane object allows options that are common to a set of X and Y axes.
  29. *
  30. * In the future, this can be extended to basic Highcharts and Highstock.
  31. *
  32. */
  33. function Pane(options, chart) {
  34. this.init(options, chart);
  35. }
  36. // Extend the Pane prototype
  37. extend(Pane.prototype, {
  38. coll: 'pane', // Member of chart.pane
  39. /**
  40. * Initiate the Pane object
  41. */
  42. init: function (options, chart) {
  43. this.chart = chart;
  44. this.background = [];
  45. chart.pane.push(this);
  46. this.setOptions(options);
  47. },
  48. setOptions: function (options) {
  49. // Set options. Angular charts have a default background (#3318)
  50. this.options = options = merge(
  51. this.defaultOptions,
  52. this.chart.angular ? { background: {} } : undefined,
  53. options
  54. );
  55. },
  56. /**
  57. * Render the pane with its backgrounds.
  58. */
  59. render: function () {
  60. var options = this.options,
  61. backgroundOption = this.options.background,
  62. renderer = this.chart.renderer,
  63. len,
  64. i;
  65. if (!this.group) {
  66. this.group = renderer.g('pane-group')
  67. .attr({ zIndex: options.zIndex || 0 })
  68. .add();
  69. }
  70. this.updateCenter();
  71. // Render the backgrounds
  72. if (backgroundOption) {
  73. backgroundOption = splat(backgroundOption);
  74. len = Math.max(
  75. backgroundOption.length,
  76. this.background.length || 0
  77. );
  78. for (i = 0; i < len; i++) {
  79. // #6641 - if axis exists, chart is circular and apply
  80. // background
  81. if (backgroundOption[i] && this.axis) {
  82. this.renderBackground(
  83. merge(
  84. this.defaultBackgroundOptions,
  85. backgroundOption[i]
  86. ),
  87. i
  88. );
  89. } else if (this.background[i]) {
  90. this.background[i] = this.background[i].destroy();
  91. this.background.splice(i, 1);
  92. }
  93. }
  94. }
  95. },
  96. /**
  97. * Render an individual pane background.
  98. * @param {Object} backgroundOptions Background options
  99. * @param {number} i The index of the background in this.backgrounds
  100. */
  101. renderBackground: function (backgroundOptions, i) {
  102. var method = 'animate';
  103. if (!this.background[i]) {
  104. this.background[i] = this.chart.renderer.path()
  105. .add(this.group);
  106. method = 'attr';
  107. }
  108. this.background[i][method]({
  109. 'd': this.axis.getPlotBandPath(
  110. backgroundOptions.from,
  111. backgroundOptions.to,
  112. backgroundOptions
  113. )
  114. }).attr({
  115. 'fill': backgroundOptions.backgroundColor,
  116. 'stroke': backgroundOptions.borderColor,
  117. 'stroke-width': backgroundOptions.borderWidth,
  118. 'class': 'highcharts-pane ' + (backgroundOptions.className || '')
  119. });
  120. },
  121. /**
  122. * The pane serves as a container for axes and backgrounds for circular
  123. * gauges and polar charts.
  124. * @since 2.3.0
  125. * @optionparent pane
  126. */
  127. defaultOptions: {
  128. /**
  129. * The end angle of the polar X axis or gauge value axis, given in
  130. * degrees where 0 is north. Defaults to [startAngle](#pane.startAngle)
  131. * + 360.
  132. *
  133. * @type {Number}
  134. * @sample {highcharts} highcharts/demo/gauge-vu-meter/
  135. * VU-meter with custom start and end angle
  136. * @since 2.3.0
  137. * @product highcharts
  138. * @apioption pane.endAngle
  139. */
  140. /**
  141. * The center of a polar chart or angular gauge, given as an array
  142. * of [x, y] positions. Positions can be given as integers that
  143. * transform to pixels, or as percentages of the plot area size.
  144. *
  145. * @type {Array<String|Number>}
  146. * @sample {highcharts} highcharts/demo/gauge-vu-meter/
  147. * Two gauges with different center
  148. * @default ["50%", "50%"]
  149. * @since 2.3.0
  150. * @product highcharts
  151. */
  152. center: ['50%', '50%'],
  153. /**
  154. * The size of the pane, either as a number defining pixels, or a
  155. * percentage defining a percentage of the plot are.
  156. *
  157. * @type {Number|String}
  158. * @sample {highcharts} highcharts/demo/gauge-vu-meter/ Smaller size
  159. * @default 85%
  160. * @product highcharts
  161. */
  162. size: '85%',
  163. /**
  164. * The start angle of the polar X axis or gauge axis, given in degrees
  165. * where 0 is north. Defaults to 0.
  166. *
  167. * @type {Number}
  168. * @sample {highcharts} highcharts/demo/gauge-vu-meter/
  169. * VU-meter with custom start and end angle
  170. * @since 2.3.0
  171. * @product highcharts
  172. */
  173. startAngle: 0
  174. },
  175. /**
  176. * An array of background items for the pane.
  177. * @type Array.<Object>
  178. * @sample {highcharts} highcharts/demo/gauge-speedometer/
  179. * Speedometer gauge with multiple backgrounds
  180. * @optionparent pane.background
  181. */
  182. defaultBackgroundOptions: {
  183. /**
  184. * The class name for this background.
  185. *
  186. * @type {String}
  187. * @sample {highcharts} highcharts/css/pane/ Panes styled by CSS
  188. * @sample {highstock} highcharts/css/pane/ Panes styled by CSS
  189. * @sample {highmaps} highcharts/css/pane/ Panes styled by CSS
  190. * @default highcharts-pane
  191. * @since 5.0.0
  192. * @apioption pane.background.className
  193. */
  194. /**
  195. * Tha shape of the pane background. When `solid`, the background
  196. * is circular. When `arc`, the background extends only from the min
  197. * to the max of the value axis.
  198. *
  199. * @validvalue ["solid", "arc"]
  200. * @type {String}
  201. * @default solid
  202. * @since 2.3.0
  203. * @product highcharts
  204. */
  205. shape: 'circle',
  206. /**
  207. * The pixel border width of the pane background.
  208. *
  209. * @type {Number}
  210. * @default 1
  211. * @since 2.3.0
  212. * @product highcharts
  213. */
  214. borderWidth: 1,
  215. /**
  216. * The pane background border color.
  217. *
  218. * @type {Color}
  219. * @default #cccccc
  220. * @since 2.3.0
  221. * @product highcharts
  222. */
  223. borderColor: '#cccccc',
  224. /**
  225. * The background color or gradient for the pane.
  226. *
  227. * @type {Color}
  228. * @since 2.3.0
  229. * @product highcharts
  230. */
  231. backgroundColor: {
  232. /**
  233. * Definition of the gradient, similar to SVG: object literal holds
  234. * start position (x1, y1) and the end position (x2, y2) relative
  235. * to the shape, where 0 means top/left and 1 is bottom/right.
  236. * All positions are floats between 0 and 1.
  237. *
  238. * @type {Object}
  239. */
  240. linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
  241. /**
  242. * The stops is an array of tuples, where the first item is a float
  243. * between 0 and 1 assigning the relative position in the gradient,
  244. * and the second item is the color.
  245. *
  246. * @default [[0, #ffffff], [1, #e6e6e6]]
  247. * @type {Array<Array>}
  248. */
  249. stops: [
  250. [0, '#ffffff'],
  251. [1, '#e6e6e6']
  252. ]
  253. },
  254. /** @ignore-option */
  255. from: -Number.MAX_VALUE, // corrected to axis min
  256. /**
  257. * The inner radius of the pane background. Can be either numeric
  258. * (pixels) or a percentage string.
  259. *
  260. * @type {Number|String}
  261. * @default 0
  262. * @since 2.3.0
  263. * @product highcharts
  264. */
  265. innerRadius: 0,
  266. /** @ignore-option */
  267. to: Number.MAX_VALUE, // corrected to axis max
  268. /**
  269. * The outer radius of the circular pane background. Can be either
  270. * numeric (pixels) or a percentage string.
  271. *
  272. * @type {Number|String}
  273. * @default 105%
  274. * @since 2.3.0
  275. * @product highcharts
  276. */
  277. outerRadius: '105%'
  278. },
  279. /**
  280. * Gets the center for the pane and its axis.
  281. */
  282. updateCenter: function (axis) {
  283. this.center = (axis || this.axis || {}).center =
  284. CenteredSeriesMixin.getCenter.call(this);
  285. },
  286. /**
  287. * Destroy the pane item
  288. * /
  289. destroy: function () {
  290. H.erase(this.chart.pane, this);
  291. each(this.background, function (background) {
  292. background.destroy();
  293. });
  294. this.background.length = 0;
  295. this.group = this.group.destroy();
  296. },
  297. */
  298. /**
  299. * Update the pane item with new options
  300. * @param {Object} options New pane options
  301. */
  302. update: function (options, redraw) {
  303. merge(true, this.options, options);
  304. this.setOptions(this.options);
  305. this.render();
  306. each(this.chart.axes, function (axis) {
  307. if (axis.pane === this) {
  308. axis.pane = null;
  309. axis.update({}, redraw);
  310. }
  311. }, this);
  312. }
  313. });
  314. H.Pane = Pane;
  315. }(Highcharts));
  316. (function (H) {
  317. /**
  318. * (c) 2010-2017 Torstein Honsi
  319. *
  320. * License: www.highcharts.com/license
  321. */
  322. var addEvent = H.addEvent,
  323. Axis = H.Axis,
  324. each = H.each,
  325. extend = H.extend,
  326. map = H.map,
  327. merge = H.merge,
  328. noop = H.noop,
  329. pick = H.pick,
  330. pInt = H.pInt,
  331. Tick = H.Tick,
  332. wrap = H.wrap,
  333. correctFloat = H.correctFloat,
  334. hiddenAxisMixin, // @todo Extract this to a new file
  335. radialAxisMixin, // @todo Extract this to a new file
  336. axisProto = Axis.prototype,
  337. tickProto = Tick.prototype;
  338. if (!H.radialAxisExtended) {
  339. H.radialAxisExtended = true;
  340. /**
  341. * Augmented methods for the x axis in order to hide it completely, used for
  342. * the X axis in gauges
  343. */
  344. hiddenAxisMixin = {
  345. getOffset: noop,
  346. redraw: function () {
  347. this.isDirty = false; // prevent setting Y axis dirty
  348. },
  349. render: function () {
  350. this.isDirty = false; // prevent setting Y axis dirty
  351. },
  352. setScale: noop,
  353. setCategories: noop,
  354. setTitle: noop
  355. };
  356. /**
  357. * Augmented methods for the value axis
  358. */
  359. radialAxisMixin = {
  360. /**
  361. * The default options extend defaultYAxisOptions
  362. */
  363. defaultRadialGaugeOptions: {
  364. labels: {
  365. align: 'center',
  366. x: 0,
  367. y: null // auto
  368. },
  369. minorGridLineWidth: 0,
  370. minorTickInterval: 'auto',
  371. minorTickLength: 10,
  372. minorTickPosition: 'inside',
  373. minorTickWidth: 1,
  374. tickLength: 10,
  375. tickPosition: 'inside',
  376. tickWidth: 2,
  377. title: {
  378. rotation: 0
  379. },
  380. zIndex: 2 // behind dials, points in the series group
  381. },
  382. // Circular axis around the perimeter of a polar chart
  383. defaultRadialXOptions: {
  384. gridLineWidth: 1, // spokes
  385. labels: {
  386. align: null, // auto
  387. distance: 15,
  388. x: 0,
  389. y: null, // auto
  390. style: {
  391. textOverflow: 'none' // wrap lines by default (#7248)
  392. }
  393. },
  394. maxPadding: 0,
  395. minPadding: 0,
  396. showLastLabel: false,
  397. tickLength: 0
  398. },
  399. // Radial axis, like a spoke in a polar chart
  400. defaultRadialYOptions: {
  401. gridLineInterpolation: 'circle',
  402. labels: {
  403. align: 'right',
  404. x: -3,
  405. y: -2
  406. },
  407. showLastLabel: false,
  408. title: {
  409. x: 4,
  410. text: null,
  411. rotation: 90
  412. }
  413. },
  414. /**
  415. * Merge and set options
  416. */
  417. setOptions: function (userOptions) {
  418. var options = this.options = merge(
  419. this.defaultOptions,
  420. this.defaultRadialOptions,
  421. userOptions
  422. );
  423. // Make sure the plotBands array is instanciated for each Axis
  424. // (#2649)
  425. if (!options.plotBands) {
  426. options.plotBands = [];
  427. }
  428. },
  429. /**
  430. * Wrap the getOffset method to return zero offset for title or labels
  431. * in a radial axis
  432. */
  433. getOffset: function () {
  434. // Call the Axis prototype method (the method we're in now is on the
  435. // instance)
  436. axisProto.getOffset.call(this);
  437. // Title or label offsets are not counted
  438. this.chart.axisOffset[this.side] = 0;
  439. },
  440. /**
  441. * Get the path for the axis line. This method is also referenced in the
  442. * getPlotLinePath method.
  443. */
  444. getLinePath: function (lineWidth, radius) {
  445. var center = this.center,
  446. end,
  447. chart = this.chart,
  448. r = pick(radius, center[2] / 2 - this.offset),
  449. path;
  450. if (this.isCircular || radius !== undefined) {
  451. path = this.chart.renderer.symbols.arc(
  452. this.left + center[0],
  453. this.top + center[1],
  454. r,
  455. r,
  456. {
  457. start: this.startAngleRad,
  458. end: this.endAngleRad,
  459. open: true,
  460. innerR: 0
  461. }
  462. );
  463. // Bounds used to position the plotLine label next to the line
  464. // (#7117)
  465. path.xBounds = [this.left + center[0]];
  466. path.yBounds = [this.top + center[1] - r];
  467. } else {
  468. end = this.postTranslate(this.angleRad, r);
  469. path = [
  470. 'M',
  471. center[0] + chart.plotLeft,
  472. center[1] + chart.plotTop,
  473. 'L',
  474. end.x,
  475. end.y
  476. ];
  477. }
  478. return path;
  479. },
  480. /**
  481. * Override setAxisTranslation by setting the translation to the
  482. * difference in rotation. This allows the translate method to return
  483. * angle for any given value.
  484. */
  485. setAxisTranslation: function () {
  486. // Call uber method
  487. axisProto.setAxisTranslation.call(this);
  488. // Set transA and minPixelPadding
  489. if (this.center) { // it's not defined the first time
  490. if (this.isCircular) {
  491. this.transA = (this.endAngleRad - this.startAngleRad) /
  492. ((this.max - this.min) || 1);
  493. } else {
  494. this.transA = (
  495. (this.center[2] / 2) /
  496. ((this.max - this.min) || 1)
  497. );
  498. }
  499. if (this.isXAxis) {
  500. this.minPixelPadding = this.transA * this.minPointOffset;
  501. } else {
  502. // This is a workaround for regression #2593, but categories
  503. // still don't position correctly.
  504. this.minPixelPadding = 0;
  505. }
  506. }
  507. },
  508. /**
  509. * In case of auto connect, add one closestPointRange to the max value
  510. * right before tickPositions are computed, so that ticks will extend
  511. * passed the real max.
  512. */
  513. beforeSetTickPositions: function () {
  514. // If autoConnect is true, polygonal grid lines are connected, and
  515. // one closestPointRange is added to the X axis to prevent the last
  516. // point from overlapping the first.
  517. this.autoConnect = (
  518. this.isCircular &&
  519. pick(this.userMax, this.options.max) === undefined &&
  520. correctFloat(this.endAngleRad - this.startAngleRad) ===
  521. correctFloat(2 * Math.PI)
  522. );
  523. if (this.autoConnect) {
  524. this.max += (
  525. (this.categories && 1) ||
  526. this.pointRange ||
  527. this.closestPointRange ||
  528. 0
  529. ); // #1197, #2260
  530. }
  531. },
  532. /**
  533. * Override the setAxisSize method to use the arc's circumference as
  534. * length. This allows tickPixelInterval to apply to pixel lengths along
  535. * the perimeter
  536. */
  537. setAxisSize: function () {
  538. axisProto.setAxisSize.call(this);
  539. if (this.isRadial) {
  540. // Set the center array
  541. this.pane.updateCenter(this);
  542. // The sector is used in Axis.translate to compute the
  543. // translation of reversed axis points (#2570)
  544. if (this.isCircular) {
  545. this.sector = this.endAngleRad - this.startAngleRad;
  546. }
  547. // Axis len is used to lay out the ticks
  548. this.len = this.width = this.height =
  549. this.center[2] * pick(this.sector, 1) / 2;
  550. }
  551. },
  552. /**
  553. * Returns the x, y coordinate of a point given by a value and a pixel
  554. * distance from center
  555. */
  556. getPosition: function (value, length) {
  557. return this.postTranslate(
  558. this.isCircular ?
  559. this.translate(value) :
  560. this.angleRad, // #2848
  561. pick(
  562. this.isCircular ? length : this.translate(value),
  563. this.center[2] / 2
  564. ) - this.offset
  565. );
  566. },
  567. /**
  568. * Translate from intermediate plotX (angle), plotY (axis.len - radius)
  569. * to final chart coordinates.
  570. */
  571. postTranslate: function (angle, radius) {
  572. var chart = this.chart,
  573. center = this.center;
  574. angle = this.startAngleRad + angle;
  575. return {
  576. x: chart.plotLeft + center[0] + Math.cos(angle) * radius,
  577. y: chart.plotTop + center[1] + Math.sin(angle) * radius
  578. };
  579. },
  580. /**
  581. * Find the path for plot bands along the radial axis
  582. */
  583. getPlotBandPath: function (from, to, options) {
  584. var center = this.center,
  585. startAngleRad = this.startAngleRad,
  586. fullRadius = center[2] / 2,
  587. radii = [
  588. pick(options.outerRadius, '100%'),
  589. options.innerRadius,
  590. pick(options.thickness, 10)
  591. ],
  592. offset = Math.min(this.offset, 0),
  593. percentRegex = /%$/,
  594. start,
  595. end,
  596. open,
  597. isCircular = this.isCircular, // X axis in a polar chart
  598. ret;
  599. // Polygonal plot bands
  600. if (this.options.gridLineInterpolation === 'polygon') {
  601. ret = this.getPlotLinePath(from).concat(
  602. this.getPlotLinePath(to, true)
  603. );
  604. // Circular grid bands
  605. } else {
  606. // Keep within bounds
  607. from = Math.max(from, this.min);
  608. to = Math.min(to, this.max);
  609. // Plot bands on Y axis (radial axis) - inner and outer radius
  610. // depend on to and from
  611. if (!isCircular) {
  612. radii[0] = this.translate(from);
  613. radii[1] = this.translate(to);
  614. }
  615. // Convert percentages to pixel values
  616. radii = map(radii, function (radius) {
  617. if (percentRegex.test(radius)) {
  618. radius = (pInt(radius, 10) * fullRadius) / 100;
  619. }
  620. return radius;
  621. });
  622. // Handle full circle
  623. if (options.shape === 'circle' || !isCircular) {
  624. start = -Math.PI / 2;
  625. end = Math.PI * 1.5;
  626. open = true;
  627. } else {
  628. start = startAngleRad + this.translate(from);
  629. end = startAngleRad + this.translate(to);
  630. }
  631. radii[0] -= offset; // #5283
  632. radii[2] -= offset; // #5283
  633. ret = this.chart.renderer.symbols.arc(
  634. this.left + center[0],
  635. this.top + center[1],
  636. radii[0],
  637. radii[0],
  638. {
  639. // Math is for reversed yAxis (#3606)
  640. start: Math.min(start, end),
  641. end: Math.max(start, end),
  642. innerR: pick(radii[1], radii[0] - radii[2]),
  643. open: open
  644. }
  645. );
  646. }
  647. return ret;
  648. },
  649. /**
  650. * Find the path for plot lines perpendicular to the radial axis.
  651. */
  652. getPlotLinePath: function (value, reverse) {
  653. var axis = this,
  654. center = axis.center,
  655. chart = axis.chart,
  656. end = axis.getPosition(value),
  657. xAxis,
  658. xy,
  659. tickPositions,
  660. ret;
  661. // Spokes
  662. if (axis.isCircular) {
  663. ret = [
  664. 'M',
  665. center[0] + chart.plotLeft,
  666. center[1] + chart.plotTop,
  667. 'L',
  668. end.x,
  669. end.y
  670. ];
  671. // Concentric circles
  672. } else if (axis.options.gridLineInterpolation === 'circle') {
  673. value = axis.translate(value);
  674. if (value) { // a value of 0 is in the center
  675. ret = axis.getLinePath(0, value);
  676. }
  677. // Concentric polygons
  678. } else {
  679. // Find the X axis in the same pane
  680. each(chart.xAxis, function (a) {
  681. if (a.pane === axis.pane) {
  682. xAxis = a;
  683. }
  684. });
  685. ret = [];
  686. value = axis.translate(value);
  687. tickPositions = xAxis.tickPositions;
  688. if (xAxis.autoConnect) {
  689. tickPositions = tickPositions.concat([tickPositions[0]]);
  690. }
  691. // Reverse the positions for concatenation of polygonal plot
  692. // bands
  693. if (reverse) {
  694. tickPositions = [].concat(tickPositions).reverse();
  695. }
  696. each(tickPositions, function (pos, i) {
  697. xy = xAxis.getPosition(pos, value);
  698. ret.push(i ? 'L' : 'M', xy.x, xy.y);
  699. });
  700. }
  701. return ret;
  702. },
  703. /**
  704. * Find the position for the axis title, by default inside the gauge
  705. */
  706. getTitlePosition: function () {
  707. var center = this.center,
  708. chart = this.chart,
  709. titleOptions = this.options.title;
  710. return {
  711. x: chart.plotLeft + center[0] + (titleOptions.x || 0),
  712. y: (
  713. chart.plotTop +
  714. center[1] -
  715. (
  716. {
  717. high: 0.5,
  718. middle: 0.25,
  719. low: 0
  720. }[titleOptions.align] * center[2]
  721. ) +
  722. (titleOptions.y || 0)
  723. )
  724. };
  725. }
  726. };
  727. /**
  728. * Actions before axis init.
  729. */
  730. addEvent(Axis, 'init', function (e) {
  731. var chart = this.chart,
  732. angular = chart.angular,
  733. polar = chart.polar,
  734. isX = this.isXAxis,
  735. isHidden = angular && isX,
  736. isCircular,
  737. chartOptions = chart.options,
  738. paneIndex = e.userOptions.pane || 0,
  739. pane = this.pane = chart.pane && chart.pane[paneIndex];
  740. // Before prototype.init
  741. if (angular) {
  742. extend(this, isHidden ? hiddenAxisMixin : radialAxisMixin);
  743. isCircular = !isX;
  744. if (isCircular) {
  745. this.defaultRadialOptions = this.defaultRadialGaugeOptions;
  746. }
  747. } else if (polar) {
  748. extend(this, radialAxisMixin);
  749. isCircular = isX;
  750. this.defaultRadialOptions = isX ?
  751. this.defaultRadialXOptions :
  752. merge(this.defaultYAxisOptions, this.defaultRadialYOptions);
  753. }
  754. // Disable certain features on angular and polar axes
  755. if (angular || polar) {
  756. this.isRadial = true;
  757. chart.inverted = false;
  758. chartOptions.chart.zoomType = null;
  759. } else {
  760. this.isRadial = false;
  761. }
  762. // A pointer back to this axis to borrow geometry
  763. if (pane && isCircular) {
  764. pane.axis = this;
  765. }
  766. this.isCircular = isCircular;
  767. });
  768. addEvent(Axis, 'afterInit', function () {
  769. var chart = this.chart,
  770. options = this.options,
  771. isHidden = chart.angular && this.isXAxis,
  772. pane = this.pane,
  773. paneOptions = pane && pane.options;
  774. if (!isHidden && pane && (chart.angular || chart.polar)) {
  775. // Start and end angle options are
  776. // given in degrees relative to top, while internal computations are
  777. // in radians relative to right (like SVG).
  778. // Y axis in polar charts
  779. this.angleRad = (options.angle || 0) * Math.PI / 180;
  780. // Gauges
  781. this.startAngleRad = (paneOptions.startAngle - 90) * Math.PI / 180;
  782. this.endAngleRad = (
  783. pick(paneOptions.endAngle, paneOptions.startAngle + 360) - 90
  784. ) * Math.PI / 180; // Gauges
  785. this.offset = options.offset || 0;
  786. }
  787. });
  788. /**
  789. * Wrap auto label align to avoid setting axis-wide rotation on radial axes
  790. * (#4920)
  791. * @param {Function} proceed
  792. * @returns {String} Alignment
  793. */
  794. wrap(axisProto, 'autoLabelAlign', function (proceed) {
  795. if (!this.isRadial) {
  796. return proceed.apply(this, [].slice.call(arguments, 1));
  797. } // else return undefined
  798. });
  799. /**
  800. * Add special cases within the Tick class' methods for radial axes.
  801. */
  802. addEvent(Tick, 'afterGetPosition', function (e) {
  803. if (this.axis.getPosition) {
  804. extend(e.pos, this.axis.getPosition(this.pos));
  805. }
  806. });
  807. /**
  808. * Find the center position of the label based on the distance option.
  809. */
  810. addEvent(Tick, 'afterGetLabelPosition', function (e) {
  811. var axis = this.axis,
  812. label = this.label,
  813. labelOptions = axis.options.labels,
  814. optionsY = labelOptions.y,
  815. ret,
  816. centerSlot = 20, // 20 degrees to each side at the top and bottom
  817. align = labelOptions.align,
  818. angle = (
  819. (axis.translate(this.pos) + axis.startAngleRad + Math.PI / 2) /
  820. Math.PI * 180
  821. ) % 360;
  822. if (axis.isRadial) { // Both X and Y axes in a polar chart
  823. ret = axis.getPosition(this.pos, (axis.center[2] / 2) +
  824. pick(labelOptions.distance, -25));
  825. // Automatically rotated
  826. if (labelOptions.rotation === 'auto') {
  827. label.attr({
  828. rotation: angle
  829. });
  830. // Vertically centered
  831. } else if (optionsY === null) {
  832. optionsY = (
  833. axis.chart.renderer
  834. .fontMetrics(label.styles && label.styles.fontSize).b -
  835. label.getBBox().height / 2
  836. );
  837. }
  838. // Automatic alignment
  839. if (align === null) {
  840. if (axis.isCircular) { // Y axis
  841. if (
  842. this.label.getBBox().width >
  843. axis.len * axis.tickInterval / (axis.max - axis.min)
  844. ) { // #3506
  845. centerSlot = 0;
  846. }
  847. if (angle > centerSlot && angle < 180 - centerSlot) {
  848. align = 'left'; // right hemisphere
  849. } else if (
  850. angle > 180 + centerSlot &&
  851. angle < 360 - centerSlot
  852. ) {
  853. align = 'right'; // left hemisphere
  854. } else {
  855. align = 'center'; // top or bottom
  856. }
  857. } else {
  858. align = 'center';
  859. }
  860. label.attr({
  861. align: align
  862. });
  863. }
  864. e.pos.x = ret.x + labelOptions.x;
  865. e.pos.y = ret.y + optionsY;
  866. }
  867. });
  868. /**
  869. * Wrap the getMarkPath function to return the path of the radial marker
  870. */
  871. wrap(tickProto, 'getMarkPath', function (
  872. proceed,
  873. x,
  874. y,
  875. tickLength,
  876. tickWidth,
  877. horiz,
  878. renderer
  879. ) {
  880. var axis = this.axis,
  881. endPoint,
  882. ret;
  883. if (axis.isRadial) {
  884. endPoint = axis.getPosition(
  885. this.pos,
  886. axis.center[2] / 2 + tickLength
  887. );
  888. ret = [
  889. 'M',
  890. x,
  891. y,
  892. 'L',
  893. endPoint.x,
  894. endPoint.y
  895. ];
  896. } else {
  897. ret = proceed.call(
  898. this,
  899. x,
  900. y,
  901. tickLength,
  902. tickWidth,
  903. horiz,
  904. renderer
  905. );
  906. }
  907. return ret;
  908. });
  909. }
  910. }(Highcharts));
  911. (function (H) {
  912. /**
  913. * (c) 2010-2017 Torstein Honsi
  914. *
  915. * License: www.highcharts.com/license
  916. */
  917. var each = H.each,
  918. noop = H.noop,
  919. pick = H.pick,
  920. defined = H.defined,
  921. Series = H.Series,
  922. seriesType = H.seriesType,
  923. seriesTypes = H.seriesTypes,
  924. seriesProto = Series.prototype,
  925. pointProto = H.Point.prototype;
  926. /**
  927. * The area range series is a carteseian series with higher and lower values
  928. * for each point along an X axis, where the area between the values is shaded.
  929. * Requires `highcharts-more.js`.
  930. *
  931. * @extends plotOptions.area
  932. * @product highcharts highstock
  933. * @sample {highcharts} highcharts/demo/arearange/
  934. * Area range chart
  935. * @sample {highstock} stock/demo/arearange/
  936. * Area range chart
  937. * @excluding stack,stacking
  938. * @optionparent plotOptions.arearange
  939. */
  940. seriesType('arearange', 'area', {
  941. /**
  942. * Whether to apply a drop shadow to the graph line. Since 2.3 the shadow
  943. * can be an object configuration containing `color`, `offsetX`, `offsetY`,
  944. * `opacity` and `width`.
  945. *
  946. * @type {Boolean|Object}
  947. * @product highcharts
  948. * @apioption plotOptions.arearange.shadow
  949. */
  950. /**
  951. * Pixel width of the arearange graph line.
  952. *
  953. * @since 2.3.0
  954. * @product highcharts highstock
  955. */
  956. lineWidth: 1,
  957. threshold: null,
  958. tooltip: {
  959. pointFormat: '<span style="color:{series.color}">\u25CF</span> {series.name}: <b>{point.low}</b> - <b>{point.high}</b><br/>' // eslint-disable-line no-dupe-keys
  960. },
  961. /**
  962. * Whether the whole area or just the line should respond to mouseover
  963. * tooltips and other mouse or touch events.
  964. *
  965. * @since 2.3.0
  966. * @product highcharts highstock
  967. */
  968. trackByArea: true,
  969. /**
  970. * Extended data labels for range series types. Range series data labels
  971. * have no `x` and `y` options. Instead, they have `xLow`, `xHigh`,
  972. * `yLow` and `yHigh` options to allow the higher and lower data label
  973. * sets individually.
  974. *
  975. * @type {Object}
  976. * @extends plotOptions.series.dataLabels
  977. * @excluding x,y
  978. * @since 2.3.0
  979. * @product highcharts highstock
  980. */
  981. dataLabels: {
  982. align: null,
  983. verticalAlign: null,
  984. /**
  985. * X offset of the lower data labels relative to the point value.
  986. *
  987. * @sample {highcharts} highcharts/plotoptions/arearange-datalabels/
  988. * Data labels on range series
  989. * @sample {highstock} highcharts/plotoptions/arearange-datalabels/
  990. * Data labels on range series
  991. * @since 2.3.0
  992. * @product highcharts highstock
  993. */
  994. xLow: 0,
  995. /**
  996. * X offset of the higher data labels relative to the point value.
  997. *
  998. * @sample {highcharts|highstock}
  999. * highcharts/plotoptions/arearange-datalabels/
  1000. * Data labels on range series
  1001. * @since 2.3.0
  1002. * @product highcharts highstock
  1003. */
  1004. xHigh: 0,
  1005. /**
  1006. * Y offset of the lower data labels relative to the point value.
  1007. *
  1008. * @sample {highcharts|highstock}
  1009. * highcharts/plotoptions/arearange-datalabels/
  1010. * Data labels on range series
  1011. * @default 16
  1012. * @since 2.3.0
  1013. * @product highcharts highstock
  1014. */
  1015. yLow: 0,
  1016. /**
  1017. * Y offset of the higher data labels relative to the point value.
  1018. *
  1019. * @sample {highcharts|highstock}
  1020. * highcharts/plotoptions/arearange-datalabels/
  1021. * Data labels on range series
  1022. * @default -6
  1023. * @since 2.3.0
  1024. * @product highcharts highstock
  1025. */
  1026. yHigh: 0
  1027. }
  1028. // Prototype members
  1029. }, {
  1030. pointArrayMap: ['low', 'high'],
  1031. dataLabelCollections: ['dataLabel', 'dataLabelUpper'],
  1032. toYData: function (point) {
  1033. return [point.low, point.high];
  1034. },
  1035. pointValKey: 'low',
  1036. deferTranslatePolar: true,
  1037. /**
  1038. * Translate a point's plotHigh from the internal angle and radius
  1039. * measures to true plotHigh coordinates. This is an addition of the
  1040. * toXY method found in Polar.js, because it runs too early for
  1041. * arearanges to be considered (#3419).
  1042. */
  1043. highToXY: function (point) {
  1044. // Find the polar plotX and plotY
  1045. var chart = this.chart,
  1046. xy = this.xAxis.postTranslate(
  1047. point.rectPlotX,
  1048. this.yAxis.len - point.plotHigh
  1049. );
  1050. point.plotHighX = xy.x - chart.plotLeft;
  1051. point.plotHigh = xy.y - chart.plotTop;
  1052. point.plotLowX = point.plotX;
  1053. },
  1054. /**
  1055. * Translate data points from raw values x and y to plotX and plotY
  1056. */
  1057. translate: function () {
  1058. var series = this,
  1059. yAxis = series.yAxis,
  1060. hasModifyValue = !!series.modifyValue;
  1061. seriesTypes.area.prototype.translate.apply(series);
  1062. // Set plotLow and plotHigh
  1063. each(series.points, function (point) {
  1064. var low = point.low,
  1065. high = point.high,
  1066. plotY = point.plotY;
  1067. if (high === null || low === null) {
  1068. point.isNull = true;
  1069. point.plotY = null;
  1070. } else {
  1071. point.plotLow = plotY;
  1072. point.plotHigh = yAxis.translate(
  1073. hasModifyValue ? series.modifyValue(high, point) : high,
  1074. 0,
  1075. 1,
  1076. 0,
  1077. 1
  1078. );
  1079. if (hasModifyValue) {
  1080. point.yBottom = point.plotHigh;
  1081. }
  1082. }
  1083. });
  1084. // Postprocess plotHigh
  1085. if (this.chart.polar) {
  1086. each(this.points, function (point) {
  1087. series.highToXY(point);
  1088. point.tooltipPos = [
  1089. (point.plotHighX + point.plotLowX) / 2,
  1090. (point.plotHigh + point.plotLow) / 2
  1091. ];
  1092. });
  1093. }
  1094. },
  1095. /**
  1096. * Extend the line series' getSegmentPath method by applying the segment
  1097. * path to both lower and higher values of the range
  1098. */
  1099. getGraphPath: function (points) {
  1100. var highPoints = [],
  1101. highAreaPoints = [],
  1102. i,
  1103. getGraphPath = seriesTypes.area.prototype.getGraphPath,
  1104. point,
  1105. pointShim,
  1106. linePath,
  1107. lowerPath,
  1108. options = this.options,
  1109. connectEnds = this.chart.polar && options.connectEnds !== false,
  1110. connectNulls = options.connectNulls,
  1111. step = options.step,
  1112. higherPath,
  1113. higherAreaPath;
  1114. points = points || this.points;
  1115. i = points.length;
  1116. /**
  1117. * Create the top line and the top part of the area fill. The area
  1118. * fill compensates for null points by drawing down to the lower graph,
  1119. * moving across the null gap and starting again at the lower graph.
  1120. */
  1121. i = points.length;
  1122. while (i--) {
  1123. point = points[i];
  1124. if (
  1125. !point.isNull &&
  1126. !connectEnds &&
  1127. !connectNulls &&
  1128. (!points[i + 1] || points[i + 1].isNull)
  1129. ) {
  1130. highAreaPoints.push({
  1131. plotX: point.plotX,
  1132. plotY: point.plotY,
  1133. doCurve: false // #5186, gaps in areasplinerange fill
  1134. });
  1135. }
  1136. pointShim = {
  1137. polarPlotY: point.polarPlotY,
  1138. rectPlotX: point.rectPlotX,
  1139. yBottom: point.yBottom,
  1140. // plotHighX is for polar charts
  1141. plotX: pick(point.plotHighX, point.plotX),
  1142. plotY: point.plotHigh,
  1143. isNull: point.isNull
  1144. };
  1145. highAreaPoints.push(pointShim);
  1146. highPoints.push(pointShim);
  1147. if (
  1148. !point.isNull &&
  1149. !connectEnds &&
  1150. !connectNulls &&
  1151. (!points[i - 1] || points[i - 1].isNull)
  1152. ) {
  1153. highAreaPoints.push({
  1154. plotX: point.plotX,
  1155. plotY: point.plotY,
  1156. doCurve: false // #5186, gaps in areasplinerange fill
  1157. });
  1158. }
  1159. }
  1160. // Get the paths
  1161. lowerPath = getGraphPath.call(this, points);
  1162. if (step) {
  1163. if (step === true) {
  1164. step = 'left';
  1165. }
  1166. options.step = {
  1167. left: 'right',
  1168. center: 'center',
  1169. right: 'left'
  1170. }[step]; // swap for reading in getGraphPath
  1171. }
  1172. higherPath = getGraphPath.call(this, highPoints);
  1173. higherAreaPath = getGraphPath.call(this, highAreaPoints);
  1174. options.step = step;
  1175. // Create a line on both top and bottom of the range
  1176. linePath = [].concat(lowerPath, higherPath);
  1177. // For the area path, we need to change the 'move' statement
  1178. // into 'lineTo' or 'curveTo'
  1179. if (!this.chart.polar && higherAreaPath[0] === 'M') {
  1180. higherAreaPath[0] = 'L'; // this probably doesn't work for spline
  1181. }
  1182. this.graphPath = linePath;
  1183. this.areaPath = lowerPath.concat(higherAreaPath);
  1184. // Prepare for sideways animation
  1185. linePath.isArea = true;
  1186. linePath.xMap = lowerPath.xMap;
  1187. this.areaPath.xMap = lowerPath.xMap;
  1188. return linePath;
  1189. },
  1190. /**
  1191. * Extend the basic drawDataLabels method by running it for both lower
  1192. * and higher values.
  1193. */
  1194. drawDataLabels: function () {
  1195. var data = this.data,
  1196. length = data.length,
  1197. i,
  1198. originalDataLabels = [],
  1199. dataLabelOptions = this.options.dataLabels,
  1200. align = dataLabelOptions.align,
  1201. verticalAlign = dataLabelOptions.verticalAlign,
  1202. inside = dataLabelOptions.inside,
  1203. point,
  1204. up,
  1205. inverted = this.chart.inverted;
  1206. if (dataLabelOptions.enabled || this._hasPointLabels) {
  1207. // Step 1: set preliminary values for plotY and dataLabel
  1208. // and draw the upper labels
  1209. i = length;
  1210. while (i--) {
  1211. point = data[i];
  1212. if (point) {
  1213. up = inside ?
  1214. point.plotHigh < point.plotLow :
  1215. point.plotHigh > point.plotLow;
  1216. // Set preliminary values
  1217. point.y = point.high;
  1218. point._plotY = point.plotY;
  1219. point.plotY = point.plotHigh;
  1220. // Store original data labels and set preliminary label
  1221. // objects to be picked up in the uber method
  1222. originalDataLabels[i] = point.dataLabel;
  1223. point.dataLabel = point.dataLabelUpper;
  1224. // Set the default offset
  1225. point.below = up;
  1226. if (inverted) {
  1227. if (!align) {
  1228. dataLabelOptions.align = up ? 'right' : 'left';
  1229. }
  1230. } else {
  1231. if (!verticalAlign) {
  1232. dataLabelOptions.verticalAlign = up ?
  1233. 'top' :
  1234. 'bottom';
  1235. }
  1236. }
  1237. dataLabelOptions.x = dataLabelOptions.xHigh;
  1238. dataLabelOptions.y = dataLabelOptions.yHigh;
  1239. }
  1240. }
  1241. if (seriesProto.drawDataLabels) {
  1242. seriesProto.drawDataLabels.apply(this, arguments); // #1209
  1243. }
  1244. // Step 2: reorganize and handle data labels for the lower values
  1245. i = length;
  1246. while (i--) {
  1247. point = data[i];
  1248. if (point) {
  1249. up = inside ?
  1250. point.plotHigh < point.plotLow :
  1251. point.plotHigh > point.plotLow;
  1252. // Move the generated labels from step 1, and reassign
  1253. // the original data labels
  1254. point.dataLabelUpper = point.dataLabel;
  1255. point.dataLabel = originalDataLabels[i];
  1256. // Reset values
  1257. point.y = point.low;
  1258. point.plotY = point._plotY;
  1259. // Set the default offset
  1260. point.below = !up;
  1261. if (inverted) {
  1262. if (!align) {
  1263. dataLabelOptions.align = up ? 'left' : 'right';
  1264. }
  1265. } else {
  1266. if (!verticalAlign) {
  1267. dataLabelOptions.verticalAlign = up ?
  1268. 'bottom' :
  1269. 'top';
  1270. }
  1271. }
  1272. dataLabelOptions.x = dataLabelOptions.xLow;
  1273. dataLabelOptions.y = dataLabelOptions.yLow;
  1274. }
  1275. }
  1276. if (seriesProto.drawDataLabels) {
  1277. seriesProto.drawDataLabels.apply(this, arguments);
  1278. }
  1279. }
  1280. dataLabelOptions.align = align;
  1281. dataLabelOptions.verticalAlign = verticalAlign;
  1282. },
  1283. alignDataLabel: function () {
  1284. seriesTypes.column.prototype.alignDataLabel.apply(this, arguments);
  1285. },
  1286. drawPoints: function () {
  1287. var series = this,
  1288. pointLength = series.points.length,
  1289. point,
  1290. i;
  1291. // Draw bottom points
  1292. seriesProto.drawPoints.apply(series, arguments);
  1293. // Prepare drawing top points
  1294. i = 0;
  1295. while (i < pointLength) {
  1296. point = series.points[i];
  1297. // Save original props to be overridden by temporary props for top
  1298. // points
  1299. point.origProps = {
  1300. plotY: point.plotY,
  1301. plotX: point.plotX,
  1302. isInside: point.isInside,
  1303. negative: point.negative,
  1304. zone: point.zone,
  1305. y: point.y
  1306. };
  1307. point.lowerGraphic = point.graphic;
  1308. point.graphic = point.upperGraphic;
  1309. point.plotY = point.plotHigh;
  1310. if (defined(point.plotHighX)) {
  1311. point.plotX = point.plotHighX;
  1312. }
  1313. point.y = point.high;
  1314. point.negative = point.high < (series.options.threshold || 0);
  1315. point.zone = series.zones.length && point.getZone();
  1316. if (!series.chart.polar) {
  1317. point.isInside = point.isTopInside = (
  1318. point.plotY !== undefined &&
  1319. point.plotY >= 0 &&
  1320. point.plotY <= series.yAxis.len && // #3519
  1321. point.plotX >= 0 &&
  1322. point.plotX <= series.xAxis.len
  1323. );
  1324. }
  1325. i++;
  1326. }
  1327. // Draw top points
  1328. seriesProto.drawPoints.apply(series, arguments);
  1329. // Reset top points preliminary modifications
  1330. i = 0;
  1331. while (i < pointLength) {
  1332. point = series.points[i];
  1333. point.upperGraphic = point.graphic;
  1334. point.graphic = point.lowerGraphic;
  1335. H.extend(point, point.origProps);
  1336. delete point.origProps;
  1337. i++;
  1338. }
  1339. },
  1340. setStackedPoints: noop
  1341. }, {
  1342. setState: function () {
  1343. var prevState = this.state,
  1344. series = this.series,
  1345. isPolar = series.chart.polar;
  1346. if (!defined(this.plotHigh)) {
  1347. // Boost doesn't calculate plotHigh
  1348. this.plotHigh = series.yAxis.toPixels(this.high, true);
  1349. }
  1350. if (!defined(this.plotLow)) {
  1351. // Boost doesn't calculate plotLow
  1352. this.plotLow = this.plotY = series.yAxis.toPixels(this.low, true);
  1353. }
  1354. if (series.stateMarkerGraphic) {
  1355. series.lowerStateMarkerGraphic = series.stateMarkerGraphic;
  1356. series.stateMarkerGraphic = series.upperStateMarkerGraphic;
  1357. }
  1358. // Change state also for the top marker
  1359. this.graphic = this.upperGraphic;
  1360. this.plotY = this.plotHigh;
  1361. if (isPolar) {
  1362. this.plotX = this.plotHighX;
  1363. }
  1364. // Top state:
  1365. pointProto.setState.apply(this, arguments);
  1366. this.state = prevState;
  1367. // Now restore defaults
  1368. this.plotY = this.plotLow;
  1369. this.graphic = this.lowerGraphic;
  1370. if (isPolar) {
  1371. this.plotX = this.plotLowX;
  1372. }
  1373. if (series.stateMarkerGraphic) {
  1374. series.upperStateMarkerGraphic = series.stateMarkerGraphic;
  1375. series.stateMarkerGraphic = series.lowerStateMarkerGraphic;
  1376. // Lower marker is stored at stateMarkerGraphic
  1377. // to avoid reference duplication (#7021)
  1378. series.lowerStateMarkerGraphic = undefined;
  1379. }
  1380. pointProto.setState.apply(this, arguments);
  1381. },
  1382. haloPath: function () {
  1383. var isPolar = this.series.chart.polar,
  1384. path = [];
  1385. // Bottom halo
  1386. this.plotY = this.plotLow;
  1387. if (isPolar) {
  1388. this.plotX = this.plotLowX;
  1389. }
  1390. if (this.isInside) {
  1391. path = pointProto.haloPath.apply(this, arguments);
  1392. }
  1393. // Top halo
  1394. this.plotY = this.plotHigh;
  1395. if (isPolar) {
  1396. this.plotX = this.plotHighX;
  1397. }
  1398. if (this.isTopInside) {
  1399. path = path.concat(
  1400. pointProto.haloPath.apply(this, arguments)
  1401. );
  1402. }
  1403. return path;
  1404. },
  1405. destroyElements: function () {
  1406. var graphics = ['lowerGraphic', 'upperGraphic'];
  1407. each(graphics, function (graphicName) {
  1408. if (this[graphicName]) {
  1409. this[graphicName] = this[graphicName].destroy();
  1410. }
  1411. }, this);
  1412. // Clear graphic for states, removed in the above each:
  1413. this.graphic = null;
  1414. return pointProto.destroyElements.apply(this, arguments);
  1415. }
  1416. });
  1417. /**
  1418. * A `arearange` series. If the [type](#series.arearange.type) option
  1419. * is not specified, it is inherited from [chart.type](#chart.type).
  1420. *
  1421. *
  1422. * @type {Object}
  1423. * @extends series,plotOptions.arearange
  1424. * @excluding dataParser,dataURL,stack,stacking
  1425. * @product highcharts highstock
  1426. * @apioption series.arearange
  1427. */
  1428. /**
  1429. * An array of data points for the series. For the `arearange` series
  1430. * type, points can be given in the following ways:
  1431. *
  1432. * 1. An array of arrays with 3 or 2 values. In this case, the values
  1433. * correspond to `x,low,high`. If the first value is a string, it is
  1434. * applied as the name of the point, and the `x` value is inferred.
  1435. * The `x` value can also be omitted, in which case the inner arrays
  1436. * should be of length 2\. Then the `x` value is automatically calculated,
  1437. * either starting at 0 and incremented by 1, or from `pointStart`
  1438. * and `pointInterval` given in the series options.
  1439. *
  1440. * ```js
  1441. * data: [
  1442. * [0, 8, 3],
  1443. * [1, 1, 1],
  1444. * [2, 6, 8]
  1445. * ]
  1446. * ```
  1447. *
  1448. * 2. An array of objects with named values. The objects are point
  1449. * configuration objects as seen below. If the total number of data
  1450. * points exceeds the series'
  1451. * [turboThreshold](#series.arearange.turboThreshold),
  1452. * this option is not available.
  1453. *
  1454. * ```js
  1455. * data: [{
  1456. * x: 1,
  1457. * low: 9,
  1458. * high: 0,
  1459. * name: "Point2",
  1460. * color: "#00FF00"
  1461. * }, {
  1462. * x: 1,
  1463. * low: 3,
  1464. * high: 4,
  1465. * name: "Point1",
  1466. * color: "#FF00FF"
  1467. * }]
  1468. * ```
  1469. *
  1470. * @type {Array<Object|Array>}
  1471. * @extends series.line.data
  1472. * @excluding marker,y
  1473. * @sample {highcharts} highcharts/chart/reflow-true/
  1474. * Numerical values
  1475. * @sample {highcharts} highcharts/series/data-array-of-arrays/
  1476. * Arrays of numeric x and y
  1477. * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
  1478. * Arrays of datetime x and y
  1479. * @sample {highcharts} highcharts/series/data-array-of-name-value/
  1480. * Arrays of point.name and y
  1481. * @sample {highcharts} highcharts/series/data-array-of-objects/
  1482. * Config objects
  1483. * @product highcharts highstock
  1484. * @apioption series.arearange.data
  1485. */
  1486. /**
  1487. * The high or maximum value for each data point.
  1488. *
  1489. * @type {Number}
  1490. * @product highcharts highstock
  1491. * @apioption series.arearange.data.high
  1492. */
  1493. /**
  1494. * The low or minimum value for each data point.
  1495. *
  1496. * @type {Number}
  1497. * @product highcharts highstock
  1498. * @apioption series.arearange.data.low
  1499. */
  1500. /**
  1501. * @excluding x,y
  1502. * @product highcharts highstock
  1503. * @apioption series.arearange.dataLabels
  1504. */
  1505. }(Highcharts));
  1506. (function (H) {
  1507. /**
  1508. * (c) 2010-2017 Torstein Honsi
  1509. *
  1510. * License: www.highcharts.com/license
  1511. */
  1512. var seriesType = H.seriesType,
  1513. seriesTypes = H.seriesTypes;
  1514. /**
  1515. * The area spline range is a cartesian series type with higher and
  1516. * lower Y values along an X axis. The area inside the range is colored, and
  1517. * the graph outlining the area is a smoothed spline. Requires
  1518. * `highcharts-more.js`.
  1519. *
  1520. * @extends plotOptions.arearange
  1521. * @excluding step
  1522. * @since 2.3.0
  1523. * @sample {highstock|highstock} stock/demo/areasplinerange/
  1524. * Area spline range
  1525. * @product highcharts highstock
  1526. * @apioption plotOptions.areasplinerange
  1527. */
  1528. seriesType('areasplinerange', 'arearange', null, {
  1529. getPointSpline: seriesTypes.spline.prototype.getPointSpline
  1530. });
  1531. /**
  1532. * A `areasplinerange` series. If the [type](#series.areasplinerange.type)
  1533. * option is not specified, it is inherited from [chart.type](#chart.type).
  1534. *
  1535. * @type {Object}
  1536. * @extends series,plotOptions.areasplinerange
  1537. * @excluding dataParser,dataURL,stack
  1538. * @product highcharts highstock
  1539. * @apioption series.areasplinerange
  1540. */
  1541. /**
  1542. * An array of data points for the series. For the `areasplinerange`
  1543. * series type, points can be given in the following ways:
  1544. *
  1545. * 1. An array of arrays with 3 or 2 values. In this case, the values
  1546. * correspond to `x,low,high`. If the first value is a string, it is
  1547. * applied as the name of the point, and the `x` value is inferred.
  1548. * The `x` value can also be omitted, in which case the inner arrays
  1549. * should be of length 2\. Then the `x` value is automatically calculated,
  1550. * either starting at 0 and incremented by 1, or from `pointStart`
  1551. * and `pointInterval` given in the series options.
  1552. *
  1553. * ```js
  1554. * data: [
  1555. * [0, 0, 5],
  1556. * [1, 9, 1],
  1557. * [2, 5, 2]
  1558. * ]
  1559. * ```
  1560. *
  1561. * 2. An array of objects with named values. The objects are point
  1562. * configuration objects as seen below. If the total number of data
  1563. * points exceeds the series' [turboThreshold](
  1564. * #series.areasplinerange.turboThreshold), this option is not available.
  1565. *
  1566. * ```js
  1567. * data: [{
  1568. * x: 1,
  1569. * low: 5,
  1570. * high: 0,
  1571. * name: "Point2",
  1572. * color: "#00FF00"
  1573. * }, {
  1574. * x: 1,
  1575. * low: 4,
  1576. * high: 1,
  1577. * name: "Point1",
  1578. * color: "#FF00FF"
  1579. * }]
  1580. * ```
  1581. *
  1582. * @type {Array<Object|Array>}
  1583. * @extends series.arearange.data
  1584. * @sample {highcharts} highcharts/chart/reflow-true/
  1585. * Numerical values
  1586. * @sample {highcharts} highcharts/series/data-array-of-arrays/
  1587. * Arrays of numeric x and y
  1588. * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
  1589. * Arrays of datetime x and y
  1590. * @sample {highcharts} highcharts/series/data-array-of-name-value/
  1591. * Arrays of point.name and y
  1592. * @sample {highcharts} highcharts/series/data-array-of-objects/
  1593. * Config objects
  1594. * @product highcharts highstock
  1595. * @apioption series.areasplinerange.data
  1596. */
  1597. }(Highcharts));
  1598. (function (H) {
  1599. /**
  1600. * (c) 2010-2017 Torstein Honsi
  1601. *
  1602. * License: www.highcharts.com/license
  1603. */
  1604. var defaultPlotOptions = H.defaultPlotOptions,
  1605. each = H.each,
  1606. merge = H.merge,
  1607. noop = H.noop,
  1608. pick = H.pick,
  1609. seriesType = H.seriesType,
  1610. seriesTypes = H.seriesTypes;
  1611. var colProto = seriesTypes.column.prototype;
  1612. /**
  1613. * The column range is a cartesian series type with higher and lower
  1614. * Y values along an X axis. Requires `highcharts-more.js`. To display
  1615. * horizontal bars, set [chart.inverted](#chart.inverted) to `true`.
  1616. *
  1617. * @type {Object}
  1618. * @extends plotOptions.column
  1619. * @excluding negativeColor,stacking,softThreshold,threshold
  1620. * @sample {highcharts|highstock} highcharts/demo/columnrange/
  1621. * Inverted column range
  1622. * @since 2.3.0
  1623. * @product highcharts highstock
  1624. * @optionparent plotOptions.columnrange
  1625. */
  1626. var columnRangeOptions = {
  1627. /**
  1628. * Extended data labels for range series types. Range series data labels
  1629. * have no `x` and `y` options. Instead, they have `xLow`, `xHigh`,
  1630. * `yLow` and `yHigh` options to allow the higher and lower data label
  1631. * sets individually.
  1632. *
  1633. * @type {Object}
  1634. * @extends plotOptions.arearange.dataLabels
  1635. * @excluding x,y
  1636. * @since 2.3.0
  1637. * @product highcharts highstock
  1638. * @apioption plotOptions.columnrange.dataLabels
  1639. */
  1640. pointRange: null,
  1641. /** @ignore-option */
  1642. marker: null,
  1643. states: {
  1644. hover: {
  1645. /** @ignore-option */
  1646. halo: false
  1647. }
  1648. }
  1649. };
  1650. /**
  1651. * The ColumnRangeSeries class
  1652. */
  1653. seriesType('columnrange', 'arearange', merge(
  1654. defaultPlotOptions.column,
  1655. defaultPlotOptions.arearange,
  1656. columnRangeOptions
  1657. ), {
  1658. /**
  1659. * Translate data points from raw values x and y to plotX and plotY
  1660. */
  1661. translate: function () {
  1662. var series = this,
  1663. yAxis = series.yAxis,
  1664. xAxis = series.xAxis,
  1665. startAngleRad = xAxis.startAngleRad,
  1666. start,
  1667. chart = series.chart,
  1668. isRadial = series.xAxis.isRadial,
  1669. safeDistance = Math.max(chart.chartWidth, chart.chartHeight) + 999,
  1670. plotHigh;
  1671. // Don't draw too far outside plot area (#6835)
  1672. function safeBounds(pixelPos) {
  1673. return Math.min(Math.max(
  1674. -safeDistance,
  1675. pixelPos
  1676. ), safeDistance);
  1677. }
  1678. colProto.translate.apply(series);
  1679. // Set plotLow and plotHigh
  1680. each(series.points, function (point) {
  1681. var shapeArgs = point.shapeArgs,
  1682. minPointLength = series.options.minPointLength,
  1683. heightDifference,
  1684. height,
  1685. y;
  1686. point.plotHigh = plotHigh = safeBounds(
  1687. yAxis.translate(point.high, 0, 1, 0, 1)
  1688. );
  1689. point.plotLow = safeBounds(point.plotY);
  1690. // adjust shape
  1691. y = plotHigh;
  1692. height = pick(point.rectPlotY, point.plotY) - plotHigh;
  1693. // Adjust for minPointLength
  1694. if (Math.abs(height) < minPointLength) {
  1695. heightDifference = (minPointLength - height);
  1696. height += heightDifference;
  1697. y -= heightDifference / 2;
  1698. // Adjust for negative ranges or reversed Y axis (#1457)
  1699. } else if (height < 0) {
  1700. height *= -1;
  1701. y -= height;
  1702. }
  1703. if (isRadial) {
  1704. start = point.barX + startAngleRad;
  1705. point.shapeType = 'path';
  1706. point.shapeArgs = {
  1707. d: series.polarArc(
  1708. y + height,
  1709. y,
  1710. start,
  1711. start + point.pointWidth
  1712. )
  1713. };
  1714. } else {
  1715. shapeArgs.height = height;
  1716. shapeArgs.y = y;
  1717. point.tooltipPos = chart.inverted ?
  1718. [
  1719. yAxis.len + yAxis.pos - chart.plotLeft - y - height / 2,
  1720. xAxis.len + xAxis.pos - chart.plotTop - shapeArgs.x -
  1721. shapeArgs.width / 2,
  1722. height
  1723. ] : [
  1724. xAxis.left - chart.plotLeft + shapeArgs.x +
  1725. shapeArgs.width / 2,
  1726. yAxis.pos - chart.plotTop + y + height / 2,
  1727. height
  1728. ]; // don't inherit from column tooltip position - #3372
  1729. }
  1730. });
  1731. },
  1732. directTouch: true,
  1733. trackerGroups: ['group', 'dataLabelsGroup'],
  1734. drawGraph: noop,
  1735. getSymbol: noop,
  1736. crispCol: colProto.crispCol,
  1737. drawPoints: colProto.drawPoints,
  1738. drawTracker: colProto.drawTracker,
  1739. getColumnMetrics: colProto.getColumnMetrics,
  1740. pointAttribs: colProto.pointAttribs,
  1741. // Overrides from modules that may be loaded after this module
  1742. animate: function () {
  1743. return colProto.animate.apply(this, arguments);
  1744. },
  1745. polarArc: function () {
  1746. return colProto.polarArc.apply(this, arguments);
  1747. },
  1748. translate3dPoints: function () {
  1749. return colProto.translate3dPoints.apply(this, arguments);
  1750. },
  1751. translate3dShapes: function () {
  1752. return colProto.translate3dShapes.apply(this, arguments);
  1753. }
  1754. }, {
  1755. setState: colProto.pointClass.prototype.setState
  1756. });
  1757. /**
  1758. * A `columnrange` series. If the [type](#series.columnrange.type)
  1759. * option is not specified, it is inherited from
  1760. * [chart.type](#chart.type).
  1761. *
  1762. * @type {Object}
  1763. * @extends series,plotOptions.columnrange
  1764. * @excluding dataParser,dataURL,stack,stacking
  1765. * @product highcharts highstock
  1766. * @apioption series.columnrange
  1767. */
  1768. /**
  1769. * An array of data points for the series. For the `columnrange` series
  1770. * type, points can be given in the following ways:
  1771. *
  1772. * 1. An array of arrays with 3 or 2 values. In this case, the values
  1773. * correspond to `x,low,high`. If the first value is a string, it is
  1774. * applied as the name of the point, and the `x` value is inferred.
  1775. * The `x` value can also be omitted, in which case the inner arrays
  1776. * should be of length 2\. Then the `x` value is automatically calculated,
  1777. * either starting at 0 and incremented by 1, or from `pointStart`
  1778. * and `pointInterval` given in the series options.
  1779. *
  1780. * ```js
  1781. * data: [
  1782. * [0, 4, 2],
  1783. * [1, 2, 1],
  1784. * [2, 9, 10]
  1785. * ]
  1786. * ```
  1787. *
  1788. * 2. An array of objects with named values. The objects are point
  1789. * configuration objects as seen below. If the total number of data
  1790. * points exceeds the series' [turboThreshold](
  1791. * #series.columnrange.turboThreshold), this option is not available.
  1792. *
  1793. * ```js
  1794. * data: [{
  1795. * x: 1,
  1796. * low: 0,
  1797. * high: 4,
  1798. * name: "Point2",
  1799. * color: "#00FF00"
  1800. * }, {
  1801. * x: 1,
  1802. * low: 5,
  1803. * high: 3,
  1804. * name: "Point1",
  1805. * color: "#FF00FF"
  1806. * }]
  1807. * ```
  1808. *
  1809. * @type {Array<Object|Array>}
  1810. * @extends series.arearange.data
  1811. * @excluding marker
  1812. * @sample {highcharts} highcharts/chart/reflow-true/
  1813. * Numerical values
  1814. * @sample {highcharts} highcharts/series/data-array-of-arrays/
  1815. * Arrays of numeric x and y
  1816. * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
  1817. * Arrays of datetime x and y
  1818. * @sample {highcharts} highcharts/series/data-array-of-name-value/
  1819. * Arrays of point.name and y
  1820. * @sample {highcharts} highcharts/series/data-array-of-objects/
  1821. * Config objects
  1822. * @product highcharts highstock
  1823. * @apioption series.columnrange.data
  1824. */
  1825. /**
  1826. * @excluding halo,lineWidth,lineWidthPlus,marker
  1827. * @product highcharts highstock
  1828. * @apioption series.columnrange.states.hover
  1829. */
  1830. /**
  1831. * @excluding halo,lineWidth,lineWidthPlus,marker
  1832. * @product highcharts highstock
  1833. * @apioption series.columnrange.states.select
  1834. */
  1835. }(Highcharts));
  1836. (function (H) {
  1837. /**
  1838. * (c) 2010-2017 Torstein Honsi
  1839. *
  1840. * License: www.highcharts.com/license
  1841. */
  1842. var each = H.each,
  1843. isNumber = H.isNumber,
  1844. merge = H.merge,
  1845. noop = H.noop,
  1846. pick = H.pick,
  1847. pInt = H.pInt,
  1848. Series = H.Series,
  1849. seriesType = H.seriesType,
  1850. TrackerMixin = H.TrackerMixin;
  1851. /**
  1852. * Gauges are circular plots displaying one or more values with a dial pointing
  1853. * to values along the perimeter.
  1854. *
  1855. * @sample highcharts/demo/gauge-speedometer/ Gauge chart
  1856. * @extends {plotOptions.line}
  1857. * @excluding animationLimit,boostThreshold,connectEnds,connectNulls,
  1858. * cropThreshold,dashStyle,findNearestPointBy,getExtremesFromAll,
  1859. * marker,negativeColor,pointPlacement,shadow,softThreshold,
  1860. * stacking,states,step,threshold,turboThreshold,xAxis,zoneAxis,
  1861. * zones
  1862. * @product highcharts
  1863. * @optionparent plotOptions.gauge
  1864. */
  1865. seriesType('gauge', 'line', {
  1866. /**
  1867. * When this option is `true`, the dial will wrap around the axes. For
  1868. * instance, in a full-range gauge going from 0 to 360, a value of 400
  1869. * will point to 40\. When `wrap` is `false`, the dial stops at 360.
  1870. *
  1871. * @type {Boolean}
  1872. * @see [overshoot](#plotOptions.gauge.overshoot)
  1873. * @default true
  1874. * @since 3.0
  1875. * @product highcharts
  1876. * @apioption plotOptions.gauge.wrap
  1877. */
  1878. /**
  1879. * Data labels for the gauge. For gauges, the data labels are enabled
  1880. * by default and shown in a bordered box below the point.
  1881. *
  1882. * @type {Object}
  1883. * @extends plotOptions.series.dataLabels
  1884. * @since 2.3.0
  1885. * @product highcharts
  1886. */
  1887. dataLabels: {
  1888. /**
  1889. * Enable or disable the data labels.
  1890. *
  1891. * @since 2.3.0
  1892. * @product highcharts highmaps
  1893. */
  1894. enabled: true,
  1895. defer: false,
  1896. /**
  1897. * The y position offset of the label relative to the center of the
  1898. * gauge.
  1899. *
  1900. * @since 2.3.0
  1901. * @product highcharts highmaps
  1902. */
  1903. y: 15,
  1904. /**
  1905. * The border radius in pixels for the gauge's data label.
  1906. *
  1907. * @since 2.3.0
  1908. * @product highcharts highmaps
  1909. */
  1910. borderRadius: 3,
  1911. crop: false,
  1912. /**
  1913. * The vertical alignment of the data label.
  1914. *
  1915. * @product highcharts highmaps
  1916. */
  1917. verticalAlign: 'top',
  1918. /**
  1919. * The Z index of the data labels. A value of 2 display them behind
  1920. * the dial.
  1921. *
  1922. * @since 2.1.5
  1923. * @product highcharts highmaps
  1924. */
  1925. zIndex: 2,
  1926. // Presentational
  1927. /**
  1928. * The border width in pixels for the gauge data label.
  1929. *
  1930. * @since 2.3.0
  1931. * @product highcharts highmaps
  1932. */
  1933. borderWidth: 1,
  1934. /**
  1935. * The border color for the data label.
  1936. *
  1937. * @type {Color}
  1938. * @default #cccccc
  1939. * @since 2.3.0
  1940. * @product highcharts highmaps
  1941. */
  1942. borderColor: '#cccccc'
  1943. },
  1944. /**
  1945. * Options for the dial or arrow pointer of the gauge.
  1946. *
  1947. * In styled mode, the dial is styled with the
  1948. * `.highcharts-gauge-series .highcharts-dial` rule.
  1949. *
  1950. * @type {Object}
  1951. * @sample {highcharts} highcharts/css/gauge/ Styled mode
  1952. * @since 2.3.0
  1953. * @product highcharts
  1954. */
  1955. dial: {},
  1956. /**
  1957. * The length of the dial's base part, relative to the total radius
  1958. * or length of the dial.
  1959. *
  1960. * @type {String}
  1961. * @sample {highcharts} highcharts/plotoptions/gauge-dial/
  1962. * Dial options demonstrated
  1963. * @default 70%
  1964. * @since 2.3.0
  1965. * @product highcharts
  1966. * @apioption plotOptions.gauge.dial.baseLength
  1967. */
  1968. /**
  1969. * The pixel width of the base of the gauge dial. The base is the part
  1970. * closest to the pivot, defined by baseLength.
  1971. *
  1972. * @type {Number}
  1973. * @sample {highcharts} highcharts/plotoptions/gauge-dial/
  1974. * Dial options demonstrated
  1975. * @default 3
  1976. * @since 2.3.0
  1977. * @product highcharts
  1978. * @apioption plotOptions.gauge.dial.baseWidth
  1979. */
  1980. /**
  1981. * The radius or length of the dial, in percentages relative to the
  1982. * radius of the gauge itself.
  1983. *
  1984. * @type {String}
  1985. * @sample {highcharts} highcharts/plotoptions/gauge-dial/
  1986. * Dial options demonstrated
  1987. * @default 80%
  1988. * @since 2.3.0
  1989. * @product highcharts
  1990. * @apioption plotOptions.gauge.dial.radius
  1991. */
  1992. /**
  1993. * The length of the dial's rear end, the part that extends out on the
  1994. * other side of the pivot. Relative to the dial's length.
  1995. *
  1996. * @type {String}
  1997. * @sample {highcharts} highcharts/plotoptions/gauge-dial/
  1998. * Dial options demonstrated
  1999. * @default 10%
  2000. * @since 2.3.0
  2001. * @product highcharts
  2002. * @apioption plotOptions.gauge.dial.rearLength
  2003. */
  2004. /**
  2005. * The width of the top of the dial, closest to the perimeter. The pivot
  2006. * narrows in from the base to the top.
  2007. *
  2008. * @type {Number}
  2009. * @sample {highcharts} highcharts/plotoptions/gauge-dial/
  2010. * Dial options demonstrated
  2011. * @default 1
  2012. * @since 2.3.0
  2013. * @product highcharts
  2014. * @apioption plotOptions.gauge.dial.topWidth
  2015. */
  2016. /**
  2017. * The background or fill color of the gauge's dial.
  2018. *
  2019. * @type {Color}
  2020. * @sample {highcharts} highcharts/plotoptions/gauge-dial/
  2021. * Dial options demonstrated
  2022. * @default #000000
  2023. * @since 2.3.0
  2024. * @product highcharts
  2025. * @apioption plotOptions.gauge.dial.backgroundColor
  2026. */
  2027. /**
  2028. * The border color or stroke of the gauge's dial. By default, the
  2029. * borderWidth is 0, so this must be set in addition to a custom border
  2030. * color.
  2031. *
  2032. * @type {Color}
  2033. * @sample {highcharts} highcharts/plotoptions/gauge-dial/
  2034. * Dial options demonstrated
  2035. * @default #cccccc
  2036. * @since 2.3.0
  2037. * @product highcharts
  2038. * @apioption plotOptions.gauge.dial.borderColor
  2039. */
  2040. /**
  2041. * The width of the gauge dial border in pixels.
  2042. *
  2043. * @type {Number}
  2044. * @sample {highcharts} highcharts/plotoptions/gauge-dial/
  2045. * Dial options demonstrated
  2046. * @default 0
  2047. * @since 2.3.0
  2048. * @product highcharts
  2049. * @apioption plotOptions.gauge.dial.borderWidth
  2050. */
  2051. /**
  2052. * Allow the dial to overshoot the end of the perimeter axis by this
  2053. * many degrees. Say if the gauge axis goes from 0 to 60, a value of
  2054. * 100, or 1000, will show 5 degrees beyond the end of the axis when this
  2055. * option is set to 5.
  2056. *
  2057. * @type {Number}
  2058. * @see [wrap](#plotOptions.gauge.wrap)
  2059. * @sample {highcharts} highcharts/plotoptions/gauge-overshoot/
  2060. * Allow 5 degrees overshoot
  2061. * @default 0
  2062. * @since 3.0.10
  2063. * @product highcharts
  2064. * @apioption plotOptions.gauge.overshoot
  2065. */
  2066. /**
  2067. * Options for the pivot or the center point of the gauge.
  2068. *
  2069. * In styled mode, the pivot is styled with the
  2070. * `.highcharts-gauge-series .highcharts-pivot` rule.
  2071. *
  2072. * @type {Object}
  2073. * @sample {highcharts} highcharts/css/gauge/ Styled mode
  2074. * @since 2.3.0
  2075. * @product highcharts
  2076. */
  2077. pivot: {},
  2078. /**
  2079. * The pixel radius of the pivot.
  2080. *
  2081. * @type {Number}
  2082. * @sample {highcharts} highcharts/plotoptions/gauge-pivot/
  2083. * Pivot options demonstrated
  2084. * @default 5
  2085. * @since 2.3.0
  2086. * @product highcharts
  2087. * @apioption plotOptions.gauge.pivot.radius
  2088. */
  2089. /**
  2090. * The border or stroke width of the pivot.
  2091. *
  2092. * @type {Number}
  2093. * @sample {highcharts} highcharts/plotoptions/gauge-pivot/
  2094. * Pivot options demonstrated
  2095. * @default 0
  2096. * @since 2.3.0
  2097. * @product highcharts
  2098. * @apioption plotOptions.gauge.pivot.borderWidth
  2099. */
  2100. /**
  2101. * The border or stroke color of the pivot. In able to change this,
  2102. * the borderWidth must also be set to something other than the default
  2103. * 0.
  2104. *
  2105. * @type {Color}
  2106. * @sample {highcharts} highcharts/plotoptions/gauge-pivot/
  2107. * Pivot options demonstrated
  2108. * @default #cccccc
  2109. * @since 2.3.0
  2110. * @product highcharts
  2111. * @apioption plotOptions.gauge.pivot.borderColor
  2112. */
  2113. /**
  2114. * The background color or fill of the pivot.
  2115. *
  2116. * @type {Color}
  2117. * @sample {highcharts} highcharts/plotoptions/gauge-pivot/
  2118. * Pivot options demonstrated
  2119. * @default #000000
  2120. * @since 2.3.0
  2121. * @product highcharts
  2122. * @apioption plotOptions.gauge.pivot.backgroundColor
  2123. */
  2124. tooltip: {
  2125. headerFormat: ''
  2126. },
  2127. /**
  2128. * Whether to display this particular series or series type in the
  2129. * legend. Defaults to false for gauge series.
  2130. *
  2131. * @since 2.3.0
  2132. * @product highcharts
  2133. */
  2134. showInLegend: false
  2135. // Prototype members
  2136. }, {
  2137. // chart.angular will be set to true when a gauge series is present,
  2138. // and this will be used on the axes
  2139. angular: true,
  2140. directTouch: true, // #5063
  2141. drawGraph: noop,
  2142. fixedBox: true,
  2143. forceDL: true,
  2144. noSharedTooltip: true,
  2145. trackerGroups: ['group', 'dataLabelsGroup'],
  2146. /**
  2147. * Calculate paths etc
  2148. */
  2149. translate: function () {
  2150. var series = this,
  2151. yAxis = series.yAxis,
  2152. options = series.options,
  2153. center = yAxis.center;
  2154. series.generatePoints();
  2155. each(series.points, function (point) {
  2156. var dialOptions = merge(options.dial, point.dial),
  2157. radius = (pInt(pick(dialOptions.radius, 80)) * center[2]) /
  2158. 200,
  2159. baseLength = (pInt(pick(dialOptions.baseLength, 70)) * radius) /
  2160. 100,
  2161. rearLength = (pInt(pick(dialOptions.rearLength, 10)) * radius) /
  2162. 100,
  2163. baseWidth = dialOptions.baseWidth || 3,
  2164. topWidth = dialOptions.topWidth || 1,
  2165. overshoot = options.overshoot,
  2166. rotation = yAxis.startAngleRad +
  2167. yAxis.translate(point.y, null, null, null, true);
  2168. // Handle the wrap and overshoot options
  2169. if (isNumber(overshoot)) {
  2170. overshoot = overshoot / 180 * Math.PI;
  2171. rotation = Math.max(
  2172. yAxis.startAngleRad - overshoot,
  2173. Math.min(yAxis.endAngleRad + overshoot, rotation)
  2174. );
  2175. } else if (options.wrap === false) {
  2176. rotation = Math.max(
  2177. yAxis.startAngleRad,
  2178. Math.min(yAxis.endAngleRad, rotation)
  2179. );
  2180. }
  2181. rotation = rotation * 180 / Math.PI;
  2182. point.shapeType = 'path';
  2183. point.shapeArgs = {
  2184. d: dialOptions.path || [
  2185. 'M',
  2186. -rearLength, -baseWidth / 2,
  2187. 'L',
  2188. baseLength, -baseWidth / 2,
  2189. radius, -topWidth / 2,
  2190. radius, topWidth / 2,
  2191. baseLength, baseWidth / 2,
  2192. -rearLength, baseWidth / 2,
  2193. 'z'
  2194. ],
  2195. translateX: center[0],
  2196. translateY: center[1],
  2197. rotation: rotation
  2198. };
  2199. // Positions for data label
  2200. point.plotX = center[0];
  2201. point.plotY = center[1];
  2202. });
  2203. },
  2204. /**
  2205. * Draw the points where each point is one needle
  2206. */
  2207. drawPoints: function () {
  2208. var series = this,
  2209. center = series.yAxis.center,
  2210. pivot = series.pivot,
  2211. options = series.options,
  2212. pivotOptions = options.pivot,
  2213. renderer = series.chart.renderer;
  2214. each(series.points, function (point) {
  2215. var graphic = point.graphic,
  2216. shapeArgs = point.shapeArgs,
  2217. d = shapeArgs.d,
  2218. dialOptions = merge(options.dial, point.dial); // #1233
  2219. if (graphic) {
  2220. graphic.animate(shapeArgs);
  2221. shapeArgs.d = d; // animate alters it
  2222. } else {
  2223. point.graphic = renderer[point.shapeType](shapeArgs)
  2224. .attr({
  2225. // required by VML when animation is false
  2226. rotation: shapeArgs.rotation,
  2227. zIndex: 1
  2228. })
  2229. .addClass('highcharts-dial')
  2230. .add(series.group);
  2231. // Presentational attributes
  2232. point.graphic.attr({
  2233. stroke: dialOptions.borderColor || 'none',
  2234. 'stroke-width': dialOptions.borderWidth || 0,
  2235. fill: dialOptions.backgroundColor ||
  2236. '#000000'
  2237. });
  2238. }
  2239. });
  2240. // Add or move the pivot
  2241. if (pivot) {
  2242. pivot.animate({ // #1235
  2243. translateX: center[0],
  2244. translateY: center[1]
  2245. });
  2246. } else {
  2247. series.pivot = renderer.circle(0, 0, pick(pivotOptions.radius, 5))
  2248. .attr({
  2249. zIndex: 2
  2250. })
  2251. .addClass('highcharts-pivot')
  2252. .translate(center[0], center[1])
  2253. .add(series.group);
  2254. // Presentational attributes
  2255. series.pivot.attr({
  2256. 'stroke-width': pivotOptions.borderWidth || 0,
  2257. stroke: pivotOptions.borderColor ||
  2258. '#cccccc',
  2259. fill: pivotOptions.backgroundColor ||
  2260. '#000000'
  2261. });
  2262. }
  2263. },
  2264. /**
  2265. * Animate the arrow up from startAngle
  2266. */
  2267. animate: function (init) {
  2268. var series = this;
  2269. if (!init) {
  2270. each(series.points, function (point) {
  2271. var graphic = point.graphic;
  2272. if (graphic) {
  2273. // start value
  2274. graphic.attr({
  2275. rotation: series.yAxis.startAngleRad * 180 / Math.PI
  2276. });
  2277. // animate
  2278. graphic.animate({
  2279. rotation: point.shapeArgs.rotation
  2280. }, series.options.animation);
  2281. }
  2282. });
  2283. // delete this function to allow it only once
  2284. series.animate = null;
  2285. }
  2286. },
  2287. render: function () {
  2288. this.group = this.plotGroup(
  2289. 'group',
  2290. 'series',
  2291. this.visible ? 'visible' : 'hidden',
  2292. this.options.zIndex,
  2293. this.chart.seriesGroup
  2294. );
  2295. Series.prototype.render.call(this);
  2296. this.group.clip(this.chart.clipRect);
  2297. },
  2298. /**
  2299. * Extend the basic setData method by running processData and generatePoints
  2300. * immediately, in order to access the points from the legend.
  2301. */
  2302. setData: function (data, redraw) {
  2303. Series.prototype.setData.call(this, data, false);
  2304. this.processData();
  2305. this.generatePoints();
  2306. if (pick(redraw, true)) {
  2307. this.chart.redraw();
  2308. }
  2309. },
  2310. /**
  2311. * If the tracking module is loaded, add the point tracker
  2312. */
  2313. drawTracker: TrackerMixin && TrackerMixin.drawTrackerPoint
  2314. // Point members
  2315. }, {
  2316. /**
  2317. * Don't do any hover colors or anything
  2318. */
  2319. setState: function (state) {
  2320. this.state = state;
  2321. }
  2322. });
  2323. /**
  2324. * A `gauge` series. If the [type](#series.gauge.type) option is not
  2325. * specified, it is inherited from [chart.type](#chart.type).
  2326. *
  2327. * @type {Object}
  2328. * @extends series,plotOptions.gauge
  2329. * @excluding animationLimit,boostThreshold,connectEnds,connectNulls,
  2330. * cropThreshold,dashStyle,dataParser,dataURL,findNearestPointBy,
  2331. * getExtremesFromAll,marker,negativeColor,pointPlacement,shadow,
  2332. * softThreshold,stack,stacking,states,step,threshold,
  2333. * turboThreshold,zoneAxis,zones
  2334. * @product highcharts
  2335. * @apioption series.gauge
  2336. */
  2337. /**
  2338. * An array of data points for the series. For the `gauge` series type,
  2339. * points can be given in the following ways:
  2340. *
  2341. * 1. An array of numerical values. In this case, the numerical values
  2342. * will be interpreted as `y` options. Example:
  2343. *
  2344. * ```js
  2345. * data: [0, 5, 3, 5]
  2346. * ```
  2347. *
  2348. * 2. An array of objects with named values. The objects are point
  2349. * configuration objects as seen below. If the total number of data
  2350. * points exceeds the series' [turboThreshold](#series.gauge.turboThreshold),
  2351. * this option is not available.
  2352. *
  2353. * ```js
  2354. * data: [{
  2355. * y: 6,
  2356. * name: "Point2",
  2357. * color: "#00FF00"
  2358. * }, {
  2359. * y: 8,
  2360. * name: "Point1",
  2361. * color: "#FF00FF"
  2362. * }]</pre>
  2363. *
  2364. * The typical gauge only contains a single data value.
  2365. *
  2366. * @type {Array<Object|Number>}
  2367. * @extends series.line.data
  2368. * @excluding drilldown,marker,x
  2369. * @sample {highcharts} highcharts/chart/reflow-true/
  2370. * Numerical values
  2371. * @sample {highcharts} highcharts/series/data-array-of-arrays/
  2372. * Arrays of numeric x and y
  2373. * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
  2374. * Arrays of datetime x and y
  2375. * @sample {highcharts} highcharts/series/data-array-of-name-value/
  2376. * Arrays of point.name and y
  2377. * @sample {highcharts} highcharts/series/data-array-of-objects/
  2378. * Config objects
  2379. * @product highcharts
  2380. * @apioption series.gauge.data
  2381. */
  2382. }(Highcharts));
  2383. (function (H) {
  2384. /**
  2385. * (c) 2010-2017 Torstein Honsi
  2386. *
  2387. * License: www.highcharts.com/license
  2388. */
  2389. var each = H.each,
  2390. noop = H.noop,
  2391. pick = H.pick,
  2392. seriesType = H.seriesType,
  2393. seriesTypes = H.seriesTypes;
  2394. /**
  2395. * The boxplot series type.
  2396. *
  2397. * @constructor seriesTypes.boxplot
  2398. * @augments seriesTypes.column
  2399. */
  2400. /**
  2401. * A box plot is a convenient way of depicting groups of data through their
  2402. * five-number summaries: the smallest observation (sample minimum), lower
  2403. * quartile (Q1), median (Q2), upper quartile (Q3), and largest observation
  2404. * (sample maximum).
  2405. *
  2406. * @sample highcharts/demo/box-plot/ Box plot
  2407. * @extends {plotOptions.column}
  2408. * @product highcharts
  2409. * @excluding borderColor,borderRadius,borderWidth,groupZPadding,states
  2410. * @optionparent plotOptions.boxplot
  2411. */
  2412. seriesType('boxplot', 'column', {
  2413. threshold: null,
  2414. tooltip: {
  2415. pointFormat: // eslint-disable-line no-dupe-keys
  2416. '<span style="color:{point.color}">\u25CF</span> <b> ' +
  2417. '{series.name}</b><br/>' +
  2418. 'Maximum: {point.high}<br/>' +
  2419. 'Upper quartile: {point.q3}<br/>' +
  2420. 'Median: {point.median}<br/>' +
  2421. 'Lower quartile: {point.q1}<br/>' +
  2422. 'Minimum: {point.low}<br/>'
  2423. },
  2424. /**
  2425. * The length of the whiskers, the horizontal lines marking low and
  2426. * high values. It can be a numerical pixel value, or a percentage
  2427. * value of the box width. Set `0` to disable whiskers.
  2428. *
  2429. * @type {Number|String}
  2430. * @sample {highcharts} highcharts/plotoptions/box-plot-styling/
  2431. * True by default
  2432. * @since 3.0
  2433. * @product highcharts
  2434. */
  2435. whiskerLength: '50%',
  2436. /**
  2437. * The fill color of the box.
  2438. *
  2439. * In styled mode, the fill color can be set with the
  2440. * `.highcharts-boxplot-box` class.
  2441. *
  2442. * @type {Color}
  2443. * @sample {highcharts} highcharts/plotoptions/box-plot-styling/
  2444. * Box plot styling
  2445. * @default #ffffff
  2446. * @since 3.0
  2447. * @product highcharts
  2448. */
  2449. fillColor: '#ffffff',
  2450. /**
  2451. * The width of the line surrounding the box. If any of
  2452. * [stemWidth](#plotOptions.boxplot.stemWidth),
  2453. * [medianWidth](#plotOptions.boxplot.medianWidth)
  2454. * or [whiskerWidth](#plotOptions.boxplot.whiskerWidth) are `null`,
  2455. * the lineWidth also applies to these lines.
  2456. *
  2457. * @sample {highcharts} highcharts/plotoptions/box-plot-styling/
  2458. * Box plot styling
  2459. * @sample {highcharts} highcharts/plotoptions/error-bar-styling/
  2460. * Error bar styling
  2461. * @since 3.0
  2462. * @product highcharts
  2463. */
  2464. lineWidth: 1,
  2465. /**
  2466. * The color of the median line. If `null`, the general series color
  2467. * applies.
  2468. *
  2469. * In styled mode, the median stroke width can be set with the
  2470. * `.highcharts-boxplot-median` class.
  2471. *
  2472. * @type {Color}
  2473. * @sample {highcharts} highcharts/plotoptions/box-plot-styling/
  2474. * Box plot styling
  2475. * @sample {highcharts} highcharts/css/boxplot/
  2476. * Box plot in styled mode
  2477. * @sample {highcharts} highcharts/plotoptions/error-bar-styling/
  2478. * Error bar styling
  2479. * @default null
  2480. * @since 3.0
  2481. * @product highcharts
  2482. * @apioption plotOptions.boxplot.medianColor
  2483. */
  2484. /**
  2485. * The pixel width of the median line. If `null`, the
  2486. * [lineWidth](#plotOptions.boxplot.lineWidth) is used.
  2487. *
  2488. * In styled mode, the median stroke width can be set with the
  2489. * `.highcharts-boxplot-median` class.
  2490. *
  2491. * @sample {highcharts} highcharts/plotoptions/box-plot-styling/
  2492. * Box plot styling
  2493. * @sample {highcharts} highcharts/css/boxplot/
  2494. * Box plot in styled mode
  2495. * @since 3.0
  2496. * @product highcharts
  2497. */
  2498. medianWidth: 2,
  2499. /*
  2500. // States are not working and are removed from docs.
  2501. // Refer to: #2340
  2502. states: {
  2503. hover: {
  2504. brightness: -0.3
  2505. }
  2506. },
  2507. */
  2508. /**
  2509. * The color of the stem, the vertical line extending from the box to
  2510. * the whiskers. If `null`, the series color is used.
  2511. *
  2512. * In styled mode, the stem stroke can be set with the
  2513. * `.highcharts-boxplot-stem` class.
  2514. *
  2515. * @type {Color}
  2516. * @sample {highcharts} highcharts/plotoptions/box-plot-styling/
  2517. * Box plot styling
  2518. * @sample {highcharts} highcharts/css/boxplot/
  2519. * Box plot in styled mode
  2520. * @sample {highcharts} highcharts/plotoptions/error-bar-styling/
  2521. * Error bar styling
  2522. * @default null
  2523. * @since 3.0
  2524. * @product highcharts
  2525. * @apioption plotOptions.boxplot.stemColor
  2526. */
  2527. /**
  2528. * The dash style of the stem, the vertical line extending from the
  2529. * box to the whiskers.
  2530. *
  2531. * @validvalue ["Solid", "ShortDash", "ShortDot", "ShortDashDot",
  2532. * "ShortDashDotDot", "Dot", "Dash" ,"LongDash", "DashDot",
  2533. * "LongDashDot", "LongDashDotDot"]
  2534. * @type {String}
  2535. * @sample {highcharts} highcharts/plotoptions/box-plot-styling/
  2536. * Box plot styling
  2537. * @sample {highcharts} highcharts/css/boxplot/
  2538. * Box plot in styled mode
  2539. * @sample {highcharts} highcharts/plotoptions/error-bar-styling/
  2540. * Error bar styling
  2541. * @default Solid
  2542. * @since 3.0
  2543. * @product highcharts
  2544. * @apioption plotOptions.boxplot.stemDashStyle
  2545. */
  2546. /**
  2547. * The width of the stem, the vertical line extending from the box to
  2548. * the whiskers. If `null`, the width is inherited from the
  2549. * [lineWidth](#plotOptions.boxplot.lineWidth) option.
  2550. *
  2551. * In styled mode, the stem stroke width can be set with the
  2552. * `.highcharts-boxplot-stem` class.
  2553. *
  2554. * @type {Number}
  2555. * @sample {highcharts} highcharts/plotoptions/box-plot-styling/
  2556. * Box plot styling
  2557. * @sample {highcharts} highcharts/css/boxplot/
  2558. * Box plot in styled mode
  2559. * @sample {highcharts} highcharts/plotoptions/error-bar-styling/
  2560. * Error bar styling
  2561. * @default null
  2562. * @since 3.0
  2563. * @product highcharts
  2564. * @apioption plotOptions.boxplot.stemWidth
  2565. */
  2566. /**
  2567. * The color of the whiskers, the horizontal lines marking low and high
  2568. * values. When `null`, the general series color is used.
  2569. *
  2570. * In styled mode, the whisker stroke can be set with the
  2571. * `.highcharts-boxplot-whisker` class .
  2572. *
  2573. * @type {Color}
  2574. * @sample {highcharts} highcharts/plotoptions/box-plot-styling/
  2575. * Box plot styling
  2576. * @sample {highcharts} highcharts/css/boxplot/
  2577. * Box plot in styled mode
  2578. * @default null
  2579. * @since 3.0
  2580. * @product highcharts
  2581. * @apioption plotOptions.boxplot.whiskerColor
  2582. */
  2583. /**
  2584. * The line width of the whiskers, the horizontal lines marking low and
  2585. * high values. When `null`, the general
  2586. * [lineWidth](#plotOptions.boxplot.lineWidth) applies.
  2587. *
  2588. * In styled mode, the whisker stroke width can be set with the
  2589. * `.highcharts-boxplot-whisker` class.
  2590. *
  2591. * @sample {highcharts} highcharts/plotoptions/box-plot-styling/
  2592. * Box plot styling
  2593. * @sample {highcharts} highcharts/css/boxplot/
  2594. * Box plot in styled mode
  2595. * @since 3.0
  2596. * @product highcharts
  2597. */
  2598. whiskerWidth: 2
  2599. }, /** @lends seriesTypes.boxplot */ {
  2600. // array point configs are mapped to this
  2601. pointArrayMap: ['low', 'q1', 'median', 'q3', 'high'],
  2602. toYData: function (point) { // return a plain array for speedy calculation
  2603. return [point.low, point.q1, point.median, point.q3, point.high];
  2604. },
  2605. // defines the top of the tracker
  2606. pointValKey: 'high',
  2607. /**
  2608. * Get presentational attributes
  2609. */
  2610. pointAttribs: function () {
  2611. // No attributes should be set on point.graphic which is the group
  2612. return {};
  2613. },
  2614. /**
  2615. * Disable data labels for box plot
  2616. */
  2617. drawDataLabels: noop,
  2618. /**
  2619. * Translate data points from raw values x and y to plotX and plotY
  2620. */
  2621. translate: function () {
  2622. var series = this,
  2623. yAxis = series.yAxis,
  2624. pointArrayMap = series.pointArrayMap;
  2625. seriesTypes.column.prototype.translate.apply(series);
  2626. // do the translation on each point dimension
  2627. each(series.points, function (point) {
  2628. each(pointArrayMap, function (key) {
  2629. if (point[key] !== null) {
  2630. point[key + 'Plot'] = yAxis.translate(
  2631. point[key], 0, 1, 0, 1
  2632. );
  2633. }
  2634. });
  2635. });
  2636. },
  2637. /**
  2638. * Draw the data points
  2639. */
  2640. drawPoints: function () {
  2641. var series = this,
  2642. points = series.points,
  2643. options = series.options,
  2644. chart = series.chart,
  2645. renderer = chart.renderer,
  2646. q1Plot,
  2647. q3Plot,
  2648. highPlot,
  2649. lowPlot,
  2650. medianPlot,
  2651. medianPath,
  2652. crispCorr,
  2653. crispX = 0,
  2654. boxPath,
  2655. width,
  2656. left,
  2657. right,
  2658. halfWidth,
  2659. // error bar inherits this series type but doesn't do quartiles
  2660. doQuartiles = series.doQuartiles !== false,
  2661. pointWiskerLength,
  2662. whiskerLength = series.options.whiskerLength;
  2663. each(points, function (point) {
  2664. var graphic = point.graphic,
  2665. verb = graphic ? 'animate' : 'attr',
  2666. shapeArgs = point.shapeArgs; // the box
  2667. var boxAttr = {},
  2668. stemAttr = {},
  2669. whiskersAttr = {},
  2670. medianAttr = {},
  2671. color = point.color || series.color;
  2672. if (point.plotY !== undefined) {
  2673. // crisp vector coordinates
  2674. width = shapeArgs.width;
  2675. left = Math.floor(shapeArgs.x);
  2676. right = left + width;
  2677. halfWidth = Math.round(width / 2);
  2678. q1Plot = Math.floor(doQuartiles ? point.q1Plot : point.lowPlot);
  2679. q3Plot = Math.floor(doQuartiles ? point.q3Plot : point.lowPlot);
  2680. highPlot = Math.floor(point.highPlot);
  2681. lowPlot = Math.floor(point.lowPlot);
  2682. if (!graphic) {
  2683. point.graphic = graphic = renderer.g('point')
  2684. .add(series.group);
  2685. point.stem = renderer.path()
  2686. .addClass('highcharts-boxplot-stem')
  2687. .add(graphic);
  2688. if (whiskerLength) {
  2689. point.whiskers = renderer.path()
  2690. .addClass('highcharts-boxplot-whisker')
  2691. .add(graphic);
  2692. }
  2693. if (doQuartiles) {
  2694. point.box = renderer.path(boxPath)
  2695. .addClass('highcharts-boxplot-box')
  2696. .add(graphic);
  2697. }
  2698. point.medianShape = renderer.path(medianPath)
  2699. .addClass('highcharts-boxplot-median')
  2700. .add(graphic);
  2701. }
  2702. // Stem attributes
  2703. stemAttr.stroke = point.stemColor || options.stemColor || color;
  2704. stemAttr['stroke-width'] = pick(
  2705. point.stemWidth,
  2706. options.stemWidth,
  2707. options.lineWidth
  2708. );
  2709. stemAttr.dashstyle =
  2710. point.stemDashStyle || options.stemDashStyle;
  2711. point.stem.attr(stemAttr);
  2712. // Whiskers attributes
  2713. if (whiskerLength) {
  2714. whiskersAttr.stroke =
  2715. point.whiskerColor || options.whiskerColor || color;
  2716. whiskersAttr['stroke-width'] = pick(
  2717. point.whiskerWidth,
  2718. options.whiskerWidth,
  2719. options.lineWidth
  2720. );
  2721. point.whiskers.attr(whiskersAttr);
  2722. }
  2723. if (doQuartiles) {
  2724. boxAttr.fill = (
  2725. point.fillColor ||
  2726. options.fillColor ||
  2727. color
  2728. );
  2729. boxAttr.stroke = options.lineColor || color;
  2730. boxAttr['stroke-width'] = options.lineWidth || 0;
  2731. point.box.attr(boxAttr);
  2732. }
  2733. // Median attributes
  2734. medianAttr.stroke =
  2735. point.medianColor || options.medianColor || color;
  2736. medianAttr['stroke-width'] = pick(
  2737. point.medianWidth,
  2738. options.medianWidth,
  2739. options.lineWidth
  2740. );
  2741. point.medianShape.attr(medianAttr);
  2742. // The stem
  2743. crispCorr = (point.stem.strokeWidth() % 2) / 2;
  2744. crispX = left + halfWidth + crispCorr;
  2745. point.stem[verb]({ d: [
  2746. // stem up
  2747. 'M',
  2748. crispX, q3Plot,
  2749. 'L',
  2750. crispX, highPlot,
  2751. // stem down
  2752. 'M',
  2753. crispX, q1Plot,
  2754. 'L',
  2755. crispX, lowPlot
  2756. ] });
  2757. // The box
  2758. if (doQuartiles) {
  2759. crispCorr = (point.box.strokeWidth() % 2) / 2;
  2760. q1Plot = Math.floor(q1Plot) + crispCorr;
  2761. q3Plot = Math.floor(q3Plot) + crispCorr;
  2762. left += crispCorr;
  2763. right += crispCorr;
  2764. point.box[verb]({ d: [
  2765. 'M',
  2766. left, q3Plot,
  2767. 'L',
  2768. left, q1Plot,
  2769. 'L',
  2770. right, q1Plot,
  2771. 'L',
  2772. right, q3Plot,
  2773. 'L',
  2774. left, q3Plot,
  2775. 'z'
  2776. ] });
  2777. }
  2778. // The whiskers
  2779. if (whiskerLength) {
  2780. crispCorr = (point.whiskers.strokeWidth() % 2) / 2;
  2781. highPlot = highPlot + crispCorr;
  2782. lowPlot = lowPlot + crispCorr;
  2783. pointWiskerLength = (/%$/).test(whiskerLength) ?
  2784. halfWidth * parseFloat(whiskerLength) / 100 :
  2785. whiskerLength / 2;
  2786. point.whiskers[verb]({ d: [
  2787. // High whisker
  2788. 'M',
  2789. crispX - pointWiskerLength,
  2790. highPlot,
  2791. 'L',
  2792. crispX + pointWiskerLength,
  2793. highPlot,
  2794. // Low whisker
  2795. 'M',
  2796. crispX - pointWiskerLength,
  2797. lowPlot,
  2798. 'L',
  2799. crispX + pointWiskerLength,
  2800. lowPlot
  2801. ] });
  2802. }
  2803. // The median
  2804. medianPlot = Math.round(point.medianPlot);
  2805. crispCorr = (point.medianShape.strokeWidth() % 2) / 2;
  2806. medianPlot = medianPlot + crispCorr;
  2807. point.medianShape[verb]({ d: [
  2808. 'M',
  2809. left,
  2810. medianPlot,
  2811. 'L',
  2812. right,
  2813. medianPlot
  2814. ] });
  2815. }
  2816. });
  2817. },
  2818. setStackedPoints: noop // #3890
  2819. });
  2820. /**
  2821. * A `boxplot` series. If the [type](#series.boxplot.type) option is
  2822. * not specified, it is inherited from [chart.type](#chart.type).
  2823. *
  2824. * @type {Object}
  2825. * @extends series,plotOptions.boxplot
  2826. * @excluding dataParser,dataURL,marker,stack,stacking,states
  2827. * @product highcharts
  2828. * @apioption series.boxplot
  2829. */
  2830. /**
  2831. * An array of data points for the series. For the `boxplot` series
  2832. * type, points can be given in the following ways:
  2833. *
  2834. * 1. An array of arrays with 6 or 5 values. In this case, the values
  2835. * correspond to `x,low,q1,median,q3,high`. If the first value is a
  2836. * string, it is applied as the name of the point, and the `x` value
  2837. * is inferred. The `x` value can also be omitted, in which case the
  2838. * inner arrays should be of length 5\. Then the `x` value is automatically
  2839. * calculated, either starting at 0 and incremented by 1, or from `pointStart`
  2840. * and `pointInterval` given in the series options.
  2841. *
  2842. * ```js
  2843. * data: [
  2844. * [0, 3, 0, 10, 3, 5],
  2845. * [1, 7, 8, 7, 2, 9],
  2846. * [2, 6, 9, 5, 1, 3]
  2847. * ]
  2848. * ```
  2849. *
  2850. * 2. An array of objects with named values. The objects are point
  2851. * configuration objects as seen below. If the total number of data
  2852. * points exceeds the series' [turboThreshold](#series.boxplot.turboThreshold),
  2853. * this option is not available.
  2854. *
  2855. * ```js
  2856. * data: [{
  2857. * x: 1,
  2858. * low: 4,
  2859. * q1: 9,
  2860. * median: 9,
  2861. * q3: 1,
  2862. * high: 10,
  2863. * name: "Point2",
  2864. * color: "#00FF00"
  2865. * }, {
  2866. * x: 1,
  2867. * low: 5,
  2868. * q1: 7,
  2869. * median: 3,
  2870. * q3: 6,
  2871. * high: 2,
  2872. * name: "Point1",
  2873. * color: "#FF00FF"
  2874. * }]
  2875. * ```
  2876. *
  2877. * @type {Array<Object|Array>}
  2878. * @extends series.line.data
  2879. * @excluding marker
  2880. * @sample {highcharts} highcharts/chart/reflow-true/
  2881. * Numerical values
  2882. * @sample {highcharts} highcharts/series/data-array-of-arrays/
  2883. * Arrays of numeric x and y
  2884. * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
  2885. * Arrays of datetime x and y
  2886. * @sample {highcharts} highcharts/series/data-array-of-name-value/
  2887. * Arrays of point.name and y
  2888. * @sample {highcharts} highcharts/series/data-array-of-objects/
  2889. * Config objects
  2890. * @product highcharts
  2891. * @apioption series.boxplot.data
  2892. */
  2893. /**
  2894. * The `high` value for each data point, signifying the highest value
  2895. * in the sample set. The top whisker is drawn here.
  2896. *
  2897. * @type {Number}
  2898. * @product highcharts
  2899. * @apioption series.boxplot.data.high
  2900. */
  2901. /**
  2902. * The `low` value for each data point, signifying the lowest value
  2903. * in the sample set. The bottom whisker is drawn here.
  2904. *
  2905. * @type {Number}
  2906. * @product highcharts
  2907. * @apioption series.boxplot.data.low
  2908. */
  2909. /**
  2910. * The median for each data point. This is drawn as a line through the
  2911. * middle area of the box.
  2912. *
  2913. * @type {Number}
  2914. * @product highcharts
  2915. * @apioption series.boxplot.data.median
  2916. */
  2917. /**
  2918. * The lower quartile for each data point. This is the bottom of the
  2919. * box.
  2920. *
  2921. * @type {Number}
  2922. * @product highcharts
  2923. * @apioption series.boxplot.data.q1
  2924. */
  2925. /**
  2926. * The higher quartile for each data point. This is the top of the box.
  2927. *
  2928. * @type {Number}
  2929. * @product highcharts
  2930. * @apioption series.boxplot.data.q3
  2931. */
  2932. }(Highcharts));
  2933. (function (H) {
  2934. /**
  2935. * (c) 2010-2017 Torstein Honsi
  2936. *
  2937. * License: www.highcharts.com/license
  2938. */
  2939. var each = H.each,
  2940. noop = H.noop,
  2941. seriesType = H.seriesType,
  2942. seriesTypes = H.seriesTypes;
  2943. /**
  2944. * Error bars are a graphical representation of the variability of data and are
  2945. * used on graphs to indicate the error, or uncertainty in a reported
  2946. * measurement.
  2947. *
  2948. * @sample highcharts/demo/error-bar/
  2949. * Error bars
  2950. * @extends {plotOptions.boxplot}
  2951. * @product highcharts highstock
  2952. * @optionparent plotOptions.errorbar
  2953. */
  2954. seriesType('errorbar', 'boxplot', {
  2955. /**
  2956. * The main color of the bars. This can be overridden by
  2957. * [stemColor](#plotOptions.errorbar.stemColor) and
  2958. * [whiskerColor](#plotOptions.errorbar.whiskerColor) individually.
  2959. *
  2960. * @type {Color}
  2961. * @sample {highcharts} highcharts/plotoptions/error-bar-styling/
  2962. * Error bar styling
  2963. * @default #000000
  2964. * @since 3.0
  2965. * @product highcharts
  2966. */
  2967. color: '#000000',
  2968. grouping: false,
  2969. /**
  2970. * The parent series of the error bar. The default value links it to
  2971. * the previous series. Otherwise, use the id of the parent series.
  2972. *
  2973. * @since 3.0
  2974. * @product highcharts
  2975. */
  2976. linkedTo: ':previous',
  2977. tooltip: {
  2978. pointFormat: '<span style="color:{point.color}">\u25CF</span> {series.name}: <b>{point.low}</b> - <b>{point.high}</b><br/>'
  2979. },
  2980. /**
  2981. * The line width of the whiskers, the horizontal lines marking low
  2982. * and high values. When `null`, the general
  2983. * [lineWidth](#plotOptions.errorbar.lineWidth) applies.
  2984. *
  2985. * @type {Number}
  2986. * @sample {highcharts} highcharts/plotoptions/error-bar-styling/
  2987. * Error bar styling
  2988. * @since 3.0
  2989. * @product highcharts
  2990. */
  2991. whiskerWidth: null
  2992. // Prototype members
  2993. }, {
  2994. type: 'errorbar',
  2995. pointArrayMap: ['low', 'high'], // array point configs are mapped to this
  2996. toYData: function (point) { // return a plain array for speedy calculation
  2997. return [point.low, point.high];
  2998. },
  2999. pointValKey: 'high', // defines the top of the tracker
  3000. doQuartiles: false,
  3001. drawDataLabels: seriesTypes.arearange ?
  3002. function () {
  3003. var valKey = this.pointValKey;
  3004. seriesTypes.arearange.prototype.drawDataLabels.call(this);
  3005. // Arearange drawDataLabels does not reset point.y to high,
  3006. // but to low after drawing (#4133)
  3007. each(this.data, function (point) {
  3008. point.y = point[valKey];
  3009. });
  3010. } :
  3011. noop,
  3012. /**
  3013. * Get the width and X offset, either on top of the linked series column
  3014. * or standalone
  3015. */
  3016. getColumnMetrics: function () {
  3017. return (this.linkedParent && this.linkedParent.columnMetrics) ||
  3018. seriesTypes.column.prototype.getColumnMetrics.call(this);
  3019. }
  3020. });
  3021. /**
  3022. * A `errorbar` series. If the [type](#series.errorbar.type) option
  3023. * is not specified, it is inherited from [chart.type](#chart.type).
  3024. *
  3025. * @type {Object}
  3026. * @extends series,plotOptions.errorbar
  3027. * @excluding dataParser,dataURL,stack,stacking
  3028. * @product highcharts
  3029. * @apioption series.errorbar
  3030. */
  3031. /**
  3032. * An array of data points for the series. For the `errorbar` series
  3033. * type, points can be given in the following ways:
  3034. *
  3035. * 1. An array of arrays with 3 or 2 values. In this case, the values
  3036. * correspond to `x,low,high`. If the first value is a string, it is
  3037. * applied as the name of the point, and the `x` value is inferred.
  3038. * The `x` value can also be omitted, in which case the inner arrays
  3039. * should be of length 2\. Then the `x` value is automatically calculated,
  3040. * either starting at 0 and incremented by 1, or from `pointStart`
  3041. * and `pointInterval` given in the series options.
  3042. *
  3043. * ```js
  3044. * data: [
  3045. * [0, 10, 2],
  3046. * [1, 1, 8],
  3047. * [2, 4, 5]
  3048. * ]
  3049. * ```
  3050. *
  3051. * 2. An array of objects with named values. The objects are point
  3052. * configuration objects as seen below. If the total number of data
  3053. * points exceeds the series' [turboThreshold](#series.errorbar.turboThreshold),
  3054. * this option is not available.
  3055. *
  3056. * ```js
  3057. * data: [{
  3058. * x: 1,
  3059. * low: 0,
  3060. * high: 0,
  3061. * name: "Point2",
  3062. * color: "#00FF00"
  3063. * }, {
  3064. * x: 1,
  3065. * low: 5,
  3066. * high: 5,
  3067. * name: "Point1",
  3068. * color: "#FF00FF"
  3069. * }]
  3070. * ```
  3071. *
  3072. * @type {Array<Object|Array>}
  3073. * @extends series.arearange.data
  3074. * @excluding dataLabels,drilldown,marker,states
  3075. * @sample {highcharts} highcharts/chart/reflow-true/
  3076. * Numerical values
  3077. * @sample {highcharts} highcharts/series/data-array-of-arrays/
  3078. * Arrays of numeric x and y
  3079. * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
  3080. * Arrays of datetime x and y
  3081. * @sample {highcharts} highcharts/series/data-array-of-name-value/
  3082. * Arrays of point.name and y
  3083. * @sample {highcharts} highcharts/series/data-array-of-objects/
  3084. * Config objects
  3085. * @product highcharts
  3086. * @apioption series.errorbar.data
  3087. */
  3088. }(Highcharts));
  3089. (function (H) {
  3090. /**
  3091. * (c) 2010-2017 Torstein Honsi
  3092. *
  3093. * License: www.highcharts.com/license
  3094. */
  3095. var correctFloat = H.correctFloat,
  3096. isNumber = H.isNumber,
  3097. pick = H.pick,
  3098. Point = H.Point,
  3099. Series = H.Series,
  3100. seriesType = H.seriesType,
  3101. seriesTypes = H.seriesTypes;
  3102. /**
  3103. * A waterfall chart displays sequentially introduced positive or negative
  3104. * values in cumulative columns.
  3105. *
  3106. * @sample highcharts/demo/waterfall/
  3107. * Waterfall chart
  3108. * @sample highcharts/plotoptions/waterfall-stacked/
  3109. * Stacked waterfall chart
  3110. * @extends {plotOptions.column}
  3111. * @product highcharts
  3112. * @optionparent plotOptions.waterfall
  3113. */
  3114. seriesType('waterfall', 'column', {
  3115. /**
  3116. * The color used specifically for positive point columns. When not
  3117. * specified, the general series color is used.
  3118. *
  3119. * In styled mode, the waterfall colors can be set with the
  3120. * `.highcharts-point-negative`, `.highcharts-sum` and
  3121. * `.highcharts-intermediate-sum` classes.
  3122. *
  3123. * @type {Color}
  3124. * @sample {highcharts} highcharts/demo/waterfall/ Waterfall
  3125. * @product highcharts
  3126. * @apioption plotOptions.waterfall.upColor
  3127. */
  3128. dataLabels: {
  3129. inside: true
  3130. },
  3131. /**
  3132. * The width of the line connecting waterfall columns.
  3133. *
  3134. * @product highcharts
  3135. */
  3136. lineWidth: 1,
  3137. /**
  3138. * The color of the line that connects columns in a waterfall series.
  3139. *
  3140. * In styled mode, the stroke can be set with the `.highcharts-graph` class.
  3141. *
  3142. * @type {Color}
  3143. * @default #333333
  3144. * @since 3.0
  3145. * @product highcharts
  3146. */
  3147. lineColor: '#333333',
  3148. /**
  3149. * A name for the dash style to use for the line connecting the columns
  3150. * of the waterfall series. Possible values:
  3151. *
  3152. * * Solid
  3153. * * ShortDash
  3154. * * ShortDot
  3155. * * ShortDashDot
  3156. * * ShortDashDotDot
  3157. * * Dot
  3158. * * Dash
  3159. * * LongDash
  3160. * * DashDot
  3161. * * LongDashDot
  3162. * * LongDashDotDot
  3163. *
  3164. * In styled mode, the stroke dash-array can be set with the
  3165. * `.highcharts-graph` class.
  3166. *
  3167. * @type {String}
  3168. * @default Dot
  3169. * @since 3.0
  3170. * @product highcharts
  3171. */
  3172. dashStyle: 'dot',
  3173. /**
  3174. * The color of the border of each waterfall column.
  3175. *
  3176. * In styled mode, the border stroke can be set with the
  3177. * `.highcharts-point` class.
  3178. *
  3179. * @type {Color}
  3180. * @default #333333
  3181. * @since 3.0
  3182. * @product highcharts
  3183. */
  3184. borderColor: '#333333',
  3185. states: {
  3186. hover: {
  3187. lineWidthPlus: 0 // #3126
  3188. }
  3189. }
  3190. // Prototype members
  3191. }, {
  3192. pointValKey: 'y',
  3193. /**
  3194. * Property needed to prevent lines between the columns from disappearing
  3195. * when negativeColor is used.
  3196. */
  3197. showLine: true,
  3198. /**
  3199. * Translate data points from raw values
  3200. */
  3201. translate: function () {
  3202. var series = this,
  3203. options = series.options,
  3204. yAxis = series.yAxis,
  3205. len,
  3206. i,
  3207. points,
  3208. point,
  3209. shapeArgs,
  3210. stack,
  3211. y,
  3212. yValue,
  3213. previousY,
  3214. previousIntermediate,
  3215. range,
  3216. minPointLength = pick(options.minPointLength, 5),
  3217. halfMinPointLength = minPointLength / 2,
  3218. threshold = options.threshold,
  3219. stacking = options.stacking,
  3220. stackIndicator,
  3221. tooltipY;
  3222. // run column series translate
  3223. seriesTypes.column.prototype.translate.apply(series);
  3224. previousY = previousIntermediate = threshold;
  3225. points = series.points;
  3226. for (i = 0, len = points.length; i < len; i++) {
  3227. // cache current point object
  3228. point = points[i];
  3229. yValue = series.processedYData[i];
  3230. shapeArgs = point.shapeArgs;
  3231. // get current stack
  3232. stack = stacking &&
  3233. yAxis.stacks[
  3234. (series.negStacks && yValue < threshold ? '-' : '') +
  3235. series.stackKey
  3236. ];
  3237. stackIndicator = series.getStackIndicator(
  3238. stackIndicator,
  3239. point.x,
  3240. series.index
  3241. );
  3242. range = pick(
  3243. stack && stack[point.x].points[stackIndicator.key],
  3244. [0, yValue]
  3245. );
  3246. // override point value for sums
  3247. // #3710 Update point does not propagate to sum
  3248. if (point.isSum) {
  3249. point.y = correctFloat(yValue);
  3250. } else if (point.isIntermediateSum) {
  3251. point.y = correctFloat(yValue - previousIntermediate); // #3840
  3252. }
  3253. // up points
  3254. y = Math.max(previousY, previousY + point.y) + range[0];
  3255. shapeArgs.y = yAxis.translate(y, 0, 1, 0, 1);
  3256. // sum points
  3257. if (point.isSum) {
  3258. shapeArgs.y = yAxis.translate(range[1], 0, 1, 0, 1);
  3259. shapeArgs.height = Math.min(
  3260. yAxis.translate(range[0], 0, 1, 0, 1),
  3261. yAxis.len
  3262. ) - shapeArgs.y; // #4256
  3263. } else if (point.isIntermediateSum) {
  3264. shapeArgs.y = yAxis.translate(range[1], 0, 1, 0, 1);
  3265. shapeArgs.height = Math.min(
  3266. yAxis.translate(previousIntermediate, 0, 1, 0, 1),
  3267. yAxis.len
  3268. ) - shapeArgs.y;
  3269. previousIntermediate = range[1];
  3270. // If it's not the sum point, update previous stack end position
  3271. // and get shape height (#3886)
  3272. } else {
  3273. shapeArgs.height = yValue > 0 ?
  3274. yAxis.translate(previousY, 0, 1, 0, 1) - shapeArgs.y :
  3275. yAxis.translate(previousY, 0, 1, 0, 1) -
  3276. yAxis.translate(previousY - yValue, 0, 1, 0, 1);
  3277. previousY += stack && stack[point.x] ?
  3278. stack[point.x].total :
  3279. yValue;
  3280. }
  3281. // #3952 Negative sum or intermediate sum not rendered correctly
  3282. if (shapeArgs.height < 0) {
  3283. shapeArgs.y += shapeArgs.height;
  3284. shapeArgs.height *= -1;
  3285. }
  3286. point.plotY = shapeArgs.y = Math.round(shapeArgs.y) -
  3287. (series.borderWidth % 2) / 2;
  3288. // #3151
  3289. shapeArgs.height = Math.max(Math.round(shapeArgs.height), 0.001);
  3290. point.yBottom = shapeArgs.y + shapeArgs.height;
  3291. if (shapeArgs.height <= minPointLength && !point.isNull) {
  3292. shapeArgs.height = minPointLength;
  3293. shapeArgs.y -= halfMinPointLength;
  3294. point.plotY = shapeArgs.y;
  3295. if (point.y < 0) {
  3296. point.minPointLengthOffset = -halfMinPointLength;
  3297. } else {
  3298. point.minPointLengthOffset = halfMinPointLength;
  3299. }
  3300. } else {
  3301. point.minPointLengthOffset = 0;
  3302. }
  3303. // Correct tooltip placement (#3014)
  3304. tooltipY = point.plotY + (point.negative ? shapeArgs.height : 0);
  3305. if (series.chart.inverted) {
  3306. point.tooltipPos[0] = yAxis.len - tooltipY;
  3307. } else {
  3308. point.tooltipPos[1] = tooltipY;
  3309. }
  3310. }
  3311. },
  3312. /**
  3313. * Call default processData then override yData to reflect
  3314. * waterfall's extremes on yAxis
  3315. */
  3316. processData: function (force) {
  3317. var series = this,
  3318. options = series.options,
  3319. yData = series.yData,
  3320. // #3710 Update point does not propagate to sum
  3321. points = series.options.data,
  3322. point,
  3323. dataLength = yData.length,
  3324. threshold = options.threshold || 0,
  3325. subSum,
  3326. sum,
  3327. dataMin,
  3328. dataMax,
  3329. y,
  3330. i;
  3331. sum = subSum = dataMin = dataMax = threshold;
  3332. for (i = 0; i < dataLength; i++) {
  3333. y = yData[i];
  3334. point = points && points[i] ? points[i] : {};
  3335. if (y === 'sum' || point.isSum) {
  3336. yData[i] = correctFloat(sum);
  3337. } else if (y === 'intermediateSum' || point.isIntermediateSum) {
  3338. yData[i] = correctFloat(subSum);
  3339. } else {
  3340. sum += y;
  3341. subSum += y;
  3342. }
  3343. dataMin = Math.min(sum, dataMin);
  3344. dataMax = Math.max(sum, dataMax);
  3345. }
  3346. Series.prototype.processData.call(this, force);
  3347. // Record extremes only if stacking was not set:
  3348. if (!series.options.stacking) {
  3349. series.dataMin = dataMin;
  3350. series.dataMax = dataMax;
  3351. }
  3352. },
  3353. /**
  3354. * Return y value or string if point is sum
  3355. */
  3356. toYData: function (pt) {
  3357. if (pt.isSum) {
  3358. // #3245 Error when first element is Sum or Intermediate Sum
  3359. return (pt.x === 0 ? null : 'sum');
  3360. }
  3361. if (pt.isIntermediateSum) {
  3362. return (pt.x === 0 ? null : 'intermediateSum'); // #3245
  3363. }
  3364. return pt.y;
  3365. },
  3366. /**
  3367. * Postprocess mapping between options and SVG attributes
  3368. */
  3369. pointAttribs: function (point, state) {
  3370. var upColor = this.options.upColor,
  3371. attr;
  3372. // Set or reset up color (#3710, update to negative)
  3373. if (upColor && !point.options.color) {
  3374. point.color = point.y > 0 ? upColor : null;
  3375. }
  3376. attr = seriesTypes.column.prototype.pointAttribs.call(
  3377. this,
  3378. point,
  3379. state
  3380. );
  3381. // The dashStyle option in waterfall applies to the graph, not
  3382. // the points
  3383. delete attr.dashstyle;
  3384. return attr;
  3385. },
  3386. /**
  3387. * Return an empty path initially, because we need to know the
  3388. * stroke-width in order to set the final path.
  3389. */
  3390. getGraphPath: function () {
  3391. return ['M', 0, 0];
  3392. },
  3393. /**
  3394. * Draw columns' connector lines
  3395. */
  3396. getCrispPath: function () {
  3397. var data = this.data,
  3398. length = data.length,
  3399. lineWidth = this.graph.strokeWidth() + this.borderWidth,
  3400. normalizer = Math.round(lineWidth) % 2 / 2,
  3401. reversedXAxis = this.xAxis.reversed,
  3402. reversedYAxis = this.yAxis.reversed,
  3403. path = [],
  3404. prevArgs,
  3405. pointArgs,
  3406. i,
  3407. d;
  3408. for (i = 1; i < length; i++) {
  3409. pointArgs = data[i].shapeArgs;
  3410. prevArgs = data[i - 1].shapeArgs;
  3411. d = [
  3412. 'M',
  3413. prevArgs.x + (reversedXAxis ? 0 : prevArgs.width),
  3414. prevArgs.y + data[i - 1].minPointLengthOffset + normalizer,
  3415. 'L',
  3416. pointArgs.x + (reversedXAxis ? prevArgs.width : 0),
  3417. prevArgs.y + data[i - 1].minPointLengthOffset + normalizer
  3418. ];
  3419. if (
  3420. (data[i - 1].y < 0 && !reversedYAxis) ||
  3421. (data[i - 1].y > 0 && reversedYAxis)
  3422. ) {
  3423. d[2] += prevArgs.height;
  3424. d[5] += prevArgs.height;
  3425. }
  3426. path = path.concat(d);
  3427. }
  3428. return path;
  3429. },
  3430. /**
  3431. * The graph is initally drawn with an empty definition, then updated with
  3432. * crisp rendering.
  3433. */
  3434. drawGraph: function () {
  3435. Series.prototype.drawGraph.call(this);
  3436. this.graph.attr({
  3437. d: this.getCrispPath()
  3438. });
  3439. },
  3440. /**
  3441. * Waterfall has stacking along the x-values too.
  3442. */
  3443. setStackedPoints: function () {
  3444. var series = this,
  3445. options = series.options,
  3446. stackedYLength,
  3447. i;
  3448. Series.prototype.setStackedPoints.apply(series, arguments);
  3449. stackedYLength = series.stackedYData ? series.stackedYData.length : 0;
  3450. // Start from the second point:
  3451. for (i = 1; i < stackedYLength; i++) {
  3452. if (
  3453. !options.data[i].isSum &&
  3454. !options.data[i].isIntermediateSum
  3455. ) {
  3456. // Sum previous stacked data as waterfall can grow up/down:
  3457. series.stackedYData[i] += series.stackedYData[i - 1];
  3458. }
  3459. }
  3460. },
  3461. /**
  3462. * Extremes for a non-stacked series are recorded in processData.
  3463. * In case of stacking, use Series.stackedYData to calculate extremes.
  3464. */
  3465. getExtremes: function () {
  3466. if (this.options.stacking) {
  3467. return Series.prototype.getExtremes.apply(this, arguments);
  3468. }
  3469. }
  3470. // Point members
  3471. }, {
  3472. getClassName: function () {
  3473. var className = Point.prototype.getClassName.call(this);
  3474. if (this.isSum) {
  3475. className += ' highcharts-sum';
  3476. } else if (this.isIntermediateSum) {
  3477. className += ' highcharts-intermediate-sum';
  3478. }
  3479. return className;
  3480. },
  3481. /**
  3482. * Pass the null test in ColumnSeries.translate.
  3483. */
  3484. isValid: function () {
  3485. return isNumber(this.y, true) || this.isSum || this.isIntermediateSum;
  3486. }
  3487. });
  3488. /**
  3489. * A `waterfall` series. If the [type](#series.waterfall.type) option
  3490. * is not specified, it is inherited from [chart.type](#chart.type).
  3491. *
  3492. * @type {Object}
  3493. * @extends series,plotOptions.waterfall
  3494. * @excluding dataParser,dataURL
  3495. * @product highcharts
  3496. * @apioption series.waterfall
  3497. */
  3498. /**
  3499. * An array of data points for the series. For the `waterfall` series
  3500. * type, points can be given in the following ways:
  3501. *
  3502. * 1. An array of numerical values. In this case, the numerical values
  3503. * will be interpreted as `y` options. The `x` values will be automatically
  3504. * calculated, either starting at 0 and incremented by 1, or from `pointStart`
  3505. * and `pointInterval` given in the series options. If the axis has
  3506. * categories, these will be used. Example:
  3507. *
  3508. * ```js
  3509. * data: [0, 5, 3, 5]
  3510. * ```
  3511. *
  3512. * 2. An array of arrays with 2 values. In this case, the values correspond
  3513. * to `x,y`. If the first value is a string, it is applied as the name
  3514. * of the point, and the `x` value is inferred.
  3515. *
  3516. * ```js
  3517. * data: [
  3518. * [0, 7],
  3519. * [1, 8],
  3520. * [2, 3]
  3521. * ]
  3522. * ```
  3523. *
  3524. * 3. An array of objects with named values. The objects are point
  3525. * configuration objects as seen below. If the total number of data
  3526. * points exceeds the series'
  3527. * [turboThreshold](#series.waterfall.turboThreshold),
  3528. * this option is not available.
  3529. *
  3530. * ```js
  3531. * data: [{
  3532. * x: 1,
  3533. * y: 8,
  3534. * name: "Point2",
  3535. * color: "#00FF00"
  3536. * }, {
  3537. * x: 1,
  3538. * y: 8,
  3539. * name: "Point1",
  3540. * color: "#FF00FF"
  3541. * }]
  3542. * ```
  3543. *
  3544. * @type {Array<Object|Array|Number>}
  3545. * @extends series.line.data
  3546. * @excluding marker
  3547. * @sample {highcharts} highcharts/chart/reflow-true/
  3548. * Numerical values
  3549. * @sample {highcharts} highcharts/series/data-array-of-arrays/
  3550. * Arrays of numeric x and y
  3551. * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
  3552. * Arrays of datetime x and y
  3553. * @sample {highcharts} highcharts/series/data-array-of-name-value/
  3554. * Arrays of point.name and y
  3555. * @sample {highcharts} highcharts/series/data-array-of-objects/
  3556. * Config objects
  3557. * @product highcharts
  3558. * @apioption series.waterfall.data
  3559. */
  3560. /**
  3561. * When this property is true, the points acts as a summary column for
  3562. * the values added or substracted since the last intermediate sum,
  3563. * or since the start of the series. The `y` value is ignored.
  3564. *
  3565. * @type {Boolean}
  3566. * @sample {highcharts} highcharts/demo/waterfall/ Waterfall
  3567. * @default false
  3568. * @product highcharts
  3569. * @apioption series.waterfall.data.isIntermediateSum
  3570. */
  3571. /**
  3572. * When this property is true, the point display the total sum across
  3573. * the entire series. The `y` value is ignored.
  3574. *
  3575. * @type {Boolean}
  3576. * @sample {highcharts} highcharts/demo/waterfall/ Waterfall
  3577. * @default false
  3578. * @product highcharts
  3579. * @apioption series.waterfall.data.isSum
  3580. */
  3581. }(Highcharts));
  3582. (function (H) {
  3583. /**
  3584. * (c) 2010-2017 Torstein Honsi
  3585. *
  3586. * License: www.highcharts.com/license
  3587. */
  3588. var LegendSymbolMixin = H.LegendSymbolMixin,
  3589. noop = H.noop,
  3590. Series = H.Series,
  3591. seriesType = H.seriesType,
  3592. seriesTypes = H.seriesTypes;
  3593. /**
  3594. * A polygon series can be used to draw any freeform shape in the cartesian
  3595. * coordinate system. A fill is applied with the `color` option, and
  3596. * stroke is applied through `lineWidth` and `lineColor` options. Requires
  3597. * the `highcharts-more.js` file.
  3598. *
  3599. * @type {Object}
  3600. * @extends plotOptions.scatter
  3601. * @excluding softThreshold,threshold
  3602. * @sample {highcharts} highcharts/demo/polygon/ Polygon
  3603. * @sample {highstock} highcharts/demo/polygon/ Polygon
  3604. * @since 4.1.0
  3605. * @product highcharts highstock
  3606. * @optionparent plotOptions.polygon
  3607. */
  3608. seriesType('polygon', 'scatter', {
  3609. marker: {
  3610. enabled: false,
  3611. states: {
  3612. hover: {
  3613. enabled: false
  3614. }
  3615. }
  3616. },
  3617. stickyTracking: false,
  3618. tooltip: {
  3619. followPointer: true,
  3620. pointFormat: ''
  3621. },
  3622. trackByArea: true
  3623. // Prototype members
  3624. }, {
  3625. type: 'polygon',
  3626. getGraphPath: function () {
  3627. var graphPath = Series.prototype.getGraphPath.call(this),
  3628. i = graphPath.length + 1;
  3629. // Close all segments
  3630. while (i--) {
  3631. if ((i === graphPath.length || graphPath[i] === 'M') && i > 0) {
  3632. graphPath.splice(i, 0, 'z');
  3633. }
  3634. }
  3635. this.areaPath = graphPath;
  3636. return graphPath;
  3637. },
  3638. drawGraph: function () {
  3639. // Hack into the fill logic in area.drawGraph
  3640. this.options.fillColor = this.color;
  3641. seriesTypes.area.prototype.drawGraph.call(this);
  3642. },
  3643. drawLegendSymbol: LegendSymbolMixin.drawRectangle,
  3644. drawTracker: Series.prototype.drawTracker,
  3645. setStackedPoints: noop // No stacking points on polygons (#5310)
  3646. });
  3647. /**
  3648. * A `polygon` series. If the [type](#series.polygon.type) option is
  3649. * not specified, it is inherited from [chart.type](#chart.type).
  3650. *
  3651. * @type {Object}
  3652. * @extends series,plotOptions.polygon
  3653. * @excluding dataParser,dataURL,stack
  3654. * @product highcharts highstock
  3655. * @apioption series.polygon
  3656. */
  3657. /**
  3658. * An array of data points for the series. For the `polygon` series
  3659. * type, points can be given in the following ways:
  3660. *
  3661. * 1. An array of numerical values. In this case, the numerical values
  3662. * will be interpreted as `y` options. The `x` values will be automatically
  3663. * calculated, either starting at 0 and incremented by 1, or from `pointStart`
  3664. * and `pointInterval` given in the series options. If the axis has
  3665. * categories, these will be used. Example:
  3666. *
  3667. * ```js
  3668. * data: [0, 5, 3, 5]
  3669. * ```
  3670. *
  3671. * 2. An array of arrays with 2 values. In this case, the values correspond
  3672. * to `x,y`. If the first value is a string, it is applied as the name
  3673. * of the point, and the `x` value is inferred.
  3674. *
  3675. * ```js
  3676. * data: [
  3677. * [0, 10],
  3678. * [1, 3],
  3679. * [2, 1]
  3680. * ]
  3681. * ```
  3682. *
  3683. * 3. An array of objects with named values. The objects are point
  3684. * configuration objects as seen below. If the total number of data
  3685. * points exceeds the series' [turboThreshold](#series.polygon.turboThreshold),
  3686. * this option is not available.
  3687. *
  3688. * ```js
  3689. * data: [{
  3690. * x: 1,
  3691. * y: 1,
  3692. * name: "Point2",
  3693. * color: "#00FF00"
  3694. * }, {
  3695. * x: 1,
  3696. * y: 8,
  3697. * name: "Point1",
  3698. * color: "#FF00FF"
  3699. * }]
  3700. * ```
  3701. *
  3702. * @type {Array<Object|Array>}
  3703. * @extends series.line.data
  3704. * @sample {highcharts} highcharts/chart/reflow-true/
  3705. * Numerical values
  3706. * @sample {highcharts} highcharts/series/data-array-of-arrays/
  3707. * Arrays of numeric x and y
  3708. * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
  3709. * Arrays of datetime x and y
  3710. * @sample {highcharts} highcharts/series/data-array-of-name-value/
  3711. * Arrays of point.name and y
  3712. * @sample {highcharts} highcharts/series/data-array-of-objects/
  3713. * Config objects
  3714. * @product highcharts highstock
  3715. * @apioption series.polygon.data
  3716. */
  3717. }(Highcharts));
  3718. (function (H) {
  3719. /**
  3720. * (c) 2010-2017 Torstein Honsi
  3721. *
  3722. * License: www.highcharts.com/license
  3723. */
  3724. var arrayMax = H.arrayMax,
  3725. arrayMin = H.arrayMin,
  3726. Axis = H.Axis,
  3727. color = H.color,
  3728. each = H.each,
  3729. isNumber = H.isNumber,
  3730. noop = H.noop,
  3731. pick = H.pick,
  3732. pInt = H.pInt,
  3733. Point = H.Point,
  3734. Series = H.Series,
  3735. seriesType = H.seriesType,
  3736. seriesTypes = H.seriesTypes;
  3737. /**
  3738. * A bubble series is a three dimensional series type where each point renders
  3739. * an X, Y and Z value. Each points is drawn as a bubble where the position
  3740. * along the X and Y axes mark the X and Y values, and the size of the bubble
  3741. * relates to the Z value. Requires `highcharts-more.js`.
  3742. *
  3743. * @sample {highcharts} highcharts/demo/bubble/ Bubble chart
  3744. * @extends plotOptions.scatter
  3745. * @product highcharts highstock
  3746. * @optionparent plotOptions.bubble
  3747. */
  3748. seriesType('bubble', 'scatter', {
  3749. dataLabels: {
  3750. formatter: function () { // #2945
  3751. return this.point.z;
  3752. },
  3753. inside: true,
  3754. verticalAlign: 'middle'
  3755. },
  3756. /**
  3757. * If there are more points in the series than the `animationLimit`, the
  3758. * animation won't run. Animation affects overall performance and doesn't
  3759. * work well with heavy data series.
  3760. * @since 6.1.0
  3761. */
  3762. animationLimit: 250,
  3763. /**
  3764. * Whether to display negative sized bubbles. The threshold is given
  3765. * by the [zThreshold](#plotOptions.bubble.zThreshold) option, and negative
  3766. * bubbles can be visualized by setting
  3767. * [negativeColor](#plotOptions.bubble.negativeColor).
  3768. *
  3769. * @type {Boolean}
  3770. * @sample {highcharts} highcharts/plotoptions/bubble-negative/
  3771. * Negative bubbles
  3772. * @default true
  3773. * @since 3.0
  3774. * @apioption plotOptions.bubble.displayNegative
  3775. */
  3776. /**
  3777. * @extends plotOptions.series.marker
  3778. * @excluding enabled,enabledThreshold,height,radius,width
  3779. */
  3780. marker: {
  3781. lineColor: null, // inherit from series.color
  3782. lineWidth: 1,
  3783. /**
  3784. * The fill opacity of the bubble markers.
  3785. */
  3786. fillOpacity: 0.5,
  3787. /**
  3788. * In bubble charts, the radius is overridden and determined based on
  3789. * the point's data value.
  3790. */
  3791. /**
  3792. * @ignore-option
  3793. */
  3794. radius: null,
  3795. states: {
  3796. hover: {
  3797. radiusPlus: 0
  3798. }
  3799. },
  3800. /**
  3801. * A predefined shape or symbol for the marker. Possible values are
  3802. * "circle", "square", "diamond", "triangle" and "triangle-down".
  3803. *
  3804. * Additionally, the URL to a graphic can be given on the form
  3805. * `url(graphic.png)`. Note that for the image to be applied to exported
  3806. * charts, its URL needs to be accessible by the export server.
  3807. *
  3808. * Custom callbacks for symbol path generation can also be added to
  3809. * `Highcharts.SVGRenderer.prototype.symbols`. The callback is then
  3810. * used by its method name, as shown in the demo.
  3811. *
  3812. * @validvalue ["circle", "square", "diamond", "triangle",
  3813. * "triangle-down"]
  3814. * @sample {highcharts} highcharts/plotoptions/bubble-symbol/
  3815. * Bubble chart with various symbols
  3816. * @sample {highcharts} highcharts/plotoptions/series-marker-symbol/
  3817. * General chart with predefined, graphic and custom markers
  3818. * @since 5.0.11
  3819. */
  3820. symbol: 'circle'
  3821. },
  3822. /**
  3823. * Minimum bubble size. Bubbles will automatically size between the
  3824. * `minSize` and `maxSize` to reflect the `z` value of each bubble.
  3825. * Can be either pixels (when no unit is given), or a percentage of
  3826. * the smallest one of the plot width and height.
  3827. *
  3828. * @type {Number|String}
  3829. * @sample {highcharts} highcharts/plotoptions/bubble-size/ Bubble size
  3830. * @since 3.0
  3831. * @product highcharts highstock
  3832. */
  3833. minSize: 8,
  3834. /**
  3835. * Maximum bubble size. Bubbles will automatically size between the
  3836. * `minSize` and `maxSize` to reflect the `z` value of each bubble.
  3837. * Can be either pixels (when no unit is given), or a percentage of
  3838. * the smallest one of the plot width and height.
  3839. *
  3840. * @type {Number|String}
  3841. * @sample {highcharts} highcharts/plotoptions/bubble-size/
  3842. * Bubble size
  3843. * @since 3.0
  3844. * @product highcharts highstock
  3845. */
  3846. maxSize: '20%',
  3847. /**
  3848. * When a point's Z value is below the
  3849. * [zThreshold](#plotOptions.bubble.zThreshold) setting, this color is used.
  3850. *
  3851. * @type {Color}
  3852. * @sample {highcharts} highcharts/plotoptions/bubble-negative/
  3853. * Negative bubbles
  3854. * @default null
  3855. * @since 3.0
  3856. * @product highcharts
  3857. * @apioption plotOptions.bubble.negativeColor
  3858. */
  3859. /**
  3860. * Whether the bubble's value should be represented by the area or the
  3861. * width of the bubble. The default, `area`, corresponds best to the
  3862. * human perception of the size of each bubble.
  3863. *
  3864. * @validvalue ["area", "width"]
  3865. * @type {String}
  3866. * @sample {highcharts} highcharts/plotoptions/bubble-sizeby/
  3867. * Comparison of area and size
  3868. * @default area
  3869. * @since 3.0.7
  3870. * @apioption plotOptions.bubble.sizeBy
  3871. */
  3872. /**
  3873. * When this is true, the absolute value of z determines the size of
  3874. * the bubble. This means that with the default `zThreshold` of 0, a
  3875. * bubble of value -1 will have the same size as a bubble of value 1,
  3876. * while a bubble of value 0 will have a smaller size according to
  3877. * `minSize`.
  3878. *
  3879. * @type {Boolean}
  3880. * @sample {highcharts}
  3881. * highcharts/plotoptions/bubble-sizebyabsolutevalue/
  3882. * Size by absolute value, various thresholds
  3883. * @default false
  3884. * @since 4.1.9
  3885. * @product highcharts
  3886. * @apioption plotOptions.bubble.sizeByAbsoluteValue
  3887. */
  3888. /**
  3889. * When this is true, the series will not cause the Y axis to cross
  3890. * the zero plane (or [threshold](#plotOptions.series.threshold) option)
  3891. * unless the data actually crosses the plane.
  3892. *
  3893. * For example, if `softThreshold` is `false`, a series of 0, 1, 2,
  3894. * 3 will make the Y axis show negative values according to the `minPadding`
  3895. * option. If `softThreshold` is `true`, the Y axis starts at 0.
  3896. *
  3897. * @since 4.1.9
  3898. * @product highcharts
  3899. */
  3900. softThreshold: false,
  3901. states: {
  3902. hover: {
  3903. halo: {
  3904. size: 5
  3905. }
  3906. }
  3907. },
  3908. tooltip: {
  3909. pointFormat: '({point.x}, {point.y}), Size: {point.z}'
  3910. },
  3911. turboThreshold: 0,
  3912. /**
  3913. * The minimum for the Z value range. Defaults to the highest Z value
  3914. * in the data.
  3915. *
  3916. * @type {Number}
  3917. * @see [zMin](#plotOptions.bubble.zMin)
  3918. * @sample {highcharts} highcharts/plotoptions/bubble-zmin-zmax/
  3919. * Z has a possible range of 0-100
  3920. * @default null
  3921. * @since 4.0.3
  3922. * @product highcharts
  3923. * @apioption plotOptions.bubble.zMax
  3924. */
  3925. /**
  3926. * The minimum for the Z value range. Defaults to the lowest Z value
  3927. * in the data.
  3928. *
  3929. * @type {Number}
  3930. * @see [zMax](#plotOptions.bubble.zMax)
  3931. * @sample {highcharts} highcharts/plotoptions/bubble-zmin-zmax/
  3932. * Z has a possible range of 0-100
  3933. * @default null
  3934. * @since 4.0.3
  3935. * @product highcharts
  3936. * @apioption plotOptions.bubble.zMin
  3937. */
  3938. /**
  3939. * When [displayNegative](#plotOptions.bubble.displayNegative) is `false`,
  3940. * bubbles with lower Z values are skipped. When `displayNegative`
  3941. * is `true` and a [negativeColor](#plotOptions.bubble.negativeColor)
  3942. * is given, points with lower Z is colored.
  3943. *
  3944. * @type {Number}
  3945. * @sample {highcharts} highcharts/plotoptions/bubble-negative/
  3946. * Negative bubbles
  3947. * @default 0
  3948. * @since 3.0
  3949. * @product highcharts
  3950. */
  3951. zThreshold: 0,
  3952. zoneAxis: 'z'
  3953. // Prototype members
  3954. }, {
  3955. pointArrayMap: ['y', 'z'],
  3956. parallelArrays: ['x', 'y', 'z'],
  3957. trackerGroups: ['group', 'dataLabelsGroup'],
  3958. specialGroup: 'group', // To allow clipping (#6296)
  3959. bubblePadding: true,
  3960. zoneAxis: 'z',
  3961. directTouch: true,
  3962. pointAttribs: function (point, state) {
  3963. var markerOptions = this.options.marker,
  3964. fillOpacity = markerOptions.fillOpacity,
  3965. attr = Series.prototype.pointAttribs.call(this, point, state);
  3966. if (fillOpacity !== 1) {
  3967. attr.fill = color(attr.fill).setOpacity(fillOpacity).get('rgba');
  3968. }
  3969. return attr;
  3970. },
  3971. /**
  3972. * Get the radius for each point based on the minSize, maxSize and each
  3973. * point's Z value. This must be done prior to Series.translate because
  3974. * the axis needs to add padding in accordance with the point sizes.
  3975. */
  3976. getRadii: function (zMin, zMax, minSize, maxSize) {
  3977. var len,
  3978. i,
  3979. pos,
  3980. zData = this.zData,
  3981. radii = [],
  3982. options = this.options,
  3983. sizeByArea = options.sizeBy !== 'width',
  3984. zThreshold = options.zThreshold,
  3985. zRange = zMax - zMin,
  3986. value,
  3987. radius;
  3988. // Set the shape type and arguments to be picked up in drawPoints
  3989. for (i = 0, len = zData.length; i < len; i++) {
  3990. value = zData[i];
  3991. // When sizing by threshold, the absolute value of z determines
  3992. // the size of the bubble.
  3993. if (options.sizeByAbsoluteValue && value !== null) {
  3994. value = Math.abs(value - zThreshold);
  3995. zMax = zRange = Math.max(
  3996. zMax - zThreshold,
  3997. Math.abs(zMin - zThreshold)
  3998. );
  3999. zMin = 0;
  4000. }
  4001. if (value === null) {
  4002. radius = null;
  4003. // Issue #4419 - if value is less than zMin, push a radius that's
  4004. // always smaller than the minimum size
  4005. } else if (value < zMin) {
  4006. radius = minSize / 2 - 1;
  4007. } else {
  4008. // Relative size, a number between 0 and 1
  4009. pos = zRange > 0 ? (value - zMin) / zRange : 0.5;
  4010. if (sizeByArea && pos >= 0) {
  4011. pos = Math.sqrt(pos);
  4012. }
  4013. radius = Math.ceil(minSize + pos * (maxSize - minSize)) / 2;
  4014. }
  4015. radii.push(radius);
  4016. }
  4017. this.radii = radii;
  4018. },
  4019. /**
  4020. * Perform animation on the bubbles
  4021. */
  4022. animate: function (init) {
  4023. if (
  4024. !init &&
  4025. this.points.length < this.options.animationLimit // #8099
  4026. ) {
  4027. each(this.points, function (point) {
  4028. var graphic = point.graphic,
  4029. animationTarget;
  4030. if (graphic && graphic.width) { // URL symbols don't have width
  4031. animationTarget = {
  4032. x: graphic.x,
  4033. y: graphic.y,
  4034. width: graphic.width,
  4035. height: graphic.height
  4036. };
  4037. // Start values
  4038. graphic.attr({
  4039. x: point.plotX,
  4040. y: point.plotY,
  4041. width: 1,
  4042. height: 1
  4043. });
  4044. // Run animation
  4045. graphic.animate(animationTarget, this.options.animation);
  4046. }
  4047. }, this);
  4048. // delete this function to allow it only once
  4049. this.animate = null;
  4050. }
  4051. },
  4052. /**
  4053. * Extend the base translate method to handle bubble size
  4054. */
  4055. translate: function () {
  4056. var i,
  4057. data = this.data,
  4058. point,
  4059. radius,
  4060. radii = this.radii;
  4061. // Run the parent method
  4062. seriesTypes.scatter.prototype.translate.call(this);
  4063. // Set the shape type and arguments to be picked up in drawPoints
  4064. i = data.length;
  4065. while (i--) {
  4066. point = data[i];
  4067. radius = radii ? radii[i] : 0; // #1737
  4068. if (isNumber(radius) && radius >= this.minPxSize / 2) {
  4069. // Shape arguments
  4070. point.marker = H.extend(point.marker, {
  4071. radius: radius,
  4072. width: 2 * radius,
  4073. height: 2 * radius
  4074. });
  4075. // Alignment box for the data label
  4076. point.dlBox = {
  4077. x: point.plotX - radius,
  4078. y: point.plotY - radius,
  4079. width: 2 * radius,
  4080. height: 2 * radius
  4081. };
  4082. } else { // below zThreshold
  4083. // #1691
  4084. point.shapeArgs = point.plotY = point.dlBox = undefined;
  4085. }
  4086. }
  4087. },
  4088. alignDataLabel: seriesTypes.column.prototype.alignDataLabel,
  4089. buildKDTree: noop,
  4090. applyZones: noop
  4091. // Point class
  4092. }, {
  4093. haloPath: function (size) {
  4094. return Point.prototype.haloPath.call(
  4095. this,
  4096. // #6067
  4097. size === 0 ? 0 : (this.marker ? this.marker.radius || 0 : 0) + size
  4098. );
  4099. },
  4100. ttBelow: false
  4101. });
  4102. /**
  4103. * Add logic to pad each axis with the amount of pixels
  4104. * necessary to avoid the bubbles to overflow.
  4105. */
  4106. Axis.prototype.beforePadding = function () {
  4107. var axis = this,
  4108. axisLength = this.len,
  4109. chart = this.chart,
  4110. pxMin = 0,
  4111. pxMax = axisLength,
  4112. isXAxis = this.isXAxis,
  4113. dataKey = isXAxis ? 'xData' : 'yData',
  4114. min = this.min,
  4115. extremes = {},
  4116. smallestSize = Math.min(chart.plotWidth, chart.plotHeight),
  4117. zMin = Number.MAX_VALUE,
  4118. zMax = -Number.MAX_VALUE,
  4119. range = this.max - min,
  4120. transA = axisLength / range,
  4121. activeSeries = [];
  4122. // Handle padding on the second pass, or on redraw
  4123. each(this.series, function (series) {
  4124. var seriesOptions = series.options,
  4125. zData;
  4126. if (
  4127. series.bubblePadding &&
  4128. (series.visible || !chart.options.chart.ignoreHiddenSeries)
  4129. ) {
  4130. // Correction for #1673
  4131. axis.allowZoomOutside = true;
  4132. // Cache it
  4133. activeSeries.push(series);
  4134. if (isXAxis) { // because X axis is evaluated first
  4135. // For each series, translate the size extremes to pixel values
  4136. each(['minSize', 'maxSize'], function (prop) {
  4137. var length = seriesOptions[prop],
  4138. isPercent = /%$/.test(length);
  4139. length = pInt(length);
  4140. extremes[prop] = isPercent ?
  4141. smallestSize * length / 100 :
  4142. length;
  4143. });
  4144. series.minPxSize = extremes.minSize;
  4145. // Prioritize min size if conflict to make sure bubbles are
  4146. // always visible. #5873
  4147. series.maxPxSize = Math.max(extremes.maxSize, extremes.minSize);
  4148. // Find the min and max Z
  4149. zData = series.zData;
  4150. if (zData.length) { // #1735
  4151. zMin = pick(seriesOptions.zMin, Math.min(
  4152. zMin,
  4153. Math.max(
  4154. arrayMin(zData),
  4155. seriesOptions.displayNegative === false ?
  4156. seriesOptions.zThreshold :
  4157. -Number.MAX_VALUE
  4158. )
  4159. ));
  4160. zMax = pick(
  4161. seriesOptions.zMax,
  4162. Math.max(zMax, arrayMax(zData))
  4163. );
  4164. }
  4165. }
  4166. }
  4167. });
  4168. each(activeSeries, function (series) {
  4169. var data = series[dataKey],
  4170. i = data.length,
  4171. radius;
  4172. if (isXAxis) {
  4173. series.getRadii(zMin, zMax, series.minPxSize, series.maxPxSize);
  4174. }
  4175. if (range > 0) {
  4176. while (i--) {
  4177. if (
  4178. isNumber(data[i]) &&
  4179. axis.dataMin <= data[i] &&
  4180. data[i] <= axis.dataMax
  4181. ) {
  4182. radius = series.radii[i];
  4183. pxMin = Math.min(
  4184. ((data[i] - min) * transA) - radius,
  4185. pxMin
  4186. );
  4187. pxMax = Math.max(
  4188. ((data[i] - min) * transA) + radius,
  4189. pxMax
  4190. );
  4191. }
  4192. }
  4193. }
  4194. });
  4195. if (activeSeries.length && range > 0 && !this.isLog) {
  4196. pxMax -= axisLength;
  4197. transA *= (axisLength + pxMin - pxMax) / axisLength;
  4198. each(
  4199. [['min', 'userMin', pxMin], ['max', 'userMax', pxMax]],
  4200. function (keys) {
  4201. if (pick(axis.options[keys[0]], axis[keys[1]]) === undefined) {
  4202. axis[keys[0]] += keys[2] / transA;
  4203. }
  4204. }
  4205. );
  4206. }
  4207. };
  4208. /**
  4209. * A `bubble` series. If the [type](#series.bubble.type) option is
  4210. * not specified, it is inherited from [chart.type](#chart.type).
  4211. *
  4212. * @type {Object}
  4213. * @extends series,plotOptions.bubble
  4214. * @excluding dataParser,dataURL,stack
  4215. * @product highcharts highstock
  4216. * @apioption series.bubble
  4217. */
  4218. /**
  4219. * An array of data points for the series. For the `bubble` series type,
  4220. * points can be given in the following ways:
  4221. *
  4222. * 1. An array of arrays with 3 or 2 values. In this case, the values
  4223. * correspond to `x,y,z`. If the first value is a string, it is applied
  4224. * as the name of the point, and the `x` value is inferred. The `x`
  4225. * value can also be omitted, in which case the inner arrays should
  4226. * be of length 2\. Then the `x` value is automatically calculated,
  4227. * either starting at 0 and incremented by 1, or from `pointStart` and
  4228. * `pointInterval` given in the series options.
  4229. *
  4230. * ```js
  4231. * data: [
  4232. * [0, 1, 2],
  4233. * [1, 5, 5],
  4234. * [2, 0, 2]
  4235. * ]
  4236. * ```
  4237. *
  4238. * 2. An array of objects with named values. The objects are point
  4239. * configuration objects as seen below. If the total number of data
  4240. * points exceeds the series' [turboThreshold](#series.bubble.turboThreshold),
  4241. * this option is not available.
  4242. *
  4243. * ```js
  4244. * data: [{
  4245. * x: 1,
  4246. * y: 1,
  4247. * z: 1,
  4248. * name: "Point2",
  4249. * color: "#00FF00"
  4250. * }, {
  4251. * x: 1,
  4252. * y: 5,
  4253. * z: 4,
  4254. * name: "Point1",
  4255. * color: "#FF00FF"
  4256. * }]
  4257. * ```
  4258. *
  4259. * @type {Array<Object|Array>}
  4260. * @extends series.line.data
  4261. * @excluding marker
  4262. * @sample {highcharts} highcharts/chart/reflow-true/
  4263. * Numerical values
  4264. * @sample {highcharts} highcharts/series/data-array-of-arrays/
  4265. * Arrays of numeric x and y
  4266. * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
  4267. * Arrays of datetime x and y
  4268. * @sample {highcharts} highcharts/series/data-array-of-name-value/
  4269. * Arrays of point.name and y
  4270. * @sample {highcharts} highcharts/series/data-array-of-objects/
  4271. * Config objects
  4272. * @product highcharts
  4273. * @apioption series.bubble.data
  4274. */
  4275. /**
  4276. * The size value for each bubble. The bubbles' diameters are computed
  4277. * based on the `z`, and controlled by series options like `minSize`,
  4278. * `maxSize`, `sizeBy`, `zMin` and `zMax`.
  4279. *
  4280. * @type {Number}
  4281. * @product highcharts
  4282. * @apioption series.bubble.data.z
  4283. */
  4284. /**
  4285. * @excluding enabled,enabledThreshold,height,radius,width
  4286. * @apioption series.bubble.marker
  4287. */
  4288. }(Highcharts));
  4289. (function (H) {
  4290. /**
  4291. * (c) 2010-2017 Torstein Honsi
  4292. *
  4293. * License: www.highcharts.com/license
  4294. */
  4295. /**
  4296. * Extensions for polar charts. Additionally, much of the geometry required for
  4297. * polar charts is gathered in RadialAxes.js.
  4298. */
  4299. var each = H.each,
  4300. pick = H.pick,
  4301. Pointer = H.Pointer,
  4302. Series = H.Series,
  4303. seriesTypes = H.seriesTypes,
  4304. wrap = H.wrap,
  4305. seriesProto = Series.prototype,
  4306. pointerProto = Pointer.prototype,
  4307. colProto;
  4308. if (!H.polarExtended) {
  4309. H.polarExtended = true;
  4310. /**
  4311. * Search a k-d tree by the point angle, used for shared tooltips in polar
  4312. * charts
  4313. */
  4314. seriesProto.searchPointByAngle = function (e) {
  4315. var series = this,
  4316. chart = series.chart,
  4317. xAxis = series.xAxis,
  4318. center = xAxis.pane.center,
  4319. plotX = e.chartX - center[0] - chart.plotLeft,
  4320. plotY = e.chartY - center[1] - chart.plotTop;
  4321. return this.searchKDTree({
  4322. clientX: 180 + (Math.atan2(plotX, plotY) * (-180 / Math.PI))
  4323. });
  4324. };
  4325. /**
  4326. * #6212 Calculate connectors for spline series in polar chart.
  4327. * @param {Boolean} calculateNeighbours
  4328. * Check if connectors should be calculated for neighbour points as
  4329. * well allows short recurence
  4330. */
  4331. seriesProto.getConnectors = function (
  4332. segment,
  4333. index,
  4334. calculateNeighbours,
  4335. connectEnds
  4336. ) {
  4337. var i,
  4338. prevPointInd,
  4339. nextPointInd,
  4340. previousPoint,
  4341. nextPoint,
  4342. previousX,
  4343. previousY,
  4344. nextX,
  4345. nextY,
  4346. plotX,
  4347. plotY,
  4348. ret,
  4349. // 1 means control points midway between points, 2 means 1/3 from
  4350. // the point, 3 is 1/4 etc;
  4351. smoothing = 1.5,
  4352. denom = smoothing + 1,
  4353. leftContX,
  4354. leftContY,
  4355. rightContX,
  4356. rightContY,
  4357. dLControlPoint, // distance left control point
  4358. dRControlPoint,
  4359. leftContAngle,
  4360. rightContAngle,
  4361. jointAngle,
  4362. addedNumber = connectEnds ? 1 : 0;
  4363. // Calculate final index of points depending on the initial index value.
  4364. // Because of calculating neighbours, index may be outisde segment
  4365. // array.
  4366. if (index >= 0 && index <= segment.length - 1) {
  4367. i = index;
  4368. } else if (index < 0) {
  4369. i = segment.length - 1 + index;
  4370. } else {
  4371. i = 0;
  4372. }
  4373. prevPointInd = (i - 1 < 0) ? segment.length - (1 + addedNumber) : i - 1;
  4374. nextPointInd = (i + 1 > segment.length - 1) ? addedNumber : i + 1;
  4375. previousPoint = segment[prevPointInd];
  4376. nextPoint = segment[nextPointInd];
  4377. previousX = previousPoint.plotX;
  4378. previousY = previousPoint.plotY;
  4379. nextX = nextPoint.plotX;
  4380. nextY = nextPoint.plotY;
  4381. plotX = segment[i].plotX; // actual point
  4382. plotY = segment[i].plotY;
  4383. leftContX = (smoothing * plotX + previousX) / denom;
  4384. leftContY = (smoothing * plotY + previousY) / denom;
  4385. rightContX = (smoothing * plotX + nextX) / denom;
  4386. rightContY = (smoothing * plotY + nextY) / denom;
  4387. dLControlPoint = Math.sqrt(
  4388. Math.pow(leftContX - plotX, 2) + Math.pow(leftContY - plotY, 2)
  4389. );
  4390. dRControlPoint = Math.sqrt(
  4391. Math.pow(rightContX - plotX, 2) + Math.pow(rightContY - plotY, 2)
  4392. );
  4393. leftContAngle = Math.atan2(leftContY - plotY, leftContX - plotX);
  4394. rightContAngle = Math.atan2(rightContY - plotY, rightContX - plotX);
  4395. jointAngle = (Math.PI / 2) + ((leftContAngle + rightContAngle) / 2);
  4396. // Ensure the right direction, jointAngle should be in the same quadrant
  4397. // as leftContAngle
  4398. if (Math.abs(leftContAngle - jointAngle) > Math.PI / 2) {
  4399. jointAngle -= Math.PI;
  4400. }
  4401. // Find the corrected control points for a spline straight through the
  4402. // point
  4403. leftContX = plotX + Math.cos(jointAngle) * dLControlPoint;
  4404. leftContY = plotY + Math.sin(jointAngle) * dLControlPoint;
  4405. rightContX = plotX + Math.cos(Math.PI + jointAngle) * dRControlPoint;
  4406. rightContY = plotY + Math.sin(Math.PI + jointAngle) * dRControlPoint;
  4407. // push current point's connectors into returned object
  4408. ret = {
  4409. rightContX: rightContX,
  4410. rightContY: rightContY,
  4411. leftContX: leftContX,
  4412. leftContY: leftContY,
  4413. plotX: plotX,
  4414. plotY: plotY
  4415. };
  4416. // calculate connectors for previous and next point and push them inside
  4417. // returned object
  4418. if (calculateNeighbours) {
  4419. ret.prevPointCont = this.getConnectors(
  4420. segment,
  4421. prevPointInd,
  4422. false,
  4423. connectEnds
  4424. );
  4425. }
  4426. return ret;
  4427. };
  4428. /**
  4429. * Wrap the buildKDTree function so that it searches by angle (clientX) in
  4430. * case of shared tooltip, and by two dimensional distance in case of
  4431. * non-shared.
  4432. */
  4433. wrap(seriesProto, 'buildKDTree', function (proceed) {
  4434. if (this.chart.polar) {
  4435. if (this.kdByAngle) {
  4436. this.searchPoint = this.searchPointByAngle;
  4437. } else {
  4438. this.options.findNearestPointBy = 'xy';
  4439. }
  4440. }
  4441. proceed.apply(this);
  4442. });
  4443. /**
  4444. * Translate a point's plotX and plotY from the internal angle and radius
  4445. * measures to true plotX, plotY coordinates
  4446. */
  4447. seriesProto.toXY = function (point) {
  4448. var xy,
  4449. chart = this.chart,
  4450. plotX = point.plotX,
  4451. plotY = point.plotY,
  4452. clientX;
  4453. // Save rectangular plotX, plotY for later computation
  4454. point.rectPlotX = plotX;
  4455. point.rectPlotY = plotY;
  4456. // Find the polar plotX and plotY
  4457. xy = this.xAxis.postTranslate(point.plotX, this.yAxis.len - plotY);
  4458. point.plotX = point.polarPlotX = xy.x - chart.plotLeft;
  4459. point.plotY = point.polarPlotY = xy.y - chart.plotTop;
  4460. // If shared tooltip, record the angle in degrees in order to align X
  4461. // points. Otherwise, use a standard k-d tree to get the nearest point
  4462. // in two dimensions.
  4463. if (this.kdByAngle) {
  4464. clientX = (
  4465. (plotX / Math.PI * 180) + this.xAxis.pane.options.startAngle
  4466. ) % 360;
  4467. if (clientX < 0) { // #2665
  4468. clientX += 360;
  4469. }
  4470. point.clientX = clientX;
  4471. } else {
  4472. point.clientX = point.plotX;
  4473. }
  4474. };
  4475. if (seriesTypes.spline) {
  4476. /**
  4477. * Overridden method for calculating a spline from one point to the next
  4478. */
  4479. wrap(
  4480. seriesTypes.spline.prototype,
  4481. 'getPointSpline',
  4482. function (proceed, segment, point, i) {
  4483. var ret,
  4484. connectors;
  4485. if (this.chart.polar) {
  4486. // moveTo or lineTo
  4487. if (!i) {
  4488. ret = ['M', point.plotX, point.plotY];
  4489. } else { // curve from last point to this
  4490. connectors = this.getConnectors(
  4491. segment,
  4492. i,
  4493. true,
  4494. this.connectEnds
  4495. );
  4496. ret = [
  4497. 'C',
  4498. connectors.prevPointCont.rightContX,
  4499. connectors.prevPointCont.rightContY,
  4500. connectors.leftContX,
  4501. connectors.leftContY,
  4502. connectors.plotX,
  4503. connectors.plotY
  4504. ];
  4505. }
  4506. } else {
  4507. ret = proceed.call(this, segment, point, i);
  4508. }
  4509. return ret;
  4510. }
  4511. );
  4512. // #6430 Areasplinerange series use unwrapped getPointSpline method, so
  4513. // we need to set this method again.
  4514. if (seriesTypes.areasplinerange) {
  4515. seriesTypes.areasplinerange.prototype.getPointSpline =
  4516. seriesTypes.spline.prototype.getPointSpline;
  4517. }
  4518. }
  4519. /**
  4520. * Extend translate. The plotX and plotY values are computed as if the polar
  4521. * chart were a cartesian plane, where plotX denotes the angle in radians
  4522. * and (yAxis.len - plotY) is the pixel distance from center.
  4523. */
  4524. H.addEvent(Series, 'afterTranslate', function () {
  4525. var chart = this.chart,
  4526. points,
  4527. i;
  4528. if (chart.polar) {
  4529. // Postprocess plot coordinates
  4530. this.kdByAngle = chart.tooltip && chart.tooltip.shared;
  4531. if (!this.preventPostTranslate) {
  4532. points = this.points;
  4533. i = points.length;
  4534. while (i--) {
  4535. // Translate plotX, plotY from angle and radius to true plot
  4536. // coordinates
  4537. this.toXY(points[i]);
  4538. }
  4539. }
  4540. // Perform clip after render
  4541. if (!this.hasClipCircleSetter) {
  4542. this.hasClipCircleSetter = Boolean(
  4543. H.addEvent(this, 'afterRender', function () {
  4544. var circ;
  4545. if (chart.polar) {
  4546. circ = this.yAxis.center;
  4547. this.group.clip(
  4548. chart.renderer.clipCircle(
  4549. circ[0],
  4550. circ[1],
  4551. circ[2] / 2
  4552. )
  4553. );
  4554. this.setClip = H.noop;
  4555. }
  4556. })
  4557. );
  4558. }
  4559. }
  4560. });
  4561. /**
  4562. * Extend getSegmentPath to allow connecting ends across 0 to provide a
  4563. * closed circle in line-like series.
  4564. */
  4565. wrap(seriesProto, 'getGraphPath', function (proceed, points) {
  4566. var series = this,
  4567. i,
  4568. firstValid,
  4569. popLastPoint;
  4570. // Connect the path
  4571. if (this.chart.polar) {
  4572. points = points || this.points;
  4573. // Append first valid point in order to connect the ends
  4574. for (i = 0; i < points.length; i++) {
  4575. if (!points[i].isNull) {
  4576. firstValid = i;
  4577. break;
  4578. }
  4579. }
  4580. /**
  4581. * Polar charts only. Whether to connect the ends of a line series
  4582. * plot across the extremes.
  4583. *
  4584. * @type {Boolean}
  4585. * @sample {highcharts} highcharts/plotoptions/line-connectends-false/
  4586. * Do not connect
  4587. * @since 2.3.0
  4588. * @product highcharts
  4589. * @apioption plotOptions.series.connectEnds
  4590. */
  4591. if (
  4592. this.options.connectEnds !== false &&
  4593. firstValid !== undefined
  4594. ) {
  4595. this.connectEnds = true; // re-used in splines
  4596. points.splice(points.length, 0, points[firstValid]);
  4597. popLastPoint = true;
  4598. }
  4599. // For area charts, pseudo points are added to the graph, now we
  4600. // need to translate these
  4601. each(points, function (point) {
  4602. if (point.polarPlotY === undefined) {
  4603. series.toXY(point);
  4604. }
  4605. });
  4606. }
  4607. // Run uber method
  4608. var ret = proceed.apply(this, [].slice.call(arguments, 1));
  4609. // #6212 points.splice method is adding points to an array. In case of
  4610. // areaspline getGraphPath method is used two times and in both times
  4611. // points are added to an array. That is why points.pop is used, to get
  4612. // unmodified points.
  4613. if (popLastPoint) {
  4614. points.pop();
  4615. }
  4616. return ret;
  4617. });
  4618. var polarAnimate = function (proceed, init) {
  4619. var chart = this.chart,
  4620. animation = this.options.animation,
  4621. group = this.group,
  4622. markerGroup = this.markerGroup,
  4623. center = this.xAxis.center,
  4624. plotLeft = chart.plotLeft,
  4625. plotTop = chart.plotTop,
  4626. attribs;
  4627. // Specific animation for polar charts
  4628. if (chart.polar) {
  4629. // Enable animation on polar charts only in SVG. In VML, the scaling
  4630. // is different, plus animation would be so slow it would't matter.
  4631. if (chart.renderer.isSVG) {
  4632. if (animation === true) {
  4633. animation = {};
  4634. }
  4635. // Initialize the animation
  4636. if (init) {
  4637. // Scale down the group and place it in the center
  4638. attribs = {
  4639. translateX: center[0] + plotLeft,
  4640. translateY: center[1] + plotTop,
  4641. scaleX: 0.001, // #1499
  4642. scaleY: 0.001
  4643. };
  4644. group.attr(attribs);
  4645. if (markerGroup) {
  4646. markerGroup.attr(attribs);
  4647. }
  4648. // Run the animation
  4649. } else {
  4650. attribs = {
  4651. translateX: plotLeft,
  4652. translateY: plotTop,
  4653. scaleX: 1,
  4654. scaleY: 1
  4655. };
  4656. group.animate(attribs, animation);
  4657. if (markerGroup) {
  4658. markerGroup.animate(attribs, animation);
  4659. }
  4660. // Delete this function to allow it only once
  4661. this.animate = null;
  4662. }
  4663. }
  4664. // For non-polar charts, revert to the basic animation
  4665. } else {
  4666. proceed.call(this, init);
  4667. }
  4668. };
  4669. // Define the animate method for regular series
  4670. wrap(seriesProto, 'animate', polarAnimate);
  4671. if (seriesTypes.column) {
  4672. colProto = seriesTypes.column.prototype;
  4673. colProto.polarArc = function (low, high, start, end) {
  4674. var center = this.xAxis.center,
  4675. len = this.yAxis.len;
  4676. return this.chart.renderer.symbols.arc(
  4677. center[0],
  4678. center[1],
  4679. len - high,
  4680. null,
  4681. {
  4682. start: start,
  4683. end: end,
  4684. innerR: len - pick(low, len)
  4685. }
  4686. );
  4687. };
  4688. /**
  4689. * Define the animate method for columnseries
  4690. */
  4691. wrap(colProto, 'animate', polarAnimate);
  4692. /**
  4693. * Extend the column prototype's translate method
  4694. */
  4695. wrap(colProto, 'translate', function (proceed) {
  4696. var xAxis = this.xAxis,
  4697. startAngleRad = xAxis.startAngleRad,
  4698. start,
  4699. points,
  4700. point,
  4701. i;
  4702. this.preventPostTranslate = true;
  4703. // Run uber method
  4704. proceed.call(this);
  4705. // Postprocess plot coordinates
  4706. if (xAxis.isRadial) {
  4707. points = this.points;
  4708. i = points.length;
  4709. while (i--) {
  4710. point = points[i];
  4711. start = point.barX + startAngleRad;
  4712. point.shapeType = 'path';
  4713. point.shapeArgs = {
  4714. d: this.polarArc(
  4715. point.yBottom,
  4716. point.plotY,
  4717. start,
  4718. start + point.pointWidth
  4719. )
  4720. };
  4721. // Provide correct plotX, plotY for tooltip
  4722. this.toXY(point);
  4723. point.tooltipPos = [point.plotX, point.plotY];
  4724. point.ttBelow = point.plotY > xAxis.center[1];
  4725. }
  4726. }
  4727. });
  4728. /**
  4729. * Align column data labels outside the columns. #1199.
  4730. */
  4731. wrap(colProto, 'alignDataLabel', function (
  4732. proceed,
  4733. point,
  4734. dataLabel,
  4735. options,
  4736. alignTo,
  4737. isNew
  4738. ) {
  4739. if (this.chart.polar) {
  4740. var angle = point.rectPlotX / Math.PI * 180,
  4741. align,
  4742. verticalAlign;
  4743. // Align nicely outside the perimeter of the columns
  4744. if (options.align === null) {
  4745. if (angle > 20 && angle < 160) {
  4746. align = 'left'; // right hemisphere
  4747. } else if (angle > 200 && angle < 340) {
  4748. align = 'right'; // left hemisphere
  4749. } else {
  4750. align = 'center'; // top or bottom
  4751. }
  4752. options.align = align;
  4753. }
  4754. if (options.verticalAlign === null) {
  4755. if (angle < 45 || angle > 315) {
  4756. verticalAlign = 'bottom'; // top part
  4757. } else if (angle > 135 && angle < 225) {
  4758. verticalAlign = 'top'; // bottom part
  4759. } else {
  4760. verticalAlign = 'middle'; // left or right
  4761. }
  4762. options.verticalAlign = verticalAlign;
  4763. }
  4764. seriesProto.alignDataLabel.call(
  4765. this,
  4766. point,
  4767. dataLabel,
  4768. options,
  4769. alignTo,
  4770. isNew
  4771. );
  4772. } else {
  4773. proceed.call(this, point, dataLabel, options, alignTo, isNew);
  4774. }
  4775. });
  4776. }
  4777. /**
  4778. * Extend getCoordinates to prepare for polar axis values
  4779. */
  4780. wrap(pointerProto, 'getCoordinates', function (proceed, e) {
  4781. var chart = this.chart,
  4782. ret = {
  4783. xAxis: [],
  4784. yAxis: []
  4785. };
  4786. if (chart.polar) {
  4787. each(chart.axes, function (axis) {
  4788. var isXAxis = axis.isXAxis,
  4789. center = axis.center,
  4790. x = e.chartX - center[0] - chart.plotLeft,
  4791. y = e.chartY - center[1] - chart.plotTop;
  4792. ret[isXAxis ? 'xAxis' : 'yAxis'].push({
  4793. axis: axis,
  4794. value: axis.translate(
  4795. isXAxis ?
  4796. Math.PI - Math.atan2(x, y) : // angle
  4797. // distance from center
  4798. Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)),
  4799. true
  4800. )
  4801. });
  4802. });
  4803. } else {
  4804. ret = proceed.call(this, e);
  4805. }
  4806. return ret;
  4807. });
  4808. H.SVGRenderer.prototype.clipCircle = function (x, y, r) {
  4809. var wrapper,
  4810. id = H.uniqueKey(),
  4811. clipPath = this.createElement('clipPath').attr({
  4812. id: id
  4813. }).add(this.defs);
  4814. wrapper = this.circle(x, y, r).add(clipPath);
  4815. wrapper.id = id;
  4816. wrapper.clipPath = clipPath;
  4817. return wrapper;
  4818. };
  4819. H.addEvent(H.Chart, 'getAxes', function () {
  4820. if (!this.pane) {
  4821. this.pane = [];
  4822. }
  4823. each(H.splat(this.options.pane), function (paneOptions) {
  4824. new H.Pane( // eslint-disable-line no-new
  4825. paneOptions,
  4826. this
  4827. );
  4828. }, this);
  4829. });
  4830. H.addEvent(H.Chart, 'afterDrawChartBox', function () {
  4831. each(this.pane, function (pane) {
  4832. pane.render();
  4833. });
  4834. });
  4835. /**
  4836. * Extend chart.get to also search in panes. Used internally in
  4837. * responsiveness and chart.update.
  4838. */
  4839. wrap(H.Chart.prototype, 'get', function (proceed, id) {
  4840. return H.find(this.pane, function (pane) {
  4841. return pane.options.id === id;
  4842. }) || proceed.call(this, id);
  4843. });
  4844. }
  4845. }(Highcharts));
  4846. }));