annotations-advanced.src.js 303 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003
  1. /**
  2. * @license Highcharts JS v8.1.2 (2020-06-16)
  3. *
  4. * Annotations module
  5. *
  6. * (c) 2009-2019 Torstein Honsi
  7. *
  8. * License: www.highcharts.com/license
  9. */
  10. 'use strict';
  11. (function (factory) {
  12. if (typeof module === 'object' && module.exports) {
  13. factory['default'] = factory;
  14. module.exports = factory;
  15. } else if (typeof define === 'function' && define.amd) {
  16. define('highcharts/modules/annotations-advanced', ['highcharts'], function (Highcharts) {
  17. factory(Highcharts);
  18. factory.Highcharts = Highcharts;
  19. return factory;
  20. });
  21. } else {
  22. factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined);
  23. }
  24. }(function (Highcharts) {
  25. var _modules = Highcharts ? Highcharts._modules : {};
  26. function _registerModule(obj, path, args, fn) {
  27. if (!obj.hasOwnProperty(path)) {
  28. obj[path] = fn.apply(null, args);
  29. }
  30. }
  31. _registerModule(_modules, 'annotations/eventEmitterMixin.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) {
  32. /* *
  33. *
  34. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  35. *
  36. * */
  37. var addEvent = U.addEvent, fireEvent = U.fireEvent, inArray = U.inArray, objectEach = U.objectEach, pick = U.pick, removeEvent = U.removeEvent;
  38. /* eslint-disable valid-jsdoc */
  39. /**
  40. * It provides methods for:
  41. * - adding and handling DOM events and a drag event,
  42. * - mapping a mouse move event to the distance between two following events.
  43. * The units of the distance are specific to a transformation,
  44. * e.g. for rotation they are radians, for scaling they are scale factors.
  45. *
  46. * @private
  47. * @mixin
  48. * @memberOf Annotation
  49. */
  50. var eventEmitterMixin = {
  51. /**
  52. * Add emitter events.
  53. */
  54. addEvents: function () {
  55. var emitter = this, addMouseDownEvent = function (element) {
  56. addEvent(element, H.isTouchDevice ? 'touchstart' : 'mousedown', function (e) {
  57. emitter.onMouseDown(e);
  58. });
  59. };
  60. addMouseDownEvent(this.graphic.element);
  61. (emitter.labels || []).forEach(function (label) {
  62. if (label.options.useHTML && label.graphic.text) {
  63. // Mousedown event bound to HTML element (#13070).
  64. addMouseDownEvent(label.graphic.text.element);
  65. }
  66. });
  67. objectEach(emitter.options.events, function (event, type) {
  68. var eventHandler = function (e) {
  69. if (type !== 'click' || !emitter.cancelClick) {
  70. event.call(emitter, emitter.chart.pointer.normalize(e), emitter.target);
  71. }
  72. };
  73. if (inArray(type, emitter.nonDOMEvents || []) === -1) {
  74. emitter.graphic.on(type, eventHandler);
  75. }
  76. else {
  77. addEvent(emitter, type, eventHandler);
  78. }
  79. });
  80. if (emitter.options.draggable) {
  81. addEvent(emitter, H.isTouchDevice ? 'touchmove' : 'drag', emitter.onDrag);
  82. if (!emitter.graphic.renderer.styledMode) {
  83. var cssPointer_1 = {
  84. cursor: {
  85. x: 'ew-resize',
  86. y: 'ns-resize',
  87. xy: 'move'
  88. }[emitter.options.draggable]
  89. };
  90. emitter.graphic.css(cssPointer_1);
  91. (emitter.labels || []).forEach(function (label) {
  92. if (label.options.useHTML && label.graphic.text) {
  93. label.graphic.text.css(cssPointer_1);
  94. }
  95. });
  96. }
  97. }
  98. if (!emitter.isUpdating) {
  99. fireEvent(emitter, 'add');
  100. }
  101. },
  102. /**
  103. * Remove emitter document events.
  104. */
  105. removeDocEvents: function () {
  106. if (this.removeDrag) {
  107. this.removeDrag = this.removeDrag();
  108. }
  109. if (this.removeMouseUp) {
  110. this.removeMouseUp = this.removeMouseUp();
  111. }
  112. },
  113. /**
  114. * Mouse down handler.
  115. */
  116. onMouseDown: function (e) {
  117. var emitter = this, pointer = emitter.chart.pointer, prevChartX, prevChartY;
  118. if (e.preventDefault) {
  119. e.preventDefault();
  120. }
  121. // On right click, do nothing:
  122. if (e.button === 2) {
  123. return;
  124. }
  125. e = pointer.normalize(e);
  126. prevChartX = e.chartX;
  127. prevChartY = e.chartY;
  128. emitter.cancelClick = false;
  129. emitter.chart.hasDraggedAnnotation = true;
  130. emitter.removeDrag = addEvent(H.doc, H.isTouchDevice ? 'touchmove' : 'mousemove', function (e) {
  131. emitter.hasDragged = true;
  132. e = pointer.normalize(e);
  133. e.prevChartX = prevChartX;
  134. e.prevChartY = prevChartY;
  135. fireEvent(emitter, 'drag', e);
  136. prevChartX = e.chartX;
  137. prevChartY = e.chartY;
  138. });
  139. emitter.removeMouseUp = addEvent(H.doc, H.isTouchDevice ? 'touchend' : 'mouseup', function (e) {
  140. emitter.cancelClick = emitter.hasDragged;
  141. emitter.hasDragged = false;
  142. emitter.chart.hasDraggedAnnotation = false;
  143. // ControlPoints vs Annotation:
  144. fireEvent(pick(emitter.target, emitter), 'afterUpdate');
  145. emitter.onMouseUp(e);
  146. });
  147. },
  148. /**
  149. * Mouse up handler.
  150. */
  151. onMouseUp: function (_e) {
  152. var chart = this.chart, annotation = this.target || this, annotationsOptions = chart.options.annotations, index = chart.annotations.indexOf(annotation);
  153. this.removeDocEvents();
  154. annotationsOptions[index] = annotation.options;
  155. },
  156. /**
  157. * Drag and drop event. All basic annotations should share this
  158. * capability as well as the extended ones.
  159. */
  160. onDrag: function (e) {
  161. if (this.chart.isInsidePlot(e.chartX - this.chart.plotLeft, e.chartY - this.chart.plotTop)) {
  162. var translation = this.mouseMoveToTranslation(e);
  163. if (this.options.draggable === 'x') {
  164. translation.y = 0;
  165. }
  166. if (this.options.draggable === 'y') {
  167. translation.x = 0;
  168. }
  169. if (this.points.length) {
  170. this.translate(translation.x, translation.y);
  171. }
  172. else {
  173. this.shapes.forEach(function (shape) {
  174. shape.translate(translation.x, translation.y);
  175. });
  176. this.labels.forEach(function (label) {
  177. label.translate(translation.x, translation.y);
  178. });
  179. }
  180. this.redraw(false);
  181. }
  182. },
  183. /**
  184. * Map mouse move event to the radians.
  185. */
  186. mouseMoveToRadians: function (e, cx, cy) {
  187. var prevDy = e.prevChartY - cy, prevDx = e.prevChartX - cx, dy = e.chartY - cy, dx = e.chartX - cx, temp;
  188. if (this.chart.inverted) {
  189. temp = prevDx;
  190. prevDx = prevDy;
  191. prevDy = temp;
  192. temp = dx;
  193. dx = dy;
  194. dy = temp;
  195. }
  196. return Math.atan2(dy, dx) - Math.atan2(prevDy, prevDx);
  197. },
  198. /**
  199. * Map mouse move event to the distance between two following events.
  200. */
  201. mouseMoveToTranslation: function (e) {
  202. var dx = e.chartX - e.prevChartX, dy = e.chartY - e.prevChartY, temp;
  203. if (this.chart.inverted) {
  204. temp = dy;
  205. dy = dx;
  206. dx = temp;
  207. }
  208. return {
  209. x: dx,
  210. y: dy
  211. };
  212. },
  213. /**
  214. * Map mouse move to the scale factors.
  215. *
  216. * @param {Object} e event
  217. * @param {number} cx center x
  218. * @param {number} cy center y
  219. **/
  220. mouseMoveToScale: function (e, cx, cy) {
  221. var prevDx = e.prevChartX - cx, prevDy = e.prevChartY - cy, dx = e.chartX - cx, dy = e.chartY - cy, sx = (dx || 1) / (prevDx || 1), sy = (dy || 1) / (prevDy || 1), temp;
  222. if (this.chart.inverted) {
  223. temp = sy;
  224. sy = sx;
  225. sx = temp;
  226. }
  227. return {
  228. x: sx,
  229. y: sy
  230. };
  231. },
  232. /**
  233. * Destroy the event emitter.
  234. */
  235. destroy: function () {
  236. this.removeDocEvents();
  237. removeEvent(this);
  238. this.hcEvents = null;
  239. }
  240. };
  241. return eventEmitterMixin;
  242. });
  243. _registerModule(_modules, 'annotations/ControlPoint.js', [_modules['parts/Utilities.js'], _modules['annotations/eventEmitterMixin.js']], function (U, eventEmitterMixin) {
  244. /* *
  245. *
  246. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  247. *
  248. * */
  249. /**
  250. * Callback to modify annotation's possitioner controls.
  251. *
  252. * @callback Highcharts.AnnotationControlPointPositionerFunction
  253. * @param {Highcharts.AnnotationControlPoint} this
  254. * @param {Highcharts.AnnotationControllable} target
  255. * @return {Highcharts.PositionObject}
  256. */
  257. var extend = U.extend, merge = U.merge, pick = U.pick;
  258. /* eslint-disable no-invalid-this, valid-jsdoc */
  259. /**
  260. * A control point class which is a connection between controllable
  261. * transform methods and a user actions.
  262. *
  263. * @requires modules/annotations
  264. *
  265. * @class
  266. * @name Highcharts.AnnotationControlPoint
  267. *
  268. * @hideconstructor
  269. *
  270. * @param {Highcharts.Chart} chart
  271. * A chart instance.
  272. *
  273. * @param {Highcharts.AnnotationControllable} target
  274. * A controllable instance which is a target for a control point.
  275. *
  276. * @param {Highcharts.AnnotationControlPointOptionsObject} options
  277. * An options object.
  278. *
  279. * @param {number} [index]
  280. * Point index.
  281. */
  282. var ControlPoint = /** @class */ (function () {
  283. function ControlPoint(chart, target, options, index) {
  284. /**
  285. *
  286. * Properties
  287. *
  288. */
  289. this.addEvents = eventEmitterMixin.addEvents;
  290. this.graphic = void 0;
  291. this.mouseMoveToRadians = eventEmitterMixin.mouseMoveToRadians;
  292. this.mouseMoveToScale = eventEmitterMixin.mouseMoveToScale;
  293. this.mouseMoveToTranslation = eventEmitterMixin.mouseMoveToTranslation;
  294. this.onDrag = eventEmitterMixin.onDrag;
  295. this.onMouseDown = eventEmitterMixin.onMouseDown;
  296. this.onMouseUp = eventEmitterMixin.onMouseUp;
  297. this.removeDocEvents = eventEmitterMixin.removeDocEvents;
  298. /**
  299. *
  300. * Functions
  301. *
  302. */
  303. /**
  304. * List of events for `anntation.options.events` that should not be
  305. * added to `annotation.graphic` but to the `annotation`.
  306. * @private
  307. * @name Highcharts.AnnotationControlPoint#nonDOMEvents
  308. * @type {Array<string>}
  309. */
  310. this.nonDOMEvents = ['drag'];
  311. this.chart = chart;
  312. this.target = target;
  313. this.options = options;
  314. this.index = pick(options.index, index);
  315. }
  316. /**
  317. * Set the visibility of the control point.
  318. *
  319. * @function Highcharts.AnnotationControlPoint#setVisibility
  320. *
  321. * @param {boolean} visible
  322. * Visibility of the control point.
  323. *
  324. * @return {void}
  325. */
  326. ControlPoint.prototype.setVisibility = function (visible) {
  327. this.graphic.attr('visibility', visible ? 'visible' : 'hidden');
  328. this.options.visible = visible;
  329. };
  330. /**
  331. * Render the control point.
  332. * @private
  333. */
  334. ControlPoint.prototype.render = function () {
  335. var chart = this.chart, options = this.options;
  336. this.graphic = chart.renderer
  337. .symbol(options.symbol, 0, 0, options.width, options.height)
  338. .add(chart.controlPointsGroup)
  339. .css(options.style);
  340. this.setVisibility(options.visible);
  341. // npm test -- --tests "highcharts/annotations-advanced/*"
  342. this.addEvents();
  343. };
  344. /**
  345. * Redraw the control point.
  346. * @private
  347. * @param {boolean} [animation]
  348. */
  349. ControlPoint.prototype.redraw = function (animation) {
  350. this.graphic[animation ? 'animate' : 'attr'](this.options.positioner.call(this, this.target));
  351. };
  352. /**
  353. * Destroy the control point.
  354. * @private
  355. */
  356. ControlPoint.prototype.destroy = function () {
  357. eventEmitterMixin.destroy.call(this);
  358. if (this.graphic) {
  359. this.graphic = this.graphic.destroy();
  360. }
  361. this.chart = null;
  362. this.target = null;
  363. this.options = null;
  364. };
  365. /**
  366. * Update the control point.
  367. *
  368. * @function Highcharts.AnnotationControlPoint#update
  369. *
  370. * @param {Partial<Highcharts.AnnotationControlPointOptionsObject>} userOptions
  371. * New options for the control point.
  372. *
  373. * @return {void}
  374. */
  375. ControlPoint.prototype.update = function (userOptions) {
  376. var chart = this.chart, target = this.target, index = this.index, options = merge(true, this.options, userOptions);
  377. this.destroy();
  378. this.constructor(chart, target, options, index);
  379. this.render(chart.controlPointsGroup);
  380. this.redraw();
  381. };
  382. return ControlPoint;
  383. }());
  384. return ControlPoint;
  385. });
  386. _registerModule(_modules, 'annotations/MockPoint.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) {
  387. /* *
  388. *
  389. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  390. *
  391. * */
  392. /**
  393. * @private
  394. * @interface Highcharts.AnnotationMockLabelOptionsObject
  395. */ /**
  396. * Point instance of the point.
  397. * @name Highcharts.AnnotationMockLabelOptionsObject#point
  398. * @type {Highcharts.AnnotationMockPoint}
  399. */ /**
  400. * X value translated to x axis scale.
  401. * @name Highcharts.AnnotationMockLabelOptionsObject#x
  402. * @type {number|null}
  403. */ /**
  404. * Y value translated to y axis scale.
  405. * @name Highcharts.AnnotationMockLabelOptionsObject#y
  406. * @type {number|null}
  407. */
  408. /**
  409. * A mock series instance imitating a real series from a real point.
  410. * @private
  411. * @interface Highcharts.AnnotationMockSeries
  412. */ /**
  413. * Whether a series is visible.
  414. * @name Highcharts.AnnotationMockSeries#visible
  415. * @type {boolean}
  416. */ /**
  417. * A chart instance.
  418. * @name Highcharts.AnnotationMockSeries#chart
  419. * @type {Highcharts.Chart}
  420. */ /**
  421. * @name Highcharts.AnnotationMockSeries#getPlotBox
  422. * @type {Function}
  423. */
  424. /**
  425. * Indicates if this is a mock point for an annotation.
  426. * @name Highcharts.Point#mock
  427. * @type {boolean|undefined}
  428. */
  429. var defined = U.defined, extend = U.extend, fireEvent = U.fireEvent;
  430. /* eslint-disable no-invalid-this, valid-jsdoc */
  431. /**
  432. * A trimmed point object which imitates {@link Highchart.Point} class. It is
  433. * created when there is a need of pointing to some chart's position using axis
  434. * values or pixel values
  435. *
  436. * @requires modules/annotations
  437. *
  438. * @private
  439. * @class
  440. * @name Highcharts.AnnotationMockPoint
  441. *
  442. * @hideconstructor
  443. *
  444. * @param {Highcharts.Chart} chart
  445. * The chart instance.
  446. *
  447. * @param {Highcharts.AnnotationControllable|null} target
  448. * The related controllable.
  449. *
  450. * @param {Highcharts.AnnotationMockPointOptionsObject|Function} options
  451. * The options object.
  452. */
  453. var MockPoint = /** @class */ (function () {
  454. function MockPoint(chart, target, options) {
  455. this.isInside = void 0;
  456. this.plotX = void 0;
  457. this.plotY = void 0;
  458. this.x = void 0;
  459. this.y = void 0;
  460. /* *
  461. *
  462. * Functions
  463. *
  464. * */
  465. /**
  466. * A flag indicating that a point is not the real one.
  467. *
  468. * @type {boolean}
  469. * @default true
  470. */
  471. this.mock = true;
  472. /**
  473. * A mock series instance imitating a real series from a real point.
  474. *
  475. * @name Annotation.AnnotationMockPoint#series
  476. * @type {Highcharts.AnnotationMockSeries}
  477. */
  478. this.series = {
  479. visible: true,
  480. chart: chart,
  481. getPlotBox: H.Series.prototype.getPlotBox
  482. };
  483. /**
  484. * @name Annotation.AnnotationMockPoint#target
  485. * @type {Highcharts.AnnotationControllable|null}
  486. */
  487. this.target = target || null;
  488. /**
  489. * Options for the mock point.
  490. *
  491. * @name Annotation.AnnotationMockPoint#options
  492. * @type {Highcharts.AnnotationsMockPointOptionsObject}
  493. */
  494. this.options = options;
  495. /**
  496. * If an xAxis is set it represents the point's value in terms of the
  497. * xAxis.
  498. *
  499. * @name Annotation.AnnotationMockPoint#x
  500. * @type {number|undefined}
  501. */
  502. /**
  503. * If an yAxis is set it represents the point's value in terms of the
  504. * yAxis.
  505. *
  506. * @name Annotation.AnnotationMockPoint#y
  507. * @type {number|undefined}
  508. */
  509. /**
  510. * It represents the point's pixel x coordinate relative to its plot
  511. * box.
  512. *
  513. * @name Annotation.AnnotationMockPoint#plotX
  514. * @type {number|undefined}
  515. */
  516. /**
  517. * It represents the point's pixel y position relative to its plot box.
  518. *
  519. * @name Annotation.AnnotationMockPoint#plotY
  520. * @type {number|undefined}
  521. */
  522. /**
  523. * Whether the point is inside the plot box.
  524. *
  525. * @name Annotation.AnnotationMockPoint#isInside
  526. * @type {boolean|undefined}
  527. */
  528. this.applyOptions(this.getOptions());
  529. }
  530. /**
  531. * Create a mock point from a real Highcharts point.
  532. *
  533. * @private
  534. * @static
  535. *
  536. * @param {Highcharts.Point} point
  537. *
  538. * @return {Highcharts.AnnotationMockPoint}
  539. * A mock point instance.
  540. */
  541. MockPoint.fromPoint = function (point) {
  542. return new MockPoint(point.series.chart, null, {
  543. x: point.x,
  544. y: point.y,
  545. xAxis: point.series.xAxis,
  546. yAxis: point.series.yAxis
  547. });
  548. };
  549. /**
  550. * Get the pixel position from the point like object.
  551. *
  552. * @private
  553. * @static
  554. *
  555. * @param {Highcharts.AnnotationPointType} point
  556. *
  557. * @param {boolean} [paneCoordinates]
  558. * whether the pixel position should be relative
  559. *
  560. * @return {Highcharts.PositionObject} pixel position
  561. */
  562. MockPoint.pointToPixels = function (point, paneCoordinates) {
  563. var series = point.series, chart = series.chart, x = point.plotX, y = point.plotY, plotBox;
  564. if (chart.inverted) {
  565. if (point.mock) {
  566. x = point.plotY;
  567. y = point.plotX;
  568. }
  569. else {
  570. x = chart.plotWidth - point.plotY;
  571. y = chart.plotHeight - point.plotX;
  572. }
  573. }
  574. if (series && !paneCoordinates) {
  575. plotBox = series.getPlotBox();
  576. x += plotBox.translateX;
  577. y += plotBox.translateY;
  578. }
  579. return {
  580. x: x,
  581. y: y
  582. };
  583. };
  584. /**
  585. * Get fresh mock point options from the point like object.
  586. *
  587. * @private
  588. * @static
  589. *
  590. * @param {Highcharts.AnnotationPointType} point
  591. *
  592. * @return {Highcharts.AnnotationMockPointOptionsObject}
  593. * A mock point's options.
  594. */
  595. MockPoint.pointToOptions = function (point) {
  596. return {
  597. x: point.x,
  598. y: point.y,
  599. xAxis: point.series.xAxis,
  600. yAxis: point.series.yAxis
  601. };
  602. };
  603. /**
  604. * Check if the point has dynamic options.
  605. * @private
  606. * @return {boolean}
  607. * A positive flag if the point has dynamic options.
  608. */
  609. MockPoint.prototype.hasDynamicOptions = function () {
  610. return typeof this.options === 'function';
  611. };
  612. /**
  613. * Get the point's options.
  614. * @private
  615. * @return {Highcharts.AnnotationMockPointOptionsObject}
  616. * The mock point's options.
  617. */
  618. MockPoint.prototype.getOptions = function () {
  619. return this.hasDynamicOptions() ?
  620. this.options(this.target) :
  621. this.options;
  622. };
  623. /**
  624. * Apply options for the point.
  625. * @private
  626. * @param {Highcharts.AnnotationMockPointOptionsObject} options
  627. */
  628. MockPoint.prototype.applyOptions = function (options) {
  629. this.command = options.command;
  630. this.setAxis(options, 'x');
  631. this.setAxis(options, 'y');
  632. this.refresh();
  633. };
  634. /**
  635. * Set x or y axis.
  636. * @private
  637. * @param {Highcharts.AnnotationMockPointOptionsObject} options
  638. * @param {string} xOrY
  639. * 'x' or 'y' string literal
  640. */
  641. MockPoint.prototype.setAxis = function (options, xOrY) {
  642. var axisName = (xOrY + 'Axis'), axisOptions = options[axisName], chart = this.series.chart;
  643. this.series[axisName] =
  644. axisOptions instanceof H.Axis ?
  645. axisOptions :
  646. defined(axisOptions) ?
  647. (chart[axisName][axisOptions] ||
  648. chart.get(axisOptions)) :
  649. null;
  650. };
  651. /**
  652. * Transform the mock point to an anchor (relative position on the chart).
  653. * @private
  654. * @return {Array<number>}
  655. * A quadruple of numbers which denotes x, y, width and height of the box
  656. **/
  657. MockPoint.prototype.toAnchor = function () {
  658. var anchor = [this.plotX, this.plotY, 0, 0];
  659. if (this.series.chart.inverted) {
  660. anchor[0] = this.plotY;
  661. anchor[1] = this.plotX;
  662. }
  663. return anchor;
  664. };
  665. /**
  666. * Returns a label config object - the same as
  667. * Highcharts.Point.prototype.getLabelConfig
  668. * @private
  669. * @return {Highcharts.AnnotationMockLabelOptionsObject} the point's label config
  670. */
  671. MockPoint.prototype.getLabelConfig = function () {
  672. return {
  673. x: this.x,
  674. y: this.y,
  675. point: this
  676. };
  677. };
  678. /**
  679. * Check if the point is inside its pane.
  680. * @private
  681. * @return {boolean} A flag indicating whether the point is inside the pane.
  682. */
  683. MockPoint.prototype.isInsidePlot = function () {
  684. var plotX = this.plotX, plotY = this.plotY, xAxis = this.series.xAxis, yAxis = this.series.yAxis, e = {
  685. x: plotX,
  686. y: plotY,
  687. isInsidePlot: true
  688. };
  689. if (xAxis) {
  690. e.isInsidePlot = defined(plotX) && plotX >= 0 && plotX <= xAxis.len;
  691. }
  692. if (yAxis) {
  693. e.isInsidePlot =
  694. e.isInsidePlot &&
  695. defined(plotY) &&
  696. plotY >= 0 && plotY <= yAxis.len;
  697. }
  698. fireEvent(this.series.chart, 'afterIsInsidePlot', e);
  699. return e.isInsidePlot;
  700. };
  701. /**
  702. * Refresh point values and coordinates based on its options.
  703. * @private
  704. */
  705. MockPoint.prototype.refresh = function () {
  706. var series = this.series, xAxis = series.xAxis, yAxis = series.yAxis, options = this.getOptions();
  707. if (xAxis) {
  708. this.x = options.x;
  709. this.plotX = xAxis.toPixels(options.x, true);
  710. }
  711. else {
  712. this.x = null;
  713. this.plotX = options.x;
  714. }
  715. if (yAxis) {
  716. this.y = options.y;
  717. this.plotY = yAxis.toPixels(options.y, true);
  718. }
  719. else {
  720. this.y = null;
  721. this.plotY = options.y;
  722. }
  723. this.isInside = this.isInsidePlot();
  724. };
  725. /**
  726. * Translate the point.
  727. *
  728. * @private
  729. *
  730. * @param {number|undefined} cx
  731. * Origin x transformation.
  732. *
  733. * @param {number|undefined} cy
  734. * Origin y transformation.
  735. *
  736. * @param {number} dx
  737. * Translation for x coordinate.
  738. *
  739. * @param {number} dy
  740. * Translation for y coordinate.
  741. **/
  742. MockPoint.prototype.translate = function (_cx, _cy, dx, dy) {
  743. if (!this.hasDynamicOptions()) {
  744. this.plotX += dx;
  745. this.plotY += dy;
  746. this.refreshOptions();
  747. }
  748. };
  749. /**
  750. * Scale the point.
  751. *
  752. * @private
  753. *
  754. * @param {number} cx
  755. * Origin x transformation.
  756. *
  757. * @param {number} cy
  758. * Origin y transformation.
  759. *
  760. * @param {number} sx
  761. * Scale factor x.
  762. *
  763. * @param {number} sy
  764. * Scale factor y.
  765. */
  766. MockPoint.prototype.scale = function (cx, cy, sx, sy) {
  767. if (!this.hasDynamicOptions()) {
  768. var x = this.plotX * sx, y = this.plotY * sy, tx = (1 - sx) * cx, ty = (1 - sy) * cy;
  769. this.plotX = tx + x;
  770. this.plotY = ty + y;
  771. this.refreshOptions();
  772. }
  773. };
  774. /**
  775. * Rotate the point.
  776. * @private
  777. * @param {number} cx origin x rotation
  778. * @param {number} cy origin y rotation
  779. * @param {number} radians
  780. */
  781. MockPoint.prototype.rotate = function (cx, cy, radians) {
  782. if (!this.hasDynamicOptions()) {
  783. var cos = Math.cos(radians), sin = Math.sin(radians), x = this.plotX, y = this.plotY, tx, ty;
  784. x -= cx;
  785. y -= cy;
  786. tx = x * cos - y * sin;
  787. ty = x * sin + y * cos;
  788. this.plotX = tx + cx;
  789. this.plotY = ty + cy;
  790. this.refreshOptions();
  791. }
  792. };
  793. /**
  794. * Refresh point options based on its plot coordinates.
  795. * @private
  796. */
  797. MockPoint.prototype.refreshOptions = function () {
  798. var series = this.series, xAxis = series.xAxis, yAxis = series.yAxis;
  799. this.x = this.options.x = xAxis ?
  800. this.options.x = xAxis.toValue(this.plotX, true) :
  801. this.plotX;
  802. this.y = this.options.y = yAxis ?
  803. yAxis.toValue(this.plotY, true) :
  804. this.plotY;
  805. };
  806. return MockPoint;
  807. }());
  808. return MockPoint;
  809. });
  810. _registerModule(_modules, 'annotations/controllable/controllableMixin.js', [_modules['annotations/ControlPoint.js'], _modules['annotations/MockPoint.js'], _modules['parts/Tooltip.js'], _modules['parts/Utilities.js']], function (ControlPoint, MockPoint, Tooltip, U) {
  811. /* *
  812. *
  813. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  814. *
  815. * */
  816. var isObject = U.isObject, isString = U.isString, merge = U.merge, splat = U.splat;
  817. /**
  818. * An object which denots a controllable's anchor positions - relative and
  819. * absolute.
  820. *
  821. * @private
  822. * @interface Highcharts.AnnotationAnchorObject
  823. */ /**
  824. * Relative to the plot area position
  825. * @name Highcharts.AnnotationAnchorObject#relativePosition
  826. * @type {Highcharts.BBoxObject}
  827. */ /**
  828. * Absolute position
  829. * @name Highcharts.AnnotationAnchorObject#absolutePosition
  830. * @type {Highcharts.BBoxObject}
  831. */
  832. /**
  833. * @interface Highcharts.AnnotationControllable
  834. */ /**
  835. * @name Highcharts.AnnotationControllable#annotation
  836. * @type {Highcharts.Annotation}
  837. */ /**
  838. * @name Highcharts.AnnotationControllable#chart
  839. * @type {Highcharts.Chart}
  840. */ /**
  841. * @name Highcharts.AnnotationControllable#collection
  842. * @type {string}
  843. */ /**
  844. * @private
  845. * @name Highcharts.AnnotationControllable#controlPoints
  846. * @type {Array<Highcharts.AnnotationControlPoint>}
  847. */ /**
  848. * @name Highcharts.AnnotationControllable#points
  849. * @type {Array<Highcharts.Point>}
  850. */
  851. /* eslint-disable no-invalid-this, valid-jsdoc */
  852. /**
  853. * It provides methods for handling points, control points
  854. * and points transformations.
  855. *
  856. * @private
  857. * @mixin
  858. * @name Highcharts.AnnotationControllableMixin
  859. */
  860. var controllableMixin = {
  861. /**
  862. * Init the controllable
  863. */
  864. init: function (annotation, options, index) {
  865. this.annotation = annotation;
  866. this.chart = annotation.chart;
  867. this.options = options;
  868. this.points = [];
  869. this.controlPoints = [];
  870. this.index = index;
  871. this.linkPoints();
  872. this.addControlPoints();
  873. },
  874. /**
  875. * Redirect attr usage on the controllable graphic element.
  876. */
  877. attr: function () {
  878. this.graphic.attr.apply(this.graphic, arguments);
  879. },
  880. /**
  881. * Get the controllable's points options.
  882. *
  883. * @return {Array<Highcharts.PointOptionsObject>}
  884. * An array of points' options.
  885. */
  886. getPointsOptions: function () {
  887. var options = this.options;
  888. return (options.points || (options.point && splat(options.point)));
  889. },
  890. /**
  891. * Utility function for mapping item's options
  892. * to element's attribute
  893. *
  894. * @param {Highcharts.AnnotationsLabelsOptions|Highcharts.AnnotationsShapesOptions} options
  895. *
  896. * @return {Highcharts.SVGAttributes}
  897. * Mapped options.
  898. */
  899. attrsFromOptions: function (options) {
  900. var map = this.constructor.attrsMap, attrs = {}, key, mappedKey, styledMode = this.chart.styledMode;
  901. for (key in options) { // eslint-disable-line guard-for-in
  902. mappedKey = map[key];
  903. if (mappedKey &&
  904. (!styledMode ||
  905. ['fill', 'stroke', 'stroke-width']
  906. .indexOf(mappedKey) === -1)) {
  907. attrs[mappedKey] = options[key];
  908. }
  909. }
  910. return attrs;
  911. },
  912. /**
  913. * Returns object which denotes anchor position - relative and absolute.
  914. *
  915. * @param {Highcharts.AnnotationPointType} point
  916. * A point like object.
  917. *
  918. * @return {Highcharts.AnnotationAnchorObject} a controllable anchor
  919. */
  920. anchor: function (point) {
  921. var plotBox = point.series.getPlotBox(), box = point.mock ?
  922. point.toAnchor() :
  923. Tooltip.prototype.getAnchor.call({
  924. chart: point.series.chart
  925. }, point), anchor = {
  926. x: box[0] + (this.options.x || 0),
  927. y: box[1] + (this.options.y || 0),
  928. height: box[2] || 0,
  929. width: box[3] || 0
  930. };
  931. return {
  932. relativePosition: anchor,
  933. absolutePosition: merge(anchor, {
  934. x: anchor.x + plotBox.translateX,
  935. y: anchor.y + plotBox.translateY
  936. })
  937. };
  938. },
  939. /**
  940. * Map point's options to a point-like object.
  941. *
  942. * @param {string|Function|Highcharts.AnnotationMockPointOptionsObject|Highcharts.AnnotationPointType} pointOptions
  943. * Point's options.
  944. *
  945. * @param {Highcharts.AnnotationPointType} point
  946. * A point-like instance.
  947. *
  948. * @return {Highcharts.AnnotationPointType|null}
  949. * if the point is found/set returns this point, otherwise null
  950. */
  951. point: function (pointOptions, point) {
  952. if (pointOptions && pointOptions.series) {
  953. return pointOptions;
  954. }
  955. if (!point || point.series === null) {
  956. if (isObject(pointOptions)) {
  957. point = new MockPoint(this.chart, this, pointOptions);
  958. }
  959. else if (isString(pointOptions)) {
  960. point = this.chart.get(pointOptions) || null;
  961. }
  962. else if (typeof pointOptions === 'function') {
  963. var pointConfig = pointOptions.call(point, this);
  964. point = pointConfig.series ?
  965. pointConfig :
  966. new MockPoint(this.chart, this, pointOptions);
  967. }
  968. }
  969. return point;
  970. },
  971. /**
  972. * Find point-like objects based on points options.
  973. *
  974. * @return {Array<Annotation.PointLike>} an array of point-like objects
  975. */
  976. linkPoints: function () {
  977. var pointsOptions = this.getPointsOptions(), points = this.points, len = (pointsOptions && pointsOptions.length) || 0, i, point;
  978. for (i = 0; i < len; i++) {
  979. point = this.point(pointsOptions[i], points[i]);
  980. if (!point) {
  981. points.length = 0;
  982. return;
  983. }
  984. if (point.mock) {
  985. point.refresh();
  986. }
  987. points[i] = point;
  988. }
  989. return points;
  990. },
  991. /**
  992. * Add control points to a controllable.
  993. */
  994. addControlPoints: function () {
  995. var controlPointsOptions = this.options.controlPoints;
  996. (controlPointsOptions || []).forEach(function (controlPointOptions, i) {
  997. var options = merge(this.options.controlPointOptions, controlPointOptions);
  998. if (!options.index) {
  999. options.index = i;
  1000. }
  1001. controlPointsOptions[i] = options;
  1002. this.controlPoints.push(new ControlPoint(this.chart, this, options));
  1003. }, this);
  1004. },
  1005. /**
  1006. * Check if a controllable should be rendered/redrawn.
  1007. *
  1008. * @return {boolean}
  1009. * Whether a controllable should be drawn.
  1010. */
  1011. shouldBeDrawn: function () {
  1012. return Boolean(this.points.length);
  1013. },
  1014. /**
  1015. * Render a controllable.
  1016. */
  1017. render: function (_parentGroup) {
  1018. this.controlPoints.forEach(function (controlPoint) {
  1019. controlPoint.render();
  1020. });
  1021. },
  1022. /**
  1023. * Redraw a controllable.
  1024. *
  1025. * @param {boolean} [animation]
  1026. */
  1027. redraw: function (animation) {
  1028. this.controlPoints.forEach(function (controlPoint) {
  1029. controlPoint.redraw(animation);
  1030. });
  1031. },
  1032. /**
  1033. * Transform a controllable with a specific transformation.
  1034. *
  1035. * @param {string} transformation a transformation name
  1036. * @param {number|null} cx origin x transformation
  1037. * @param {number|null} cy origin y transformation
  1038. * @param {number} p1 param for the transformation
  1039. * @param {number} [p2] param for the transformation
  1040. */
  1041. transform: function (transformation, cx, cy, p1, p2) {
  1042. if (this.chart.inverted) {
  1043. var temp = cx;
  1044. cx = cy;
  1045. cy = temp;
  1046. }
  1047. this.points.forEach(function (point, i) {
  1048. this.transformPoint(transformation, cx, cy, p1, p2, i);
  1049. }, this);
  1050. },
  1051. /**
  1052. * Transform a point with a specific transformation
  1053. * If a transformed point is a real point it is replaced with
  1054. * the mock point.
  1055. *
  1056. * @param {string} transformation a transformation name
  1057. * @param {number|null} cx origin x transformation
  1058. * @param {number|null} cy origin y transformation
  1059. * @param {number} p1 param for the transformation
  1060. * @param {number|undefined} p2 param for the transformation
  1061. * @param {number} i index of the point
  1062. */
  1063. transformPoint: function (transformation, cx, cy, p1, p2, i) {
  1064. var point = this.points[i];
  1065. if (!point.mock) {
  1066. point = this.points[i] = MockPoint.fromPoint(point);
  1067. }
  1068. point[transformation](cx, cy, p1, p2);
  1069. },
  1070. /**
  1071. * Translate a controllable.
  1072. *
  1073. * @param {number} dx translation for x coordinate
  1074. * @param {number} dy translation for y coordinate
  1075. **/
  1076. translate: function (dx, dy) {
  1077. this.transform('translate', null, null, dx, dy);
  1078. },
  1079. /**
  1080. * Translate a specific point within a controllable.
  1081. *
  1082. * @param {number} dx translation for x coordinate
  1083. * @param {number} dy translation for y coordinate
  1084. * @param {number} i index of the point
  1085. **/
  1086. translatePoint: function (dx, dy, i) {
  1087. this.transformPoint('translate', null, null, dx, dy, i);
  1088. },
  1089. /**
  1090. * Translate shape within controllable item.
  1091. * Replaces `controllable.translate` method.
  1092. *
  1093. * @param {number} dx translation for x coordinate
  1094. * @param {number} dy translation for y coordinate
  1095. */
  1096. translateShape: function (dx, dy) {
  1097. var chart = this.annotation.chart,
  1098. // Annotation.options
  1099. shapeOptions = this.annotation.userOptions,
  1100. // Chart.options.annotations
  1101. annotationIndex = chart.annotations.indexOf(this.annotation), chartOptions = chart.options.annotations[annotationIndex];
  1102. this.translatePoint(dx, dy, 0);
  1103. // Options stored in:
  1104. // - chart (for exporting)
  1105. // - current config (for redraws)
  1106. chartOptions[this.collection][this.index].point = this.options.point;
  1107. shapeOptions[this.collection][this.index].point = this.options.point;
  1108. },
  1109. /**
  1110. * Rotate a controllable.
  1111. *
  1112. * @param {number} cx origin x rotation
  1113. * @param {number} cy origin y rotation
  1114. * @param {number} radians
  1115. **/
  1116. rotate: function (cx, cy, radians) {
  1117. this.transform('rotate', cx, cy, radians);
  1118. },
  1119. /**
  1120. * Scale a controllable.
  1121. *
  1122. * @param {number} cx origin x rotation
  1123. * @param {number} cy origin y rotation
  1124. * @param {number} sx scale factor x
  1125. * @param {number} sy scale factor y
  1126. */
  1127. scale: function (cx, cy, sx, sy) {
  1128. this.transform('scale', cx, cy, sx, sy);
  1129. },
  1130. /**
  1131. * Set control points' visibility.
  1132. *
  1133. * @param {boolean} visible
  1134. */
  1135. setControlPointsVisibility: function (visible) {
  1136. this.controlPoints.forEach(function (controlPoint) {
  1137. controlPoint.setVisibility(visible);
  1138. });
  1139. },
  1140. /**
  1141. * Destroy a controllable.
  1142. */
  1143. destroy: function () {
  1144. if (this.graphic) {
  1145. this.graphic = this.graphic.destroy();
  1146. }
  1147. if (this.tracker) {
  1148. this.tracker = this.tracker.destroy();
  1149. }
  1150. this.controlPoints.forEach(function (controlPoint) {
  1151. controlPoint.destroy();
  1152. });
  1153. this.chart = null;
  1154. this.points = null;
  1155. this.controlPoints = null;
  1156. this.options = null;
  1157. if (this.annotation) {
  1158. this.annotation = null;
  1159. }
  1160. },
  1161. /**
  1162. * Update a controllable.
  1163. *
  1164. * @param {Object} newOptions
  1165. */
  1166. update: function (newOptions) {
  1167. var annotation = this.annotation, options = merge(true, this.options, newOptions), parentGroup = this.graphic.parentGroup;
  1168. this.destroy();
  1169. this.constructor(annotation, options);
  1170. this.render(parentGroup);
  1171. this.redraw();
  1172. }
  1173. };
  1174. return controllableMixin;
  1175. });
  1176. _registerModule(_modules, 'annotations/controllable/markerMixin.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) {
  1177. /* *
  1178. *
  1179. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  1180. *
  1181. * */
  1182. var addEvent = U.addEvent, defined = U.defined, merge = U.merge, objectEach = U.objectEach, uniqueKey = U.uniqueKey;
  1183. /**
  1184. * Options for configuring markers for annotations.
  1185. *
  1186. * An example of the arrow marker:
  1187. * <pre>
  1188. * {
  1189. * arrow: {
  1190. * id: 'arrow',
  1191. * tagName: 'marker',
  1192. * refY: 5,
  1193. * refX: 5,
  1194. * markerWidth: 10,
  1195. * markerHeight: 10,
  1196. * children: [{
  1197. * tagName: 'path',
  1198. * attrs: {
  1199. * d: 'M 0 0 L 10 5 L 0 10 Z',
  1200. * strokeWidth: 0
  1201. * }
  1202. * }]
  1203. * }
  1204. * }
  1205. * </pre>
  1206. *
  1207. * @sample highcharts/annotations/custom-markers/
  1208. * Define a custom marker for annotations
  1209. *
  1210. * @sample highcharts/css/annotations-markers/
  1211. * Define markers in a styled mode
  1212. *
  1213. * @type {Highcharts.Dictionary<Highcharts.SVGDefinitionObject>}
  1214. * @since 6.0.0
  1215. * @optionparent defs
  1216. */
  1217. var defaultMarkers = {
  1218. /**
  1219. * @type {Highcharts.SVGDefinitionObject}
  1220. */
  1221. arrow: {
  1222. tagName: 'marker',
  1223. render: false,
  1224. id: 'arrow',
  1225. refY: 5,
  1226. refX: 9,
  1227. markerWidth: 10,
  1228. markerHeight: 10,
  1229. /**
  1230. * @type {Array<Highcharts.DefsOptions>}
  1231. */
  1232. children: [{
  1233. tagName: 'path',
  1234. d: 'M 0 0 L 10 5 L 0 10 Z',
  1235. strokeWidth: 0
  1236. }]
  1237. },
  1238. /**
  1239. * @type {Highcharts.SVGDefinitionObject}
  1240. */
  1241. 'reverse-arrow': {
  1242. tagName: 'marker',
  1243. render: false,
  1244. id: 'reverse-arrow',
  1245. refY: 5,
  1246. refX: 1,
  1247. markerWidth: 10,
  1248. markerHeight: 10,
  1249. children: [{
  1250. tagName: 'path',
  1251. // reverse triangle (used as an arrow)
  1252. d: 'M 0 5 L 10 0 L 10 10 Z',
  1253. strokeWidth: 0
  1254. }]
  1255. }
  1256. };
  1257. H.SVGRenderer.prototype.addMarker = function (id, markerOptions) {
  1258. var options = { id: id };
  1259. var attrs = {
  1260. stroke: markerOptions.color || 'none',
  1261. fill: markerOptions.color || 'rgba(0, 0, 0, 0.75)'
  1262. };
  1263. options.children = markerOptions.children.map(function (child) {
  1264. return merge(attrs, child);
  1265. });
  1266. var marker = this.definition(merge(true, {
  1267. markerWidth: 20,
  1268. markerHeight: 20,
  1269. refX: 0,
  1270. refY: 0,
  1271. orient: 'auto'
  1272. }, markerOptions, options));
  1273. marker.id = id;
  1274. return marker;
  1275. };
  1276. /* eslint-disable no-invalid-this, valid-jsdoc */
  1277. var createMarkerSetter = function (markerType) {
  1278. return function (value) {
  1279. this.attr(markerType, 'url(#' + value + ')');
  1280. };
  1281. };
  1282. /**
  1283. * @private
  1284. * @mixin
  1285. * @name Highcharts.AnnotaitonMarkerMixin
  1286. */
  1287. var markerMixin = {
  1288. markerEndSetter: createMarkerSetter('marker-end'),
  1289. markerStartSetter: createMarkerSetter('marker-start'),
  1290. /**
  1291. * Set markers.
  1292. * @private
  1293. * @param {Highcharts.AnnotationControllablePath} item
  1294. */
  1295. setItemMarkers: function (item) {
  1296. var itemOptions = item.options, chart = item.chart, defs = chart.options.defs, fill = itemOptions.fill, color = defined(fill) && fill !== 'none' ?
  1297. fill :
  1298. itemOptions.stroke, setMarker = function (markerType) {
  1299. var markerId = itemOptions[markerType], def, predefinedMarker, key, marker;
  1300. if (markerId) {
  1301. for (key in defs) { // eslint-disable-line guard-for-in
  1302. def = defs[key];
  1303. if (markerId === def.id &&
  1304. def.tagName === 'marker') {
  1305. predefinedMarker = def;
  1306. break;
  1307. }
  1308. }
  1309. if (predefinedMarker) {
  1310. marker = item[markerType] = chart.renderer
  1311. .addMarker((itemOptions.id || uniqueKey()) + '-' +
  1312. predefinedMarker.id, merge(predefinedMarker, { color: color }));
  1313. item.attr(markerType, marker.attr('id'));
  1314. }
  1315. }
  1316. };
  1317. ['markerStart', 'markerEnd'].forEach(setMarker);
  1318. }
  1319. };
  1320. addEvent(H.Chart, 'afterGetContainer', function () {
  1321. this.options.defs = merge(defaultMarkers, this.options.defs || {});
  1322. objectEach(this.options.defs, function (def) {
  1323. if (def.tagName === 'marker' && def.render !== false) {
  1324. this.renderer.addMarker(def.id, def);
  1325. }
  1326. }, this);
  1327. });
  1328. return markerMixin;
  1329. });
  1330. _registerModule(_modules, 'annotations/controllable/ControllablePath.js', [_modules['annotations/controllable/controllableMixin.js'], _modules['parts/Globals.js'], _modules['annotations/controllable/markerMixin.js'], _modules['parts/Utilities.js']], function (controllableMixin, H, markerMixin, U) {
  1331. /* *
  1332. *
  1333. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  1334. *
  1335. * */
  1336. var extend = U.extend, merge = U.merge;
  1337. // See TRACKER_FILL in highcharts.src.js
  1338. var TRACKER_FILL = 'rgba(192,192,192,' + (H.svg ? 0.0001 : 0.002) + ')';
  1339. /* eslint-disable no-invalid-this, valid-jsdoc */
  1340. /**
  1341. * A controllable path class.
  1342. *
  1343. * @requires modules/annotations
  1344. *
  1345. * @private
  1346. * @class
  1347. * @name Highcharts.AnnotationControllablePath
  1348. *
  1349. * @param {Highcharts.Annotation}
  1350. * Related annotation.
  1351. *
  1352. * @param {Highcharts.AnnotationsShapeOptions} options
  1353. * A path's options object.
  1354. *
  1355. * @param {number} index
  1356. * Index of the path.
  1357. **/
  1358. var ControllablePath = function (annotation, options, index) {
  1359. this.init(annotation, options, index);
  1360. this.collection = 'shapes';
  1361. };
  1362. /**
  1363. * A map object which allows to map options attributes to element attributes
  1364. *
  1365. * @name Highcharts.AnnotationControllablePath.attrsMap
  1366. * @type {Highcharts.Dictionary<string>}
  1367. */
  1368. ControllablePath.attrsMap = {
  1369. dashStyle: 'dashstyle',
  1370. strokeWidth: 'stroke-width',
  1371. stroke: 'stroke',
  1372. fill: 'fill',
  1373. zIndex: 'zIndex'
  1374. };
  1375. merge(true, ControllablePath.prototype, controllableMixin, /** @lends Highcharts.AnnotationControllablePath# */ {
  1376. /**
  1377. * @type 'path'
  1378. */
  1379. type: 'path',
  1380. setMarkers: markerMixin.setItemMarkers,
  1381. /**
  1382. * Map the controllable path to 'd' path attribute.
  1383. *
  1384. * @return {Highcharts.SVGPathArray|null}
  1385. * A path's d attribute.
  1386. */
  1387. toD: function () {
  1388. var dOption = this.options.d;
  1389. if (dOption) {
  1390. return typeof dOption === 'function' ?
  1391. dOption.call(this) :
  1392. dOption;
  1393. }
  1394. var points = this.points, len = points.length, showPath = len, point = points[0], position = showPath && this.anchor(point).absolutePosition, pointIndex = 0, command, d = [];
  1395. if (position) {
  1396. d.push(['M', position.x, position.y]);
  1397. while (++pointIndex < len && showPath) {
  1398. point = points[pointIndex];
  1399. command = point.command || 'L';
  1400. position = this.anchor(point).absolutePosition;
  1401. if (command === 'M') {
  1402. d.push([command, position.x, position.y]);
  1403. }
  1404. else if (command === 'L') {
  1405. d.push([command, position.x, position.y]);
  1406. }
  1407. else if (command === 'Z') {
  1408. d.push([command]);
  1409. }
  1410. showPath = point.series.visible;
  1411. }
  1412. }
  1413. return showPath ?
  1414. this.chart.renderer.crispLine(d, this.graphic.strokeWidth()) :
  1415. null;
  1416. },
  1417. shouldBeDrawn: function () {
  1418. return (controllableMixin.shouldBeDrawn.call(this) || Boolean(this.options.d));
  1419. },
  1420. render: function (parent) {
  1421. var options = this.options, attrs = this.attrsFromOptions(options);
  1422. this.graphic = this.annotation.chart.renderer
  1423. .path([['M', 0, 0]])
  1424. .attr(attrs)
  1425. .add(parent);
  1426. if (options.className) {
  1427. this.graphic.addClass(options.className);
  1428. }
  1429. this.tracker = this.annotation.chart.renderer
  1430. .path([['M', 0, 0]])
  1431. .addClass('highcharts-tracker-line')
  1432. .attr({
  1433. zIndex: 2
  1434. })
  1435. .add(parent);
  1436. if (!this.annotation.chart.styledMode) {
  1437. this.tracker.attr({
  1438. 'stroke-linejoin': 'round',
  1439. stroke: TRACKER_FILL,
  1440. fill: TRACKER_FILL,
  1441. 'stroke-width': this.graphic.strokeWidth() +
  1442. options.snap * 2
  1443. });
  1444. }
  1445. controllableMixin.render.call(this);
  1446. extend(this.graphic, {
  1447. markerStartSetter: markerMixin.markerStartSetter,
  1448. markerEndSetter: markerMixin.markerEndSetter
  1449. });
  1450. this.setMarkers(this);
  1451. },
  1452. redraw: function (animation) {
  1453. var d = this.toD(), action = animation ? 'animate' : 'attr';
  1454. if (d) {
  1455. this.graphic[action]({ d: d });
  1456. this.tracker[action]({ d: d });
  1457. }
  1458. else {
  1459. this.graphic.attr({ d: 'M 0 ' + -9e9 });
  1460. this.tracker.attr({ d: 'M 0 ' + -9e9 });
  1461. }
  1462. this.graphic.placed = this.tracker.placed = Boolean(d);
  1463. controllableMixin.redraw.call(this, animation);
  1464. }
  1465. });
  1466. return ControllablePath;
  1467. });
  1468. _registerModule(_modules, 'annotations/controllable/ControllableRect.js', [_modules['annotations/controllable/controllableMixin.js'], _modules['annotations/controllable/ControllablePath.js'], _modules['parts/Utilities.js']], function (controllableMixin, ControllablePath, U) {
  1469. /* *
  1470. *
  1471. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  1472. *
  1473. * */
  1474. var merge = U.merge;
  1475. /* eslint-disable no-invalid-this, valid-jsdoc */
  1476. /**
  1477. * A controllable rect class.
  1478. *
  1479. * @requires modules/annotations
  1480. *
  1481. * @private
  1482. * @class
  1483. * @name Highcharts.AnnotationControllableRect
  1484. *
  1485. * @param {Highcharts.Annotation} annotation
  1486. * An annotation instance.
  1487. *
  1488. * @param {Highcharts.AnnotationsShapeOptions} options
  1489. * A rect's options.
  1490. *
  1491. * @param {number} index
  1492. * Index of the rectangle
  1493. */
  1494. var ControllableRect = function (annotation, options, index) {
  1495. this.init(annotation, options, index);
  1496. this.collection = 'shapes';
  1497. };
  1498. /**
  1499. * @typedef {Annotation.ControllablePath.AttrsMap}
  1500. * Annotation.ControllableRect.AttrsMap
  1501. * @property {string} width=width
  1502. * @property {string} height=height
  1503. */
  1504. /**
  1505. * A map object which allows to map options attributes to element attributes
  1506. *
  1507. * @type {Annotation.ControllableRect.AttrsMap}
  1508. */
  1509. ControllableRect.attrsMap = merge(ControllablePath.attrsMap, {
  1510. width: 'width',
  1511. height: 'height'
  1512. });
  1513. merge(true, ControllableRect.prototype, controllableMixin, /** @lends Annotation.ControllableRect# */ {
  1514. /**
  1515. * @type 'rect'
  1516. */
  1517. type: 'rect',
  1518. translate: controllableMixin.translateShape,
  1519. render: function (parent) {
  1520. var attrs = this.attrsFromOptions(this.options);
  1521. this.graphic = this.annotation.chart.renderer
  1522. .rect(0, -9e9, 0, 0)
  1523. .attr(attrs)
  1524. .add(parent);
  1525. controllableMixin.render.call(this);
  1526. },
  1527. redraw: function (animation) {
  1528. var position = this.anchor(this.points[0]).absolutePosition;
  1529. if (position) {
  1530. this.graphic[animation ? 'animate' : 'attr']({
  1531. x: position.x,
  1532. y: position.y,
  1533. width: this.options.width,
  1534. height: this.options.height
  1535. });
  1536. }
  1537. else {
  1538. this.attr({
  1539. x: 0,
  1540. y: -9e9
  1541. });
  1542. }
  1543. this.graphic.placed = Boolean(position);
  1544. controllableMixin.redraw.call(this, animation);
  1545. }
  1546. });
  1547. return ControllableRect;
  1548. });
  1549. _registerModule(_modules, 'annotations/controllable/ControllableCircle.js', [_modules['annotations/controllable/controllableMixin.js'], _modules['annotations/controllable/ControllablePath.js'], _modules['parts/Utilities.js']], function (controllableMixin, ControllablePath, U) {
  1550. /* *
  1551. *
  1552. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  1553. *
  1554. * */
  1555. var merge = U.merge;
  1556. /* eslint-disable no-invalid-this, valid-jsdoc */
  1557. /**
  1558. * A controllable circle class.
  1559. *
  1560. * @requires modules/annotations
  1561. *
  1562. * @private
  1563. * @constructor
  1564. * @name Highcharts.AnnotationControllableCircle
  1565. *
  1566. * @param {Highcharts.Annotation} annotation an annotation instance
  1567. * @param {Highcharts.AnnotationsShapeOptions} options a shape's options
  1568. * @param {number} index of the circle
  1569. **/
  1570. var ControllableCircle = function (annotation, options, index) {
  1571. this.init(annotation, options, index);
  1572. this.collection = 'shapes';
  1573. };
  1574. /**
  1575. * A map object which allows to map options attributes to element attributes.
  1576. *
  1577. * @name Highcharts.AnnotationControllableCircle.attrsMap
  1578. * @type {Highcharts.Dictionary<string>}
  1579. */
  1580. ControllableCircle.attrsMap = merge(ControllablePath.attrsMap, {
  1581. r: 'r'
  1582. });
  1583. merge(true, ControllableCircle.prototype, controllableMixin, /** @lends Highcharts.AnnotationControllableCircle# */ {
  1584. /**
  1585. * @type 'circle'
  1586. */
  1587. type: 'circle',
  1588. translate: controllableMixin.translateShape,
  1589. render: function (parent) {
  1590. var attrs = this.attrsFromOptions(this.options);
  1591. this.graphic = this.annotation.chart.renderer
  1592. .circle(0, -9e9, 0)
  1593. .attr(attrs)
  1594. .add(parent);
  1595. controllableMixin.render.call(this);
  1596. },
  1597. redraw: function (animation) {
  1598. var position = this.anchor(this.points[0]).absolutePosition;
  1599. if (position) {
  1600. this.graphic[animation ? 'animate' : 'attr']({
  1601. x: position.x,
  1602. y: position.y,
  1603. r: this.options.r
  1604. });
  1605. }
  1606. else {
  1607. this.graphic.attr({
  1608. x: 0,
  1609. y: -9e9
  1610. });
  1611. }
  1612. this.graphic.placed = Boolean(position);
  1613. controllableMixin.redraw.call(this, animation);
  1614. },
  1615. /**
  1616. * Set the radius.
  1617. *
  1618. * @param {number} r a radius to be set
  1619. */
  1620. setRadius: function (r) {
  1621. this.options.r = r;
  1622. }
  1623. });
  1624. return ControllableCircle;
  1625. });
  1626. _registerModule(_modules, 'annotations/controllable/ControllableLabel.js', [_modules['annotations/controllable/controllableMixin.js'], _modules['parts/Globals.js'], _modules['annotations/MockPoint.js'], _modules['parts/Tooltip.js'], _modules['parts/Utilities.js']], function (controllableMixin, H, MockPoint, Tooltip, U) {
  1627. /* *
  1628. *
  1629. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  1630. *
  1631. * */
  1632. var extend = U.extend, format = U.format, isNumber = U.isNumber, merge = U.merge, pick = U.pick;
  1633. /* eslint-disable no-invalid-this, valid-jsdoc */
  1634. /**
  1635. * A controllable label class.
  1636. *
  1637. * @requires modules/annotations
  1638. *
  1639. * @private
  1640. * @class
  1641. * @name Highcharts.AnnotationControllableLabel
  1642. *
  1643. * @param {Highcharts.Annotation} annotation
  1644. * An annotation instance.
  1645. * @param {Highcharts.AnnotationsLabelOptions} options
  1646. * A label's options.
  1647. * @param {number} index
  1648. * Index of the label.
  1649. */
  1650. var ControllableLabel = function (annotation, options, index) {
  1651. this.init(annotation, options, index);
  1652. this.collection = 'labels';
  1653. };
  1654. /**
  1655. * Shapes which do not have background - the object is used for proper
  1656. * setting of the contrast color.
  1657. *
  1658. * @type {Array<string>}
  1659. */
  1660. ControllableLabel.shapesWithoutBackground = ['connector'];
  1661. /**
  1662. * Returns new aligned position based alignment options and box to align to.
  1663. * It is almost a one-to-one copy from SVGElement.prototype.align
  1664. * except it does not use and mutate an element
  1665. *
  1666. * @param {Highcharts.AnnotationAlignObject} alignOptions
  1667. *
  1668. * @param {Highcharts.BBoxObject} box
  1669. *
  1670. * @return {Highcharts.PositionObject}
  1671. * Aligned position.
  1672. */
  1673. ControllableLabel.alignedPosition = function (alignOptions, box) {
  1674. var align = alignOptions.align, vAlign = alignOptions.verticalAlign, x = (box.x || 0) + (alignOptions.x || 0), y = (box.y || 0) + (alignOptions.y || 0), alignFactor, vAlignFactor;
  1675. if (align === 'right') {
  1676. alignFactor = 1;
  1677. }
  1678. else if (align === 'center') {
  1679. alignFactor = 2;
  1680. }
  1681. if (alignFactor) {
  1682. x += (box.width - (alignOptions.width || 0)) / alignFactor;
  1683. }
  1684. if (vAlign === 'bottom') {
  1685. vAlignFactor = 1;
  1686. }
  1687. else if (vAlign === 'middle') {
  1688. vAlignFactor = 2;
  1689. }
  1690. if (vAlignFactor) {
  1691. y += (box.height - (alignOptions.height || 0)) / vAlignFactor;
  1692. }
  1693. return {
  1694. x: Math.round(x),
  1695. y: Math.round(y)
  1696. };
  1697. };
  1698. /**
  1699. * Returns new alignment options for a label if the label is outside the
  1700. * plot area. It is almost a one-to-one copy from
  1701. * Series.prototype.justifyDataLabel except it does not mutate the label and
  1702. * it works with absolute instead of relative position.
  1703. */
  1704. ControllableLabel.justifiedOptions = function (chart, label, alignOptions, alignAttr) {
  1705. var align = alignOptions.align, verticalAlign = alignOptions.verticalAlign, padding = label.box ? 0 : (label.padding || 0), bBox = label.getBBox(), off,
  1706. //
  1707. options = {
  1708. align: align,
  1709. verticalAlign: verticalAlign,
  1710. x: alignOptions.x,
  1711. y: alignOptions.y,
  1712. width: label.width,
  1713. height: label.height
  1714. },
  1715. //
  1716. x = alignAttr.x - chart.plotLeft, y = alignAttr.y - chart.plotTop;
  1717. // Off left
  1718. off = x + padding;
  1719. if (off < 0) {
  1720. if (align === 'right') {
  1721. options.align = 'left';
  1722. }
  1723. else {
  1724. options.x = -off;
  1725. }
  1726. }
  1727. // Off right
  1728. off = x + bBox.width - padding;
  1729. if (off > chart.plotWidth) {
  1730. if (align === 'left') {
  1731. options.align = 'right';
  1732. }
  1733. else {
  1734. options.x = chart.plotWidth - off;
  1735. }
  1736. }
  1737. // Off top
  1738. off = y + padding;
  1739. if (off < 0) {
  1740. if (verticalAlign === 'bottom') {
  1741. options.verticalAlign = 'top';
  1742. }
  1743. else {
  1744. options.y = -off;
  1745. }
  1746. }
  1747. // Off bottom
  1748. off = y + bBox.height - padding;
  1749. if (off > chart.plotHeight) {
  1750. if (verticalAlign === 'top') {
  1751. options.verticalAlign = 'bottom';
  1752. }
  1753. else {
  1754. options.y = chart.plotHeight - off;
  1755. }
  1756. }
  1757. return options;
  1758. };
  1759. /**
  1760. * A map object which allows to map options attributes to element attributes
  1761. *
  1762. * @type {Highcharts.Dictionary<string>}
  1763. */
  1764. ControllableLabel.attrsMap = {
  1765. backgroundColor: 'fill',
  1766. borderColor: 'stroke',
  1767. borderWidth: 'stroke-width',
  1768. zIndex: 'zIndex',
  1769. borderRadius: 'r',
  1770. padding: 'padding'
  1771. };
  1772. merge(true, ControllableLabel.prototype, controllableMixin,
  1773. /** @lends Annotation.ControllableLabel# */ {
  1774. /**
  1775. * Translate the point of the label by deltaX and deltaY translations.
  1776. * The point is the label's anchor.
  1777. *
  1778. * @param {number} dx translation for x coordinate
  1779. * @param {number} dy translation for y coordinate
  1780. **/
  1781. translatePoint: function (dx, dy) {
  1782. controllableMixin.translatePoint.call(this, dx, dy, 0);
  1783. },
  1784. /**
  1785. * Translate x and y position relative to the label's anchor.
  1786. *
  1787. * @param {number} dx translation for x coordinate
  1788. * @param {number} dy translation for y coordinate
  1789. **/
  1790. translate: function (dx, dy) {
  1791. var chart = this.annotation.chart,
  1792. // Annotation.options
  1793. labelOptions = this.annotation.userOptions,
  1794. // Chart.options.annotations
  1795. annotationIndex = chart.annotations.indexOf(this.annotation), chartAnnotations = chart.options.annotations, chartOptions = chartAnnotations[annotationIndex], temp;
  1796. if (chart.inverted) {
  1797. temp = dx;
  1798. dx = dy;
  1799. dy = temp;
  1800. }
  1801. // Local options:
  1802. this.options.x += dx;
  1803. this.options.y += dy;
  1804. // Options stored in chart:
  1805. chartOptions[this.collection][this.index].x = this.options.x;
  1806. chartOptions[this.collection][this.index].y = this.options.y;
  1807. labelOptions[this.collection][this.index].x = this.options.x;
  1808. labelOptions[this.collection][this.index].y = this.options.y;
  1809. },
  1810. render: function (parent) {
  1811. var options = this.options, attrs = this.attrsFromOptions(options), style = options.style;
  1812. this.graphic = this.annotation.chart.renderer
  1813. .label('', 0, -9999, // #10055
  1814. options.shape, null, null, options.useHTML, null, 'annotation-label')
  1815. .attr(attrs)
  1816. .add(parent);
  1817. if (!this.annotation.chart.styledMode) {
  1818. if (style.color === 'contrast') {
  1819. style.color = this.annotation.chart.renderer.getContrast(ControllableLabel.shapesWithoutBackground.indexOf(options.shape) > -1 ? '#FFFFFF' : options.backgroundColor);
  1820. }
  1821. this.graphic
  1822. .css(options.style)
  1823. .shadow(options.shadow);
  1824. }
  1825. if (options.className) {
  1826. this.graphic.addClass(options.className);
  1827. }
  1828. this.graphic.labelrank = options.labelrank;
  1829. controllableMixin.render.call(this);
  1830. },
  1831. redraw: function (animation) {
  1832. var options = this.options, text = this.text || options.format || options.text, label = this.graphic, point = this.points[0], show = false, anchor, attrs;
  1833. label.attr({
  1834. text: text ?
  1835. format(text, point.getLabelConfig(), this.annotation.chart) :
  1836. options.formatter.call(point, this)
  1837. });
  1838. anchor = this.anchor(point);
  1839. attrs = this.position(anchor);
  1840. show = attrs;
  1841. if (show) {
  1842. label.alignAttr = attrs;
  1843. attrs.anchorX = anchor.absolutePosition.x;
  1844. attrs.anchorY = anchor.absolutePosition.y;
  1845. label[animation ? 'animate' : 'attr'](attrs);
  1846. }
  1847. else {
  1848. label.attr({
  1849. x: 0,
  1850. y: -9999 // #10055
  1851. });
  1852. }
  1853. label.placed = Boolean(show);
  1854. controllableMixin.redraw.call(this, animation);
  1855. },
  1856. /**
  1857. * All basic shapes don't support alignTo() method except label.
  1858. * For a controllable label, we need to subtract translation from
  1859. * options.
  1860. */
  1861. anchor: function () {
  1862. var anchor = controllableMixin.anchor.apply(this, arguments), x = this.options.x || 0, y = this.options.y || 0;
  1863. anchor.absolutePosition.x -= x;
  1864. anchor.absolutePosition.y -= y;
  1865. anchor.relativePosition.x -= x;
  1866. anchor.relativePosition.y -= y;
  1867. return anchor;
  1868. },
  1869. /**
  1870. * Returns the label position relative to its anchor.
  1871. *
  1872. * @param {Highcharts.AnnotationAnchorObject} anchor
  1873. *
  1874. * @return {Highcharts.PositionObject|null}
  1875. */
  1876. position: function (anchor) {
  1877. var item = this.graphic, chart = this.annotation.chart, point = this.points[0], itemOptions = this.options, anchorAbsolutePosition = anchor.absolutePosition, anchorRelativePosition = anchor.relativePosition, itemPosition, alignTo, itemPosRelativeX, itemPosRelativeY, showItem = point.series.visible &&
  1878. MockPoint.prototype.isInsidePlot.call(point);
  1879. if (showItem) {
  1880. if (itemOptions.distance) {
  1881. itemPosition = Tooltip.prototype.getPosition.call({
  1882. chart: chart,
  1883. distance: pick(itemOptions.distance, 16)
  1884. }, item.width, item.height, {
  1885. plotX: anchorRelativePosition.x,
  1886. plotY: anchorRelativePosition.y,
  1887. negative: point.negative,
  1888. ttBelow: point.ttBelow,
  1889. h: (anchorRelativePosition.height || anchorRelativePosition.width)
  1890. });
  1891. }
  1892. else if (itemOptions.positioner) {
  1893. itemPosition = itemOptions.positioner.call(this);
  1894. }
  1895. else {
  1896. alignTo = {
  1897. x: anchorAbsolutePosition.x,
  1898. y: anchorAbsolutePosition.y,
  1899. width: 0,
  1900. height: 0
  1901. };
  1902. itemPosition = ControllableLabel.alignedPosition(extend(itemOptions, {
  1903. width: item.width,
  1904. height: item.height
  1905. }), alignTo);
  1906. if (this.options.overflow === 'justify') {
  1907. itemPosition = ControllableLabel.alignedPosition(ControllableLabel.justifiedOptions(chart, item, itemOptions, itemPosition), alignTo);
  1908. }
  1909. }
  1910. if (itemOptions.crop) {
  1911. itemPosRelativeX = itemPosition.x - chart.plotLeft;
  1912. itemPosRelativeY = itemPosition.y - chart.plotTop;
  1913. showItem =
  1914. chart.isInsidePlot(itemPosRelativeX, itemPosRelativeY) &&
  1915. chart.isInsidePlot(itemPosRelativeX + item.width, itemPosRelativeY + item.height);
  1916. }
  1917. }
  1918. return showItem ? itemPosition : null;
  1919. }
  1920. });
  1921. /* ********************************************************************** */
  1922. /**
  1923. * General symbol definition for labels with connector
  1924. * @private
  1925. */
  1926. H.SVGRenderer.prototype.symbols.connector = function (x, y, w, h, options) {
  1927. var anchorX = options && options.anchorX, anchorY = options && options.anchorY, path, yOffset, lateral = w / 2;
  1928. if (isNumber(anchorX) && isNumber(anchorY)) {
  1929. path = [['M', anchorX, anchorY]];
  1930. // Prefer 45 deg connectors
  1931. yOffset = y - anchorY;
  1932. if (yOffset < 0) {
  1933. yOffset = -h - yOffset;
  1934. }
  1935. if (yOffset < w) {
  1936. lateral = anchorX < x + (w / 2) ? yOffset : w - yOffset;
  1937. }
  1938. // Anchor below label
  1939. if (anchorY > y + h) {
  1940. path.push(['L', x + lateral, y + h]);
  1941. // Anchor above label
  1942. }
  1943. else if (anchorY < y) {
  1944. path.push(['L', x + lateral, y]);
  1945. // Anchor left of label
  1946. }
  1947. else if (anchorX < x) {
  1948. path.push(['L', x, y + h / 2]);
  1949. // Anchor right of label
  1950. }
  1951. else if (anchorX > x + w) {
  1952. path.push(['L', x + w, y + h / 2]);
  1953. }
  1954. }
  1955. return path || [];
  1956. };
  1957. return ControllableLabel;
  1958. });
  1959. _registerModule(_modules, 'annotations/controllable/ControllableImage.js', [_modules['annotations/controllable/ControllableLabel.js'], _modules['annotations/controllable/controllableMixin.js'], _modules['parts/Utilities.js']], function (ControllableLabel, controllableMixin, U) {
  1960. /* *
  1961. *
  1962. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  1963. *
  1964. * */
  1965. var merge = U.merge;
  1966. /* eslint-disable no-invalid-this, valid-jsdoc */
  1967. /**
  1968. * A controllable image class.
  1969. *
  1970. * @requires modules/annotations
  1971. *
  1972. * @private
  1973. * @class
  1974. * @name Highcharts.AnnotationControllableImage
  1975. *
  1976. * @param {Highcharts.Annotation} annotation
  1977. * An annotation instance.
  1978. *
  1979. * @param {Highcharts.AnnotationsShapeOptions} options
  1980. * A controllable's options.
  1981. *
  1982. * @param {number} index
  1983. * Index of the image.
  1984. **/
  1985. var ControllableImage = function (annotation, options, index) {
  1986. this.init(annotation, options, index);
  1987. this.collection = 'shapes';
  1988. };
  1989. /**
  1990. * A map object which allows to map options attributes to element attributes
  1991. *
  1992. * @name Highcharts.AnnotationControllableImage.attrsMap
  1993. * @type {Highcharts.Dictionary<string>}
  1994. */
  1995. ControllableImage.attrsMap = {
  1996. width: 'width',
  1997. height: 'height',
  1998. zIndex: 'zIndex'
  1999. };
  2000. merge(true, ControllableImage.prototype, controllableMixin, /** @lends Annotation.ControllableImage# */ {
  2001. /**
  2002. * @type 'image'
  2003. */
  2004. type: 'image',
  2005. translate: controllableMixin.translateShape,
  2006. render: function (parent) {
  2007. var attrs = this.attrsFromOptions(this.options), options = this.options;
  2008. this.graphic = this.annotation.chart.renderer
  2009. .image(options.src, 0, -9e9, options.width, options.height)
  2010. .attr(attrs)
  2011. .add(parent);
  2012. this.graphic.width = options.width;
  2013. this.graphic.height = options.height;
  2014. controllableMixin.render.call(this);
  2015. },
  2016. redraw: function (animation) {
  2017. var anchor = this.anchor(this.points[0]), position = ControllableLabel.prototype.position.call(this, anchor);
  2018. if (position) {
  2019. this.graphic[animation ? 'animate' : 'attr']({
  2020. x: position.x,
  2021. y: position.y
  2022. });
  2023. }
  2024. else {
  2025. this.graphic.attr({
  2026. x: 0,
  2027. y: -9e9
  2028. });
  2029. }
  2030. this.graphic.placed = Boolean(position);
  2031. controllableMixin.redraw.call(this, animation);
  2032. }
  2033. });
  2034. return ControllableImage;
  2035. });
  2036. _registerModule(_modules, 'annotations/annotations.src.js', [_modules['parts/Chart.js'], _modules['annotations/controllable/controllableMixin.js'], _modules['annotations/controllable/ControllableRect.js'], _modules['annotations/controllable/ControllableCircle.js'], _modules['annotations/controllable/ControllablePath.js'], _modules['annotations/controllable/ControllableImage.js'], _modules['annotations/controllable/ControllableLabel.js'], _modules['annotations/ControlPoint.js'], _modules['annotations/eventEmitterMixin.js'], _modules['parts/Globals.js'], _modules['annotations/MockPoint.js'], _modules['parts/Pointer.js'], _modules['parts/Utilities.js']], function (Chart, ControllableMixin, ControllableRect, ControllableCircle, ControllablePath, ControllableImage, ControllableLabel, ControlPoint, EventEmitterMixin, H, MockPoint, Pointer, U) {
  2037. /* *
  2038. *
  2039. * (c) 2009-2017 Highsoft, Black Label
  2040. *
  2041. * License: www.highcharts.com/license
  2042. *
  2043. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  2044. *
  2045. * */
  2046. var chartProto = Chart.prototype;
  2047. var addEvent = U.addEvent, defined = U.defined, destroyObjectProperties = U.destroyObjectProperties, erase = U.erase, extend = U.extend, find = U.find, fireEvent = U.fireEvent, merge = U.merge, pick = U.pick, splat = U.splat, wrap = U.wrap;
  2048. /* *********************************************************************
  2049. *
  2050. * ANNOTATION
  2051. *
  2052. ******************************************************************** */
  2053. /**
  2054. * Possible directions for draggable annotations. An empty string (`''`)
  2055. * makes the annotation undraggable.
  2056. *
  2057. * @typedef {''|'x'|'xy'|'y'} Highcharts.AnnotationDraggableValue
  2058. */
  2059. /**
  2060. * @private
  2061. * @typedef {
  2062. * Highcharts.AnnotationControllableCircle|
  2063. * Highcharts.AnnotationControllableImage|
  2064. * Highcharts.AnnotationControllablePath|
  2065. * Highcharts.AnnotationControllableRect
  2066. * }
  2067. * Highcharts.AnnotationShapeType
  2068. * @requires modules/annotations
  2069. */
  2070. /**
  2071. * @private
  2072. * @typedef {
  2073. * Highcharts.AnnotationControllableLabel
  2074. * }
  2075. * Highcharts.AnnotationLabelType
  2076. * @requires modules/annotations
  2077. */
  2078. /**
  2079. * A point-like object, a mock point or a point used in series.
  2080. * @private
  2081. * @typedef {Highcharts.AnnotationMockPoint|Highcharts.Point} Highcharts.AnnotationPointType
  2082. * @requires modules/annotations
  2083. */
  2084. /* eslint-disable no-invalid-this, valid-jsdoc */
  2085. /**
  2086. * An annotation class which serves as a container for items like labels or
  2087. * shapes. Created items are positioned on the chart either by linking them to
  2088. * existing points or created mock points
  2089. *
  2090. * @class
  2091. * @name Highcharts.Annotation
  2092. *
  2093. * @param {Highcharts.Chart} chart a chart instance
  2094. * @param {Highcharts.AnnotationsOptions} userOptions the options object
  2095. */
  2096. var Annotation = /** @class */ (function () {
  2097. /* *
  2098. *
  2099. * Constructors
  2100. *
  2101. * */
  2102. function Annotation(chart, userOptions) {
  2103. /* *
  2104. *
  2105. * Properties
  2106. *
  2107. * */
  2108. this.annotation = void 0;
  2109. this.coll = 'annotations';
  2110. this.collection = void 0;
  2111. this.graphic = void 0;
  2112. this.group = void 0;
  2113. this.labelCollector = void 0;
  2114. this.labelsGroup = void 0;
  2115. this.shapesGroup = void 0;
  2116. var labelsAndShapes;
  2117. /**
  2118. * The chart that the annotation belongs to.
  2119. *
  2120. * @type {Highcharts.Chart}
  2121. */
  2122. this.chart = chart;
  2123. /**
  2124. * The array of points which defines the annotation.
  2125. *
  2126. * @type {Array<Highcharts.Point>}
  2127. */
  2128. this.points = [];
  2129. /**
  2130. * The array of control points.
  2131. *
  2132. * @private
  2133. * @name Highcharts.Annotation#controlPoints
  2134. * @type {Array<Annotation.ControlPoint>}
  2135. */
  2136. this.controlPoints = [];
  2137. this.coll = 'annotations';
  2138. /**
  2139. * The array of labels which belong to the annotation.
  2140. *
  2141. * @private
  2142. * @name Highcharts.Annotation#labels
  2143. * @type {Array<Highcharts.AnnotationLabelType>}
  2144. */
  2145. this.labels = [];
  2146. /**
  2147. * The array of shapes which belong to the annotation.
  2148. *
  2149. * @private
  2150. * @name Highcharts.Annotation#shapes
  2151. * @type {Array<Highcharts.AnnotationShapeType>}
  2152. */
  2153. this.shapes = [];
  2154. /**
  2155. * The options for the annotations.
  2156. *
  2157. * @name Highcharts.Annotation#options
  2158. * @type {Highcharts.AnnotationsOptions}
  2159. */
  2160. this.options = merge(this.defaultOptions, userOptions);
  2161. /**
  2162. * The user options for the annotations.
  2163. *
  2164. * @name Highcharts.Annotation#userOptions
  2165. * @type {Highcharts.AnnotationsOptions}
  2166. */
  2167. this.userOptions = userOptions;
  2168. // Handle labels and shapes - those are arrays
  2169. // Merging does not work with arrays (stores reference)
  2170. labelsAndShapes = this.getLabelsAndShapesOptions(this.options, userOptions);
  2171. this.options.labels = labelsAndShapes.labels;
  2172. this.options.shapes = labelsAndShapes.shapes;
  2173. /**
  2174. * The callback that reports to the overlapping-labels module which
  2175. * labels it should account for.
  2176. * @private
  2177. * @name Highcharts.Annotation#labelCollector
  2178. * @type {Function}
  2179. */
  2180. /**
  2181. * The group svg element.
  2182. *
  2183. * @name Highcharts.Annotation#group
  2184. * @type {Highcharts.SVGElement}
  2185. */
  2186. /**
  2187. * The group svg element of the annotation's shapes.
  2188. *
  2189. * @name Highcharts.Annotation#shapesGroup
  2190. * @type {Highcharts.SVGElement}
  2191. */
  2192. /**
  2193. * The group svg element of the annotation's labels.
  2194. *
  2195. * @name Highcharts.Annotation#labelsGroup
  2196. * @type {Highcharts.SVGElement}
  2197. */
  2198. this.init(chart, this.options);
  2199. }
  2200. /**
  2201. * Initialize the annotation.
  2202. * @private
  2203. */
  2204. Annotation.prototype.init = function () {
  2205. this.linkPoints();
  2206. this.addControlPoints();
  2207. this.addShapes();
  2208. this.addLabels();
  2209. this.setLabelCollector();
  2210. };
  2211. Annotation.prototype.getLabelsAndShapesOptions = function (baseOptions, newOptions) {
  2212. var mergedOptions = {};
  2213. ['labels', 'shapes'].forEach(function (name) {
  2214. if (baseOptions[name]) {
  2215. mergedOptions[name] = splat(newOptions[name]).map(function (basicOptions, i) {
  2216. return merge(baseOptions[name][i], basicOptions);
  2217. });
  2218. }
  2219. });
  2220. return mergedOptions;
  2221. };
  2222. Annotation.prototype.addShapes = function () {
  2223. (this.options.shapes || []).forEach(function (shapeOptions, i) {
  2224. var shape = this.initShape(shapeOptions, i);
  2225. merge(true, this.options.shapes[i], shape.options);
  2226. }, this);
  2227. };
  2228. Annotation.prototype.addLabels = function () {
  2229. (this.options.labels || []).forEach(function (labelsOptions, i) {
  2230. var labels = this.initLabel(labelsOptions, i);
  2231. merge(true, this.options.labels[i], labels.options);
  2232. }, this);
  2233. };
  2234. Annotation.prototype.addClipPaths = function () {
  2235. this.setClipAxes();
  2236. if (this.clipXAxis && this.clipYAxis) {
  2237. this.clipRect = this.chart.renderer.clipRect(this.getClipBox());
  2238. }
  2239. };
  2240. Annotation.prototype.setClipAxes = function () {
  2241. var xAxes = this.chart.xAxis, yAxes = this.chart.yAxis, linkedAxes = (this.options.labels || [])
  2242. .concat(this.options.shapes || [])
  2243. .reduce(function (axes, labelOrShape) {
  2244. return [
  2245. xAxes[labelOrShape &&
  2246. labelOrShape.point &&
  2247. labelOrShape.point.xAxis] || axes[0],
  2248. yAxes[labelOrShape &&
  2249. labelOrShape.point &&
  2250. labelOrShape.point.yAxis] || axes[1]
  2251. ];
  2252. }, []);
  2253. this.clipXAxis = linkedAxes[0];
  2254. this.clipYAxis = linkedAxes[1];
  2255. };
  2256. Annotation.prototype.getClipBox = function () {
  2257. if (this.clipXAxis && this.clipYAxis) {
  2258. return {
  2259. x: this.clipXAxis.left,
  2260. y: this.clipYAxis.top,
  2261. width: this.clipXAxis.width,
  2262. height: this.clipYAxis.height
  2263. };
  2264. }
  2265. };
  2266. Annotation.prototype.setLabelCollector = function () {
  2267. var annotation = this;
  2268. annotation.labelCollector = function () {
  2269. return annotation.labels.reduce(function (labels, label) {
  2270. if (!label.options.allowOverlap) {
  2271. labels.push(label.graphic);
  2272. }
  2273. return labels;
  2274. }, []);
  2275. };
  2276. annotation.chart.labelCollectors.push(annotation.labelCollector);
  2277. };
  2278. /**
  2279. * Set an annotation options.
  2280. * @private
  2281. * @param {Highcharts.AnnotationsOptions} - user options for an annotation
  2282. */
  2283. Annotation.prototype.setOptions = function (userOptions) {
  2284. this.options = merge(this.defaultOptions, userOptions);
  2285. };
  2286. Annotation.prototype.redraw = function (animation) {
  2287. this.linkPoints();
  2288. if (!this.graphic) {
  2289. this.render();
  2290. }
  2291. if (this.clipRect) {
  2292. this.clipRect.animate(this.getClipBox());
  2293. }
  2294. this.redrawItems(this.shapes, animation);
  2295. this.redrawItems(this.labels, animation);
  2296. ControllableMixin.redraw.call(this, animation);
  2297. };
  2298. /**
  2299. * @private
  2300. * @param {Array<Highcharts.AnnotationControllable>} items
  2301. * @param {boolean} [animation]
  2302. */
  2303. Annotation.prototype.redrawItems = function (items, animation) {
  2304. var i = items.length;
  2305. // needs a backward loop
  2306. // labels/shapes array might be modified
  2307. // due to destruction of the item
  2308. while (i--) {
  2309. this.redrawItem(items[i], animation);
  2310. }
  2311. };
  2312. /**
  2313. * @private
  2314. * @param {Array<Highcharts.AnnotationControllable>} items
  2315. */
  2316. Annotation.prototype.renderItems = function (items) {
  2317. var i = items.length;
  2318. while (i--) {
  2319. this.renderItem(items[i]);
  2320. }
  2321. };
  2322. Annotation.prototype.render = function () {
  2323. var renderer = this.chart.renderer;
  2324. this.graphic = renderer
  2325. .g('annotation')
  2326. .attr({
  2327. zIndex: this.options.zIndex,
  2328. visibility: this.options.visible ?
  2329. 'visible' :
  2330. 'hidden'
  2331. })
  2332. .add();
  2333. this.shapesGroup = renderer
  2334. .g('annotation-shapes')
  2335. .add(this.graphic)
  2336. .clip(this.chart.plotBoxClip);
  2337. this.labelsGroup = renderer
  2338. .g('annotation-labels')
  2339. .attr({
  2340. // hideOverlappingLabels requires translation
  2341. translateX: 0,
  2342. translateY: 0
  2343. })
  2344. .add(this.graphic);
  2345. this.addClipPaths();
  2346. if (this.clipRect) {
  2347. this.graphic.clip(this.clipRect);
  2348. }
  2349. // Render shapes and labels before adding events (#13070).
  2350. this.renderItems(this.shapes);
  2351. this.renderItems(this.labels);
  2352. this.addEvents();
  2353. ControllableMixin.render.call(this);
  2354. };
  2355. /**
  2356. * Set the annotation's visibility.
  2357. * @private
  2358. * @param {boolean} [visible]
  2359. * Whether to show or hide an annotation. If the param is omitted, the
  2360. * annotation's visibility is toggled.
  2361. */
  2362. Annotation.prototype.setVisibility = function (visible) {
  2363. var options = this.options, visibility = pick(visible, !options.visible);
  2364. this.graphic.attr('visibility', visibility ? 'visible' : 'hidden');
  2365. if (!visibility) {
  2366. this.setControlPointsVisibility(false);
  2367. }
  2368. options.visible = visibility;
  2369. };
  2370. Annotation.prototype.setControlPointsVisibility = function (visible) {
  2371. var setItemControlPointsVisibility = function (item) {
  2372. item.setControlPointsVisibility(visible);
  2373. };
  2374. ControllableMixin.setControlPointsVisibility.call(this, visible);
  2375. this.shapes.forEach(setItemControlPointsVisibility);
  2376. this.labels.forEach(setItemControlPointsVisibility);
  2377. };
  2378. /**
  2379. * Destroy the annotation. This function does not touch the chart
  2380. * that the annotation belongs to (all annotations are kept in
  2381. * the chart.annotations array) - it is recommended to use
  2382. * {@link Highcharts.Chart#removeAnnotation} instead.
  2383. * @private
  2384. */
  2385. Annotation.prototype.destroy = function () {
  2386. var chart = this.chart, destroyItem = function (item) {
  2387. item.destroy();
  2388. };
  2389. this.labels.forEach(destroyItem);
  2390. this.shapes.forEach(destroyItem);
  2391. this.clipXAxis = null;
  2392. this.clipYAxis = null;
  2393. erase(chart.labelCollectors, this.labelCollector);
  2394. EventEmitterMixin.destroy.call(this);
  2395. ControllableMixin.destroy.call(this);
  2396. destroyObjectProperties(this, chart);
  2397. };
  2398. /**
  2399. * See {@link Highcharts.Chart#removeAnnotation}.
  2400. * @private
  2401. */
  2402. Annotation.prototype.remove = function () {
  2403. // Let chart.update() remove annoations on demand
  2404. return this.chart.removeAnnotation(this);
  2405. };
  2406. /**
  2407. * Updates an annotation.
  2408. *
  2409. * @function Highcharts.Annotation#update
  2410. *
  2411. * @param {Partial<Highcharts.AnnotationsOptions>} userOptions
  2412. * New user options for the annotation.
  2413. *
  2414. * @return {void}
  2415. */
  2416. Annotation.prototype.update = function (userOptions, redraw) {
  2417. var chart = this.chart, labelsAndShapes = this.getLabelsAndShapesOptions(this.userOptions, userOptions), userOptionsIndex = chart.annotations.indexOf(this), options = merge(true, this.userOptions, userOptions);
  2418. options.labels = labelsAndShapes.labels;
  2419. options.shapes = labelsAndShapes.shapes;
  2420. this.destroy();
  2421. this.constructor(chart, options);
  2422. // Update options in chart options, used in exporting (#9767):
  2423. chart.options.annotations[userOptionsIndex] = options;
  2424. this.isUpdating = true;
  2425. if (pick(redraw, true)) {
  2426. chart.redraw();
  2427. }
  2428. fireEvent(this, 'afterUpdate');
  2429. this.isUpdating = false;
  2430. };
  2431. /* *************************************************************
  2432. * ITEM SECTION
  2433. * Contains methods for handling a single item in an annotation
  2434. **************************************************************** */
  2435. /**
  2436. * Initialisation of a single shape
  2437. * @private
  2438. * @param {Object} shapeOptions - a confg object for a single shape
  2439. */
  2440. Annotation.prototype.initShape = function (shapeOptions, index) {
  2441. var options = merge(this.options.shapeOptions, {
  2442. controlPointOptions: this.options.controlPointOptions
  2443. }, shapeOptions), shape = new Annotation.shapesMap[options.type](this, options, index);
  2444. shape.itemType = 'shape';
  2445. this.shapes.push(shape);
  2446. return shape;
  2447. };
  2448. /**
  2449. * Initialisation of a single label
  2450. * @private
  2451. */
  2452. Annotation.prototype.initLabel = function (labelOptions, index) {
  2453. var options = merge(this.options.labelOptions, {
  2454. controlPointOptions: this.options.controlPointOptions
  2455. }, labelOptions), label = new ControllableLabel(this, options, index);
  2456. label.itemType = 'label';
  2457. this.labels.push(label);
  2458. return label;
  2459. };
  2460. /**
  2461. * Redraw a single item.
  2462. * @private
  2463. * @param {Annotation.Label|Annotation.Shape} item
  2464. * @param {boolean} [animation]
  2465. */
  2466. Annotation.prototype.redrawItem = function (item, animation) {
  2467. item.linkPoints();
  2468. if (!item.shouldBeDrawn()) {
  2469. this.destroyItem(item);
  2470. }
  2471. else {
  2472. if (!item.graphic) {
  2473. this.renderItem(item);
  2474. }
  2475. item.redraw(pick(animation, true) && item.graphic.placed);
  2476. if (item.points.length) {
  2477. this.adjustVisibility(item);
  2478. }
  2479. }
  2480. };
  2481. /**
  2482. * Hide or show annotaiton attached to points.
  2483. * @private
  2484. * @param {Annotation.Label|Annotation.Shape} item
  2485. */
  2486. Annotation.prototype.adjustVisibility = function (item) {
  2487. var hasVisiblePoints = false, label = item.graphic;
  2488. item.points.forEach(function (point) {
  2489. if (point.series.visible !== false &&
  2490. point.visible !== false) {
  2491. hasVisiblePoints = true;
  2492. }
  2493. });
  2494. if (!hasVisiblePoints) {
  2495. label.hide();
  2496. }
  2497. else if (label.visibility === 'hidden') {
  2498. label.show();
  2499. }
  2500. };
  2501. /**
  2502. * Destroy a single item.
  2503. * @private
  2504. * @param {Annotation.Label|Annotation.Shape} item
  2505. */
  2506. Annotation.prototype.destroyItem = function (item) {
  2507. // erase from shapes or labels array
  2508. erase(this[item.itemType + 's'], item);
  2509. item.destroy();
  2510. };
  2511. /**
  2512. * @private
  2513. */
  2514. Annotation.prototype.renderItem = function (item) {
  2515. item.render(item.itemType === 'label' ?
  2516. this.labelsGroup :
  2517. this.shapesGroup);
  2518. };
  2519. /**
  2520. * @private
  2521. */
  2522. Annotation.ControlPoint = ControlPoint;
  2523. /**
  2524. * @private
  2525. */
  2526. Annotation.MockPoint = MockPoint;
  2527. /**
  2528. * An object uses for mapping between a shape type and a constructor.
  2529. * To add a new shape type extend this object with type name as a key
  2530. * and a constructor as its value.
  2531. */
  2532. Annotation.shapesMap = {
  2533. 'rect': ControllableRect,
  2534. 'circle': ControllableCircle,
  2535. 'path': ControllablePath,
  2536. 'image': ControllableImage
  2537. };
  2538. /**
  2539. * @private
  2540. */
  2541. Annotation.types = {};
  2542. return Annotation;
  2543. }());
  2544. merge(true, Annotation.prototype, ControllableMixin, EventEmitterMixin,
  2545. // restore original Annotation implementation after mixin overwrite
  2546. merge(Annotation.prototype,
  2547. /** @lends Highcharts.Annotation# */
  2548. {
  2549. /**
  2550. * List of events for `annotation.options.events` that should not be
  2551. * added to `annotation.graphic` but to the `annotation`.
  2552. *
  2553. * @private
  2554. * @type {Array<string>}
  2555. */
  2556. nonDOMEvents: ['add', 'afterUpdate', 'drag', 'remove'],
  2557. /**
  2558. * A basic type of an annotation. It allows to add custom labels
  2559. * or shapes. The items can be tied to points, axis coordinates
  2560. * or chart pixel coordinates.
  2561. *
  2562. * @sample highcharts/annotations/basic/
  2563. * Basic annotations
  2564. * @sample highcharts/demo/annotations/
  2565. * Advanced annotations
  2566. * @sample highcharts/css/annotations
  2567. * Styled mode
  2568. * @sample highcharts/annotations-advanced/controllable
  2569. * Controllable items
  2570. * @sample {highstock} stock/annotations/fibonacci-retracements
  2571. * Custom annotation, Fibonacci retracement
  2572. *
  2573. * @type {Array<*>}
  2574. * @since 6.0.0
  2575. * @requires modules/annotations
  2576. * @optionparent annotations
  2577. *
  2578. * @private
  2579. */
  2580. defaultOptions: {
  2581. /**
  2582. * Sets an ID for an annotation. Can be user later when
  2583. * removing an annotation in [Chart#removeAnnotation(id)](
  2584. * /class-reference/Highcharts.Chart#removeAnnotation) method.
  2585. *
  2586. * @type {number|string}
  2587. * @apioption annotations.id
  2588. */
  2589. /**
  2590. * Whether the annotation is visible.
  2591. *
  2592. * @sample highcharts/annotations/visible/
  2593. * Set annotation visibility
  2594. */
  2595. visible: true,
  2596. /**
  2597. * Allow an annotation to be draggable by a user. Possible
  2598. * values are `'x'`, `'xy'`, `'y'` and `''` (disabled).
  2599. *
  2600. * @sample highcharts/annotations/draggable/
  2601. * Annotations draggable: 'xy'
  2602. *
  2603. * @type {Highcharts.AnnotationDraggableValue}
  2604. */
  2605. draggable: 'xy',
  2606. /**
  2607. * Options for annotation's labels. Each label inherits options
  2608. * from the labelOptions object. An option from the labelOptions
  2609. * can be overwritten by config for a specific label.
  2610. *
  2611. * @requires modules/annotations
  2612. */
  2613. labelOptions: {
  2614. /**
  2615. * The alignment of the annotation's label. If right,
  2616. * the right side of the label should be touching the point.
  2617. *
  2618. * @sample highcharts/annotations/label-position/
  2619. * Set labels position
  2620. *
  2621. * @type {Highcharts.AlignValue}
  2622. */
  2623. align: 'center',
  2624. /**
  2625. * Whether to allow the annotation's labels to overlap.
  2626. * To make the labels less sensitive for overlapping,
  2627. * the can be set to 0.
  2628. *
  2629. * @sample highcharts/annotations/tooltip-like/
  2630. * Hide overlapping labels
  2631. */
  2632. allowOverlap: false,
  2633. /**
  2634. * The background color or gradient for the annotation's
  2635. * label.
  2636. *
  2637. * @sample highcharts/annotations/label-presentation/
  2638. * Set labels graphic options
  2639. *
  2640. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
  2641. */
  2642. backgroundColor: 'rgba(0, 0, 0, 0.75)',
  2643. /**
  2644. * The border color for the annotation's label.
  2645. *
  2646. * @sample highcharts/annotations/label-presentation/
  2647. * Set labels graphic options
  2648. *
  2649. * @type {Highcharts.ColorString}
  2650. */
  2651. borderColor: 'black',
  2652. /**
  2653. * The border radius in pixels for the annotaiton's label.
  2654. *
  2655. * @sample highcharts/annotations/label-presentation/
  2656. * Set labels graphic options
  2657. */
  2658. borderRadius: 3,
  2659. /**
  2660. * The border width in pixels for the annotation's label
  2661. *
  2662. * @sample highcharts/annotations/label-presentation/
  2663. * Set labels graphic options
  2664. */
  2665. borderWidth: 1,
  2666. /**
  2667. * A class name for styling by CSS.
  2668. *
  2669. * @sample highcharts/css/annotations
  2670. * Styled mode annotations
  2671. *
  2672. * @since 6.0.5
  2673. */
  2674. className: '',
  2675. /**
  2676. * Whether to hide the annotation's label
  2677. * that is outside the plot area.
  2678. *
  2679. * @sample highcharts/annotations/label-crop-overflow/
  2680. * Crop or justify labels
  2681. */
  2682. crop: false,
  2683. /**
  2684. * The label's pixel distance from the point.
  2685. *
  2686. * @sample highcharts/annotations/label-position/
  2687. * Set labels position
  2688. *
  2689. * @type {number}
  2690. * @apioption annotations.labelOptions.distance
  2691. */
  2692. /**
  2693. * A
  2694. * [format](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting)
  2695. * string for the data label.
  2696. *
  2697. * @see [plotOptions.series.dataLabels.format](plotOptions.series.dataLabels.format.html)
  2698. *
  2699. * @sample highcharts/annotations/label-text/
  2700. * Set labels text
  2701. *
  2702. * @type {string}
  2703. * @apioption annotations.labelOptions.format
  2704. */
  2705. /**
  2706. * Alias for the format option.
  2707. *
  2708. * @see [format](annotations.labelOptions.format.html)
  2709. *
  2710. * @sample highcharts/annotations/label-text/
  2711. * Set labels text
  2712. *
  2713. * @type {string}
  2714. * @apioption annotations.labelOptions.text
  2715. */
  2716. /**
  2717. * Callback JavaScript function to format the annotation's
  2718. * label. Note that if a `format` or `text` are defined,
  2719. * the format or text take precedence and the formatter is
  2720. * ignored. `This` refers to a point object.
  2721. *
  2722. * @sample highcharts/annotations/label-text/
  2723. * Set labels text
  2724. *
  2725. * @type {Highcharts.FormatterCallbackFunction<Highcharts.Point>}
  2726. * @default function () { return defined(this.y) ? this.y : 'Annotation label'; }
  2727. */
  2728. formatter: function () {
  2729. return defined(this.y) ? this.y : 'Annotation label';
  2730. },
  2731. /**
  2732. * How to handle the annotation's label that flow outside
  2733. * the plot area. The justify option aligns the label inside
  2734. * the plot area.
  2735. *
  2736. * @sample highcharts/annotations/label-crop-overflow/
  2737. * Crop or justify labels
  2738. *
  2739. * @validvalue ["allow", "justify"]
  2740. */
  2741. overflow: 'justify',
  2742. /**
  2743. * When either the borderWidth or the backgroundColor is
  2744. * set, this is the padding within the box.
  2745. *
  2746. * @sample highcharts/annotations/label-presentation/
  2747. * Set labels graphic options
  2748. */
  2749. padding: 5,
  2750. /**
  2751. * The shadow of the box. The shadow can be an object
  2752. * configuration containing `color`, `offsetX`, `offsetY`,
  2753. * `opacity` and `width`.
  2754. *
  2755. * @sample highcharts/annotations/label-presentation/
  2756. * Set labels graphic options
  2757. *
  2758. * @type {boolean|Highcharts.ShadowOptionsObject}
  2759. */
  2760. shadow: false,
  2761. /**
  2762. * The name of a symbol to use for the border around the
  2763. * label. Symbols are predefined functions on the Renderer
  2764. * object.
  2765. *
  2766. * @sample highcharts/annotations/shapes/
  2767. * Available shapes for labels
  2768. */
  2769. shape: 'callout',
  2770. /**
  2771. * Styles for the annotation's label.
  2772. *
  2773. * @see [plotOptions.series.dataLabels.style](plotOptions.series.dataLabels.style.html)
  2774. *
  2775. * @sample highcharts/annotations/label-presentation/
  2776. * Set labels graphic options
  2777. *
  2778. * @type {Highcharts.CSSObject}
  2779. */
  2780. style: {
  2781. /** @ignore */
  2782. fontSize: '11px',
  2783. /** @ignore */
  2784. fontWeight: 'normal',
  2785. /** @ignore */
  2786. color: 'contrast'
  2787. },
  2788. /**
  2789. * Whether to [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html)
  2790. * to render the annotation's label.
  2791. */
  2792. useHTML: false,
  2793. /**
  2794. * The vertical alignment of the annotation's label.
  2795. *
  2796. * @sample highcharts/annotations/label-position/
  2797. * Set labels position
  2798. *
  2799. * @type {Highcharts.VerticalAlignValue}
  2800. */
  2801. verticalAlign: 'bottom',
  2802. /**
  2803. * The x position offset of the label relative to the point.
  2804. * Note that if a `distance` is defined, the distance takes
  2805. * precedence over `x` and `y` options.
  2806. *
  2807. * @sample highcharts/annotations/label-position/
  2808. * Set labels position
  2809. */
  2810. x: 0,
  2811. /**
  2812. * The y position offset of the label relative to the point.
  2813. * Note that if a `distance` is defined, the distance takes
  2814. * precedence over `x` and `y` options.
  2815. *
  2816. * @sample highcharts/annotations/label-position/
  2817. * Set labels position
  2818. */
  2819. y: -16
  2820. },
  2821. /**
  2822. * An array of labels for the annotation. For options that apply
  2823. * to multiple labels, they can be added to the
  2824. * [labelOptions](annotations.labelOptions.html).
  2825. *
  2826. * @type {Array<*>}
  2827. * @extends annotations.labelOptions
  2828. * @apioption annotations.labels
  2829. */
  2830. /**
  2831. * This option defines the point to which the label will be
  2832. * connected. It can be either the point which exists in the
  2833. * series - it is referenced by the point's id - or a new point
  2834. * with defined x, y properties and optionally axes.
  2835. *
  2836. * @sample highcharts/annotations/mock-point/
  2837. * Attach annotation to a mock point
  2838. *
  2839. * @declare Highcharts.AnnotationMockPointOptionsObject
  2840. * @type {string|*}
  2841. * @requires modules/annotations
  2842. * @apioption annotations.labels.point
  2843. */
  2844. /**
  2845. * The x position of the point. Units can be either in axis
  2846. * or chart pixel coordinates.
  2847. *
  2848. * @type {number}
  2849. * @apioption annotations.labels.point.x
  2850. */
  2851. /**
  2852. * The y position of the point. Units can be either in axis
  2853. * or chart pixel coordinates.
  2854. *
  2855. * @type {number}
  2856. * @apioption annotations.labels.point.y
  2857. */
  2858. /**
  2859. * This number defines which xAxis the point is connected to.
  2860. * It refers to either the axis id or the index of the axis in
  2861. * the xAxis array. If the option is not configured or the axis
  2862. * is not found the point's x coordinate refers to the chart
  2863. * pixels.
  2864. *
  2865. * @type {number|string|null}
  2866. * @apioption annotations.labels.point.xAxis
  2867. */
  2868. /**
  2869. * This number defines which yAxis the point is connected to.
  2870. * It refers to either the axis id or the index of the axis in
  2871. * the yAxis array. If the option is not configured or the axis
  2872. * is not found the point's y coordinate refers to the chart
  2873. * pixels.
  2874. *
  2875. * @type {number|string|null}
  2876. * @apioption annotations.labels.point.yAxis
  2877. */
  2878. /**
  2879. * An array of shapes for the annotation. For options that apply
  2880. * to multiple shapes, then can be added to the
  2881. * [shapeOptions](annotations.shapeOptions.html).
  2882. *
  2883. * @type {Array<*>}
  2884. * @extends annotations.shapeOptions
  2885. * @apioption annotations.shapes
  2886. */
  2887. /**
  2888. * This option defines the point to which the shape will be
  2889. * connected. It can be either the point which exists in the
  2890. * series - it is referenced by the point's id - or a new point
  2891. * with defined x, y properties and optionally axes.
  2892. *
  2893. * @declare Highcharts.AnnotationMockPointOptionsObject
  2894. * @type {string|Highcharts.AnnotationMockPointOptionsObject}
  2895. * @extends annotations.labels.point
  2896. * @apioption annotations.shapes.point
  2897. */
  2898. /**
  2899. * An array of points for the shape. This option is available
  2900. * for shapes which can use multiple points such as path. A
  2901. * point can be either a point object or a point's id.
  2902. *
  2903. * @see [annotations.shapes.point](annotations.shapes.point.html)
  2904. *
  2905. * @declare Highcharts.AnnotationMockPointOptionsObject
  2906. * @type {Array<string|*>}
  2907. * @extends annotations.labels.point
  2908. * @apioption annotations.shapes.points
  2909. */
  2910. /**
  2911. * The URL for an image to use as the annotation shape. Note,
  2912. * type has to be set to `'image'`.
  2913. *
  2914. * @see [annotations.shapes.type](annotations.shapes.type)
  2915. * @sample highcharts/annotations/shape-src/
  2916. * Define a marker image url for annotations
  2917. *
  2918. * @type {string}
  2919. * @apioption annotations.shapes.src
  2920. */
  2921. /**
  2922. * Id of the marker which will be drawn at the final vertex of
  2923. * the path. Custom markers can be defined in defs property.
  2924. *
  2925. * @see [defs.markers](defs.markers.html)
  2926. *
  2927. * @sample highcharts/annotations/custom-markers/
  2928. * Define a custom marker for annotations
  2929. *
  2930. * @type {string}
  2931. * @apioption annotations.shapes.markerEnd
  2932. */
  2933. /**
  2934. * Id of the marker which will be drawn at the first vertex of
  2935. * the path. Custom markers can be defined in defs property.
  2936. *
  2937. * @see [defs.markers](defs.markers.html)
  2938. *
  2939. * @sample {highcharts} highcharts/annotations/custom-markers/
  2940. * Define a custom marker for annotations
  2941. *
  2942. * @type {string}
  2943. * @apioption annotations.shapes.markerStart
  2944. */
  2945. /**
  2946. * Options for annotation's shapes. Each shape inherits options
  2947. * from the shapeOptions object. An option from the shapeOptions
  2948. * can be overwritten by config for a specific shape.
  2949. *
  2950. * @requires modules/annotations
  2951. */
  2952. shapeOptions: {
  2953. /**
  2954. * The width of the shape.
  2955. *
  2956. * @sample highcharts/annotations/shape/
  2957. * Basic shape annotation
  2958. *
  2959. * @type {number}
  2960. * @apioption annotations.shapeOptions.width
  2961. **/
  2962. /**
  2963. * The height of the shape.
  2964. *
  2965. * @sample highcharts/annotations/shape/
  2966. * Basic shape annotation
  2967. *
  2968. * @type {number}
  2969. * @apioption annotations.shapeOptions.height
  2970. */
  2971. /**
  2972. * The type of the shape, e.g. circle or rectangle.
  2973. *
  2974. * @sample highcharts/annotations/shape/
  2975. * Basic shape annotation
  2976. *
  2977. * @type {string}
  2978. * @default 'rect'
  2979. * @apioption annotations.shapeOptions.type
  2980. */
  2981. /**
  2982. * The URL for an image to use as the annotation shape.
  2983. * Note, type has to be set to `'image'`.
  2984. *
  2985. * @see [annotations.shapeOptions.type](annotations.shapeOptions.type)
  2986. * @sample highcharts/annotations/shape-src/
  2987. * Define a marker image url for annotations
  2988. *
  2989. * @type {string}
  2990. * @apioption annotations.shapeOptions.src
  2991. */
  2992. /**
  2993. * Name of the dash style to use for the shape's stroke.
  2994. *
  2995. * @sample {highcharts} highcharts/plotoptions/series-dashstyle-all/
  2996. * Possible values demonstrated
  2997. *
  2998. * @type {Highcharts.DashStyleValue}
  2999. * @apioption annotations.shapeOptions.dashStyle
  3000. */
  3001. /**
  3002. * The color of the shape's stroke.
  3003. *
  3004. * @sample highcharts/annotations/shape/
  3005. * Basic shape annotation
  3006. *
  3007. * @type {Highcharts.ColorString}
  3008. */
  3009. stroke: 'rgba(0, 0, 0, 0.75)',
  3010. /**
  3011. * The pixel stroke width of the shape.
  3012. *
  3013. * @sample highcharts/annotations/shape/
  3014. * Basic shape annotation
  3015. */
  3016. strokeWidth: 1,
  3017. /**
  3018. * The color of the shape's fill.
  3019. *
  3020. * @sample highcharts/annotations/shape/
  3021. * Basic shape annotation
  3022. *
  3023. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
  3024. */
  3025. fill: 'rgba(0, 0, 0, 0.75)',
  3026. /**
  3027. * The radius of the shape.
  3028. *
  3029. * @sample highcharts/annotations/shape/
  3030. * Basic shape annotation
  3031. */
  3032. r: 0,
  3033. /**
  3034. * Defines additional snapping area around an annotation
  3035. * making this annotation to focus. Defined in pixels.
  3036. */
  3037. snap: 2
  3038. },
  3039. /**
  3040. * Options for annotation's control points. Each control point
  3041. * inherits options from controlPointOptions object.
  3042. * Options from the controlPointOptions can be overwritten
  3043. * by options in a specific control point.
  3044. *
  3045. * @declare Highcharts.AnnotationControlPointOptionsObject
  3046. * @requires modules/annotations
  3047. * @apioption annotations.controlPointOptions
  3048. */
  3049. controlPointOptions: {
  3050. /**
  3051. * @type {Highcharts.AnnotationControlPointPositionerFunction}
  3052. * @apioption annotations.controlPointOptions.positioner
  3053. */
  3054. symbol: 'circle',
  3055. width: 10,
  3056. height: 10,
  3057. style: {
  3058. stroke: 'black',
  3059. 'stroke-width': 2,
  3060. fill: 'white'
  3061. },
  3062. visible: false,
  3063. events: {}
  3064. },
  3065. /**
  3066. * Event callback when annotation is added to the chart.
  3067. *
  3068. * @type {Highcharts.EventCallbackFunction<Highcharts.Annotation>}
  3069. * @since 7.1.0
  3070. * @apioption annotations.events.add
  3071. */
  3072. /**
  3073. * Event callback when annotation is updated (e.g. drag and
  3074. * droppped or resized by control points).
  3075. *
  3076. * @type {Highcharts.EventCallbackFunction<Highcharts.Annotation>}
  3077. * @since 7.1.0
  3078. * @apioption annotations.events.afterUpdate
  3079. */
  3080. /**
  3081. * Event callback when annotation is removed from the chart.
  3082. *
  3083. * @type {Highcharts.EventCallbackFunction<Highcharts.Annotation>}
  3084. * @since 7.1.0
  3085. * @apioption annotations.events.remove
  3086. */
  3087. /**
  3088. * Events available in annotations.
  3089. *
  3090. * @requires modules/annotations
  3091. */
  3092. events: {},
  3093. /**
  3094. * The Z index of the annotation.
  3095. */
  3096. zIndex: 6
  3097. }
  3098. }));
  3099. H.extendAnnotation = function (Constructor, BaseConstructor, prototype, defaultOptions) {
  3100. BaseConstructor = BaseConstructor || Annotation;
  3101. merge(true, Constructor.prototype, BaseConstructor.prototype, prototype);
  3102. Constructor.prototype.defaultOptions = merge(Constructor.prototype.defaultOptions, defaultOptions || {});
  3103. };
  3104. /* *********************************************************************
  3105. *
  3106. * EXTENDING CHART PROTOTYPE
  3107. *
  3108. ******************************************************************** */
  3109. extend(chartProto, /** @lends Highcharts.Chart# */ {
  3110. initAnnotation: function (userOptions) {
  3111. var Constructor = Annotation.types[userOptions.type] || Annotation, annotation = new Constructor(this, userOptions);
  3112. this.annotations.push(annotation);
  3113. return annotation;
  3114. },
  3115. /**
  3116. * Add an annotation to the chart after render time.
  3117. *
  3118. * @param {Highcharts.AnnotationsOptions} options
  3119. * The annotation options for the new, detailed annotation.
  3120. * @param {boolean} [redraw]
  3121. *
  3122. * @return {Highcharts.Annotation} - The newly generated annotation.
  3123. */
  3124. addAnnotation: function (userOptions, redraw) {
  3125. var annotation = this.initAnnotation(userOptions);
  3126. this.options.annotations.push(annotation.options);
  3127. if (pick(redraw, true)) {
  3128. annotation.redraw();
  3129. }
  3130. return annotation;
  3131. },
  3132. /**
  3133. * Remove an annotation from the chart.
  3134. *
  3135. * @param {number|string|Highcharts.Annotation} idOrAnnotation
  3136. * The annotation's id or direct annotation object.
  3137. */
  3138. removeAnnotation: function (idOrAnnotation) {
  3139. var annotations = this.annotations, annotation = idOrAnnotation.coll === 'annotations' ?
  3140. idOrAnnotation :
  3141. find(annotations, function (annotation) {
  3142. return annotation.options.id === idOrAnnotation;
  3143. });
  3144. if (annotation) {
  3145. fireEvent(annotation, 'remove');
  3146. erase(this.options.annotations, annotation.options);
  3147. erase(annotations, annotation);
  3148. annotation.destroy();
  3149. }
  3150. },
  3151. drawAnnotations: function () {
  3152. this.plotBoxClip.attr(this.plotBox);
  3153. this.annotations.forEach(function (annotation) {
  3154. annotation.redraw();
  3155. });
  3156. }
  3157. });
  3158. // Let chart.update() update annotations
  3159. chartProto.collectionsWithUpdate.push('annotations');
  3160. // Let chart.update() create annoations on demand
  3161. chartProto.collectionsWithInit.annotations = [chartProto.addAnnotation];
  3162. chartProto.callbacks.push(function (chart) {
  3163. chart.annotations = [];
  3164. if (!chart.options.annotations) {
  3165. chart.options.annotations = [];
  3166. }
  3167. chart.plotBoxClip = this.renderer.clipRect(this.plotBox);
  3168. chart.controlPointsGroup = chart.renderer
  3169. .g('control-points')
  3170. .attr({ zIndex: 99 })
  3171. .clip(chart.plotBoxClip)
  3172. .add();
  3173. chart.options.annotations.forEach(function (annotationOptions, i) {
  3174. var annotation = chart.initAnnotation(annotationOptions);
  3175. chart.options.annotations[i] = annotation.options;
  3176. });
  3177. chart.drawAnnotations();
  3178. addEvent(chart, 'redraw', chart.drawAnnotations);
  3179. addEvent(chart, 'destroy', function () {
  3180. chart.plotBoxClip.destroy();
  3181. chart.controlPointsGroup.destroy();
  3182. });
  3183. });
  3184. wrap(Pointer.prototype, 'onContainerMouseDown', function (proceed) {
  3185. if (!this.chart.hasDraggedAnnotation) {
  3186. proceed.apply(this, Array.prototype.slice.call(arguments, 1));
  3187. }
  3188. });
  3189. H.Annotation = Annotation;
  3190. return Annotation;
  3191. });
  3192. _registerModule(_modules, 'annotations/types/BasicAnnotation.js', [_modules['annotations/annotations.src.js'], _modules['annotations/MockPoint.js'], _modules['parts/Utilities.js']], function (Annotation, MockPoint, U) {
  3193. /* *
  3194. *
  3195. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  3196. *
  3197. * */
  3198. var __extends = (this && this.__extends) || (function () {
  3199. var extendStatics = function (d, b) {
  3200. extendStatics = Object.setPrototypeOf ||
  3201. ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
  3202. function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
  3203. return extendStatics(d, b);
  3204. };
  3205. return function (d, b) {
  3206. extendStatics(d, b);
  3207. function __() { this.constructor = d; }
  3208. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  3209. };
  3210. })();
  3211. var merge = U.merge;
  3212. /* eslint-disable no-invalid-this */
  3213. var BasicAnnotation = /** @class */ (function (_super) {
  3214. __extends(BasicAnnotation, _super);
  3215. /* *
  3216. *
  3217. * Constructors
  3218. *
  3219. * */
  3220. function BasicAnnotation(chart, options) {
  3221. return _super.call(this, chart, options) || this;
  3222. }
  3223. /* *
  3224. *
  3225. * Functions
  3226. *
  3227. * */
  3228. BasicAnnotation.prototype.addControlPoints = function () {
  3229. var options = this.options, controlPoints = BasicAnnotation.basicControlPoints, langKey = options.langKey, optionsGroup = options.labels || options.shapes;
  3230. optionsGroup.forEach(function (group) {
  3231. if (langKey) {
  3232. // @todo langKey === 'label' / 'circle' / 'rectangle' ???
  3233. group.controlPoints = controlPoints[langKey];
  3234. }
  3235. });
  3236. };
  3237. /* *
  3238. *
  3239. * Static Properties
  3240. *
  3241. * */
  3242. BasicAnnotation.basicControlPoints = {
  3243. label: [{
  3244. symbol: 'triangle-down',
  3245. positioner: function (target) {
  3246. if (!target.graphic.placed) {
  3247. return {
  3248. x: 0,
  3249. y: -9e7
  3250. };
  3251. }
  3252. var xy = MockPoint
  3253. .pointToPixels(target.points[0]);
  3254. return {
  3255. x: xy.x - this.graphic.width / 2,
  3256. y: xy.y - this.graphic.height / 2
  3257. };
  3258. },
  3259. // TRANSLATE POINT/ANCHOR
  3260. events: {
  3261. drag: function (e, target) {
  3262. var xy = this.mouseMoveToTranslation(e);
  3263. target.translatePoint(xy.x, xy.y);
  3264. target.annotation.userOptions.labels[0].point =
  3265. target.options.point;
  3266. target.redraw(false);
  3267. }
  3268. }
  3269. }, {
  3270. symbol: 'square',
  3271. positioner: function (target) {
  3272. if (!target.graphic.placed) {
  3273. return {
  3274. x: 0,
  3275. y: -9e7
  3276. };
  3277. }
  3278. return {
  3279. x: target.graphic.alignAttr.x -
  3280. this.graphic.width / 2,
  3281. y: target.graphic.alignAttr.y -
  3282. this.graphic.height / 2
  3283. };
  3284. },
  3285. // TRANSLATE POSITION WITHOUT CHANGING THE
  3286. // ANCHOR
  3287. events: {
  3288. drag: function (e, target) {
  3289. var xy = this.mouseMoveToTranslation(e);
  3290. target.translate(xy.x, xy.y);
  3291. target.annotation.userOptions.labels[0].point =
  3292. target.options.point;
  3293. target.redraw(false);
  3294. }
  3295. }
  3296. }],
  3297. rectangle: [{
  3298. positioner: function (annotation) {
  3299. var xy = MockPoint
  3300. .pointToPixels(annotation.points[2]);
  3301. return {
  3302. x: xy.x - 4,
  3303. y: xy.y - 4
  3304. };
  3305. },
  3306. events: {
  3307. drag: function (e, target) {
  3308. var annotation = target.annotation, coords = this.chart.pointer.getCoordinates(e), x = coords.xAxis[0].value, y = coords.yAxis[0].value, points = target.options.points;
  3309. // Top right point
  3310. points[1].x = x;
  3311. // Bottom right point (cursor position)
  3312. points[2].x = x;
  3313. points[2].y = y;
  3314. // Bottom left
  3315. points[3].y = y;
  3316. annotation.userOptions.shapes[0].points =
  3317. target.options.points;
  3318. annotation.redraw(false);
  3319. }
  3320. }
  3321. }],
  3322. circle: [{
  3323. positioner: function (target) {
  3324. var xy = MockPoint.pointToPixels(target.points[0]), r = target.options.r;
  3325. return {
  3326. x: xy.x + r * Math.cos(Math.PI / 4) -
  3327. this.graphic.width / 2,
  3328. y: xy.y + r * Math.sin(Math.PI / 4) -
  3329. this.graphic.height / 2
  3330. };
  3331. },
  3332. events: {
  3333. // TRANSFORM RADIUS ACCORDING TO Y
  3334. // TRANSLATION
  3335. drag: function (e, target) {
  3336. var annotation = target.annotation, position = this.mouseMoveToTranslation(e);
  3337. target.setRadius(Math.max(target.options.r +
  3338. position.y /
  3339. Math.sin(Math.PI / 4), 5));
  3340. annotation.userOptions.shapes[0].r = target.options.r;
  3341. annotation.userOptions.shapes[0].point =
  3342. target.options.point;
  3343. target.redraw(false);
  3344. }
  3345. }
  3346. }]
  3347. };
  3348. return BasicAnnotation;
  3349. }(Annotation));
  3350. BasicAnnotation.prototype.defaultOptions = merge(Annotation.prototype.defaultOptions, {});
  3351. Annotation.types.basicAnnotation = BasicAnnotation;
  3352. return BasicAnnotation;
  3353. });
  3354. _registerModule(_modules, 'annotations/types/CrookedLine.js', [_modules['annotations/annotations.src.js'], _modules['annotations/ControlPoint.js'], _modules['annotations/MockPoint.js'], _modules['parts/Utilities.js']], function (Annotation, ControlPoint, MockPoint, U) {
  3355. /* *
  3356. *
  3357. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  3358. *
  3359. * */
  3360. var __extends = (this && this.__extends) || (function () {
  3361. var extendStatics = function (d, b) {
  3362. extendStatics = Object.setPrototypeOf ||
  3363. ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
  3364. function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
  3365. return extendStatics(d, b);
  3366. };
  3367. return function (d, b) {
  3368. extendStatics(d, b);
  3369. function __() { this.constructor = d; }
  3370. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  3371. };
  3372. })();
  3373. var merge = U.merge;
  3374. /* eslint-disable no-invalid-this, valid-jsdoc */
  3375. var CrookedLine = /** @class */ (function (_super) {
  3376. __extends(CrookedLine, _super);
  3377. /* *
  3378. *
  3379. * Constructors
  3380. *
  3381. * */
  3382. function CrookedLine(chart, options) {
  3383. return _super.call(this, chart, options) || this;
  3384. }
  3385. /* *
  3386. *
  3387. * Functions
  3388. *
  3389. * */
  3390. /**
  3391. * Overrides default setter to get axes from typeOptions.
  3392. * @private
  3393. */
  3394. CrookedLine.prototype.setClipAxes = function () {
  3395. this.clipXAxis = this.chart.xAxis[this.options.typeOptions.xAxis];
  3396. this.clipYAxis = this.chart.yAxis[this.options.typeOptions.yAxis];
  3397. };
  3398. CrookedLine.prototype.getPointsOptions = function () {
  3399. var typeOptions = this.options.typeOptions;
  3400. return (typeOptions.points || []).map(function (pointOptions) {
  3401. pointOptions.xAxis = typeOptions.xAxis;
  3402. pointOptions.yAxis = typeOptions.yAxis;
  3403. return pointOptions;
  3404. });
  3405. };
  3406. CrookedLine.prototype.getControlPointsOptions = function () {
  3407. return this.getPointsOptions();
  3408. };
  3409. CrookedLine.prototype.addControlPoints = function () {
  3410. this.getControlPointsOptions().forEach(function (pointOptions, i) {
  3411. var controlPoint = new ControlPoint(this.chart, this, merge(this.options.controlPointOptions, pointOptions.controlPoint), i);
  3412. this.controlPoints.push(controlPoint);
  3413. pointOptions.controlPoint = controlPoint.options;
  3414. }, this);
  3415. };
  3416. CrookedLine.prototype.addShapes = function () {
  3417. var typeOptions = this.options.typeOptions, shape = this.initShape(merge(typeOptions.line, {
  3418. type: 'path',
  3419. points: this.points.map(function (_point, i) {
  3420. return function (target) {
  3421. return target.annotation.points[i];
  3422. };
  3423. })
  3424. }), false);
  3425. typeOptions.line = shape.options;
  3426. };
  3427. return CrookedLine;
  3428. }(Annotation));
  3429. CrookedLine.prototype.defaultOptions = merge(Annotation.prototype.defaultOptions,
  3430. /**
  3431. * A crooked line annotation.
  3432. *
  3433. * @sample highcharts/annotations-advanced/crooked-line/
  3434. * Crooked line
  3435. *
  3436. * @product highstock
  3437. * @optionparent annotations.crookedLine
  3438. */
  3439. {
  3440. /**
  3441. * @extends annotations.labelOptions
  3442. * @apioption annotations.crookedLine.labelOptions
  3443. */
  3444. /**
  3445. * @extends annotations.shapeOptions
  3446. * @apioption annotations.crookedLine.shapeOptions
  3447. */
  3448. /**
  3449. * Additional options for an annotation with the type.
  3450. */
  3451. typeOptions: {
  3452. /**
  3453. * This number defines which xAxis the point is connected to.
  3454. * It refers to either the axis id or the index of the axis
  3455. * in the xAxis array.
  3456. */
  3457. xAxis: 0,
  3458. /**
  3459. * This number defines which yAxis the point is connected to.
  3460. * It refers to either the axis id or the index of the axis
  3461. * in the xAxis array.
  3462. */
  3463. yAxis: 0,
  3464. /**
  3465. * @type {Array<*>}
  3466. * @apioption annotations.crookedLine.typeOptions.points
  3467. */
  3468. /**
  3469. * The x position of the point.
  3470. *
  3471. * @type {number}
  3472. * @apioption annotations.crookedLine.typeOptions.points.x
  3473. */
  3474. /**
  3475. * The y position of the point.
  3476. *
  3477. * @type {number}
  3478. * @apioption annotations.crookedLine.typeOptions.points.y
  3479. */
  3480. /**
  3481. * @type {number}
  3482. * @excluding positioner, events
  3483. * @apioption annotations.crookedLine.typeOptions.points.controlPoint
  3484. */
  3485. /**
  3486. * Line options.
  3487. *
  3488. * @excluding height, point, points, r, type, width
  3489. */
  3490. line: {
  3491. fill: 'none'
  3492. }
  3493. },
  3494. /**
  3495. * @excluding positioner, events
  3496. */
  3497. controlPointOptions: {
  3498. positioner: function (target) {
  3499. var graphic = this.graphic, xy = MockPoint.pointToPixels(target.points[this.index]);
  3500. return {
  3501. x: xy.x - graphic.width / 2,
  3502. y: xy.y - graphic.height / 2
  3503. };
  3504. },
  3505. events: {
  3506. drag: function (e, target) {
  3507. if (target.chart.isInsidePlot(e.chartX - target.chart.plotLeft, e.chartY - target.chart.plotTop)) {
  3508. var translation = this.mouseMoveToTranslation(e);
  3509. target.translatePoint(translation.x, translation.y, this.index);
  3510. // Update options:
  3511. target.options.typeOptions.points[this.index].x = target.points[this.index].x;
  3512. target.options.typeOptions.points[this.index].y = target.points[this.index].y;
  3513. target.redraw(false);
  3514. }
  3515. }
  3516. }
  3517. }
  3518. });
  3519. Annotation.types.crookedLine = CrookedLine;
  3520. return CrookedLine;
  3521. });
  3522. _registerModule(_modules, 'annotations/types/ElliottWave.js', [_modules['annotations/annotations.src.js'], _modules['annotations/types/CrookedLine.js'], _modules['parts/Utilities.js']], function (Annotation, CrookedLine, U) {
  3523. /* *
  3524. *
  3525. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  3526. *
  3527. * */
  3528. var __extends = (this && this.__extends) || (function () {
  3529. var extendStatics = function (d, b) {
  3530. extendStatics = Object.setPrototypeOf ||
  3531. ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
  3532. function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
  3533. return extendStatics(d, b);
  3534. };
  3535. return function (d, b) {
  3536. extendStatics(d, b);
  3537. function __() { this.constructor = d; }
  3538. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  3539. };
  3540. })();
  3541. var merge = U.merge;
  3542. /* eslint-disable no-invalid-this, valid-jsdoc */
  3543. var ElliottWave = /** @class */ (function (_super) {
  3544. __extends(ElliottWave, _super);
  3545. function ElliottWave(chart, options) {
  3546. return _super.call(this, chart, options) || this;
  3547. }
  3548. /* *
  3549. *
  3550. * Functions
  3551. *
  3552. * */
  3553. ElliottWave.prototype.addLabels = function () {
  3554. this.getPointsOptions().forEach(function (point, i) {
  3555. var typeOptions = this.options.typeOptions, label = this.initLabel(merge(point.label, {
  3556. text: typeOptions.labels[i],
  3557. point: function (target) {
  3558. return target.annotation.points[i];
  3559. }
  3560. }), false);
  3561. point.label = label.options;
  3562. }, this);
  3563. };
  3564. return ElliottWave;
  3565. }(CrookedLine));
  3566. ElliottWave.prototype.defaultOptions = merge(CrookedLine.prototype.defaultOptions,
  3567. /**
  3568. * An elliott wave annotation.
  3569. *
  3570. * @sample highcharts/annotations-advanced/elliott-wave/
  3571. * Elliott wave
  3572. *
  3573. * @extends annotations.crookedLine
  3574. * @product highstock
  3575. * @optionparent annotations.elliottWave
  3576. */
  3577. {
  3578. typeOptions: {
  3579. /**
  3580. * @extends annotations.crookedLine.labelOptions
  3581. * @apioption annotations.elliottWave.typeOptions.points.label
  3582. */
  3583. /**
  3584. * @ignore-options
  3585. */
  3586. labels: ['(0)', '(A)', '(B)', '(C)', '(D)', '(E)'],
  3587. line: {
  3588. strokeWidth: 1
  3589. }
  3590. },
  3591. labelOptions: {
  3592. align: 'center',
  3593. allowOverlap: true,
  3594. crop: true,
  3595. overflow: 'none',
  3596. type: 'rect',
  3597. backgroundColor: 'none',
  3598. borderWidth: 0,
  3599. y: -5
  3600. }
  3601. });
  3602. Annotation.types.elliottWave = ElliottWave;
  3603. return ElliottWave;
  3604. });
  3605. _registerModule(_modules, 'annotations/types/Tunnel.js', [_modules['annotations/annotations.src.js'], _modules['annotations/ControlPoint.js'], _modules['annotations/types/CrookedLine.js'], _modules['annotations/MockPoint.js'], _modules['parts/Utilities.js']], function (Annotation, ControlPoint, CrookedLine, MockPoint, U) {
  3606. /* *
  3607. *
  3608. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  3609. *
  3610. * */
  3611. var __extends = (this && this.__extends) || (function () {
  3612. var extendStatics = function (d, b) {
  3613. extendStatics = Object.setPrototypeOf ||
  3614. ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
  3615. function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
  3616. return extendStatics(d, b);
  3617. };
  3618. return function (d, b) {
  3619. extendStatics(d, b);
  3620. function __() { this.constructor = d; }
  3621. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  3622. };
  3623. })();
  3624. var merge = U.merge;
  3625. /* eslint-disable no-invalid-this, valid-jsdoc */
  3626. /**
  3627. * @private
  3628. */
  3629. function getSecondCoordinate(p1, p2, x) {
  3630. return (p2.y - p1.y) / (p2.x - p1.x) * (x - p1.x) + p1.y;
  3631. }
  3632. var Tunnel = /** @class */ (function (_super) {
  3633. __extends(Tunnel, _super);
  3634. /* *
  3635. *
  3636. * Constructors
  3637. *
  3638. * */
  3639. function Tunnel(chart, options) {
  3640. return _super.call(this, chart, options) || this;
  3641. }
  3642. /* *
  3643. *
  3644. * Functions
  3645. *
  3646. * */
  3647. Tunnel.prototype.getPointsOptions = function () {
  3648. var pointsOptions = CrookedLine.prototype.getPointsOptions.call(this);
  3649. pointsOptions[2] = this.heightPointOptions(pointsOptions[1]);
  3650. pointsOptions[3] = this.heightPointOptions(pointsOptions[0]);
  3651. return pointsOptions;
  3652. };
  3653. Tunnel.prototype.getControlPointsOptions = function () {
  3654. return this.getPointsOptions().slice(0, 2);
  3655. };
  3656. Tunnel.prototype.heightPointOptions = function (pointOptions) {
  3657. var heightPointOptions = merge(pointOptions), typeOptions = this.options.typeOptions;
  3658. heightPointOptions.y += typeOptions.height;
  3659. return heightPointOptions;
  3660. };
  3661. Tunnel.prototype.addControlPoints = function () {
  3662. CrookedLine.prototype.addControlPoints.call(this);
  3663. var options = this.options, typeOptions = options.typeOptions, controlPoint = new ControlPoint(this.chart, this, merge(options.controlPointOptions, typeOptions.heightControlPoint), 2);
  3664. this.controlPoints.push(controlPoint);
  3665. typeOptions.heightControlPoint = controlPoint.options;
  3666. };
  3667. Tunnel.prototype.addShapes = function () {
  3668. this.addLine();
  3669. this.addBackground();
  3670. };
  3671. Tunnel.prototype.addLine = function () {
  3672. var line = this.initShape(merge(this.options.typeOptions.line, {
  3673. type: 'path',
  3674. points: [
  3675. this.points[0],
  3676. this.points[1],
  3677. function (target) {
  3678. var pointOptions = MockPoint.pointToOptions(target.annotation.points[2]);
  3679. pointOptions.command = 'M';
  3680. return pointOptions;
  3681. },
  3682. this.points[3]
  3683. ]
  3684. }), false);
  3685. this.options.typeOptions.line = line.options;
  3686. };
  3687. Tunnel.prototype.addBackground = function () {
  3688. var background = this.initShape(merge(this.options.typeOptions.background, {
  3689. type: 'path',
  3690. points: this.points.slice()
  3691. }));
  3692. this.options.typeOptions.background = background.options;
  3693. };
  3694. /**
  3695. * Translate start or end ("left" or "right") side of the tunnel.
  3696. * @private
  3697. * @param {number} dx - the amount of x translation
  3698. * @param {number} dy - the amount of y translation
  3699. * @param {boolean} [end] - whether to translate start or end side
  3700. */
  3701. Tunnel.prototype.translateSide = function (dx, dy, end) {
  3702. var topIndex = Number(end), bottomIndex = topIndex === 0 ? 3 : 2;
  3703. this.translatePoint(dx, dy, topIndex);
  3704. this.translatePoint(dx, dy, bottomIndex);
  3705. };
  3706. /**
  3707. * Translate height of the tunnel.
  3708. * @private
  3709. * @param {number} dh - the amount of height translation
  3710. */
  3711. Tunnel.prototype.translateHeight = function (dh) {
  3712. this.translatePoint(0, dh, 2);
  3713. this.translatePoint(0, dh, 3);
  3714. this.options.typeOptions.height = this.points[3].y - this.points[0].y;
  3715. };
  3716. return Tunnel;
  3717. }(CrookedLine));
  3718. Tunnel.prototype.defaultOptions = merge(CrookedLine.prototype.defaultOptions,
  3719. /**
  3720. * A tunnel annotation.
  3721. *
  3722. * @extends annotations.crookedLine
  3723. * @sample highcharts/annotations-advanced/tunnel/
  3724. * Tunnel
  3725. * @product highstock
  3726. * @optionparent annotations.tunnel
  3727. */
  3728. {
  3729. typeOptions: {
  3730. xAxis: 0,
  3731. yAxis: 0,
  3732. /**
  3733. * Background options.
  3734. *
  3735. * @type {Object}
  3736. * @excluding height, point, points, r, type, width, markerEnd,
  3737. * markerStart
  3738. */
  3739. background: {
  3740. fill: 'rgba(130, 170, 255, 0.4)',
  3741. strokeWidth: 0
  3742. },
  3743. line: {
  3744. strokeWidth: 1
  3745. },
  3746. /**
  3747. * The height of the annotation in terms of yAxis.
  3748. */
  3749. height: -2,
  3750. /**
  3751. * Options for the control point which controls
  3752. * the annotation's height.
  3753. *
  3754. * @extends annotations.crookedLine.controlPointOptions
  3755. * @excluding positioner, events
  3756. */
  3757. heightControlPoint: {
  3758. positioner: function (target) {
  3759. var startXY = MockPoint.pointToPixels(target.points[2]), endXY = MockPoint.pointToPixels(target.points[3]), x = (startXY.x + endXY.x) / 2;
  3760. return {
  3761. x: x - this.graphic.width / 2,
  3762. y: getSecondCoordinate(startXY, endXY, x) -
  3763. this.graphic.height / 2
  3764. };
  3765. },
  3766. events: {
  3767. drag: function (e, target) {
  3768. if (target.chart.isInsidePlot(e.chartX - target.chart.plotLeft, e.chartY - target.chart.plotTop)) {
  3769. target.translateHeight(this.mouseMoveToTranslation(e).y);
  3770. target.redraw(false);
  3771. }
  3772. }
  3773. }
  3774. }
  3775. },
  3776. /**
  3777. * @extends annotations.crookedLine.controlPointOptions
  3778. * @excluding positioner, events
  3779. */
  3780. controlPointOptions: {
  3781. events: {
  3782. drag: function (e, target) {
  3783. if (target.chart.isInsidePlot(e.chartX - target.chart.plotLeft, e.chartY - target.chart.plotTop)) {
  3784. var translation = this.mouseMoveToTranslation(e);
  3785. target.translateSide(translation.x, translation.y, this.index);
  3786. target.redraw(false);
  3787. }
  3788. }
  3789. }
  3790. }
  3791. });
  3792. Annotation.types.tunnel = Tunnel;
  3793. return Tunnel;
  3794. });
  3795. _registerModule(_modules, 'annotations/types/InfinityLine.js', [_modules['annotations/annotations.src.js'], _modules['annotations/types/CrookedLine.js'], _modules['annotations/MockPoint.js'], _modules['parts/Utilities.js']], function (Annotation, CrookedLine, MockPoint, U) {
  3796. /* *
  3797. *
  3798. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  3799. *
  3800. * */
  3801. var __extends = (this && this.__extends) || (function () {
  3802. var extendStatics = function (d, b) {
  3803. extendStatics = Object.setPrototypeOf ||
  3804. ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
  3805. function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
  3806. return extendStatics(d, b);
  3807. };
  3808. return function (d, b) {
  3809. extendStatics(d, b);
  3810. function __() { this.constructor = d; }
  3811. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  3812. };
  3813. })();
  3814. var merge = U.merge;
  3815. /* eslint-disable no-invalid-this, valid-jsdoc */
  3816. var InfinityLine = /** @class */ (function (_super) {
  3817. __extends(InfinityLine, _super);
  3818. /* *
  3819. *
  3820. * Constructors
  3821. *
  3822. * */
  3823. function InfinityLine(chart, options) {
  3824. return _super.call(this, chart, options) || this;
  3825. }
  3826. /* *
  3827. *
  3828. * Static Functions
  3829. *
  3830. * */
  3831. InfinityLine.edgePoint = function (startIndex, endIndex) {
  3832. return function (target) {
  3833. var annotation = target.annotation, points = annotation.points, type = annotation.options.typeOptions.type;
  3834. if (type === 'horizontalLine') {
  3835. // Horizontal line has only one point,
  3836. // make a copy of it:
  3837. points = [
  3838. points[0],
  3839. new MockPoint(annotation.chart, points[0].target, {
  3840. x: points[0].x + 1,
  3841. y: points[0].y,
  3842. xAxis: points[0].options.xAxis,
  3843. yAxis: points[0].options.yAxis
  3844. })
  3845. ];
  3846. }
  3847. else if (type === 'verticalLine') {
  3848. // The same for verticalLine type:
  3849. points = [
  3850. points[0],
  3851. new MockPoint(annotation.chart, points[0].target, {
  3852. x: points[0].x,
  3853. y: points[0].y + 1,
  3854. xAxis: points[0].options.xAxis,
  3855. yAxis: points[0].options.yAxis
  3856. })
  3857. ];
  3858. }
  3859. return InfinityLine.findEdgePoint(points[startIndex], points[endIndex]);
  3860. };
  3861. };
  3862. InfinityLine.findEdgeCoordinate = function (firstPoint, secondPoint, xOrY, edgePointFirstCoordinate) {
  3863. var xOrYOpposite = xOrY === 'x' ? 'y' : 'x';
  3864. // solves equation for x or y
  3865. // y - y1 = (y2 - y1) / (x2 - x1) * (x - x1)
  3866. return ((secondPoint[xOrY] - firstPoint[xOrY]) *
  3867. (edgePointFirstCoordinate - firstPoint[xOrYOpposite]) /
  3868. (secondPoint[xOrYOpposite] - firstPoint[xOrYOpposite]) +
  3869. firstPoint[xOrY]);
  3870. };
  3871. InfinityLine.findEdgePoint = function (firstPoint, secondPoint) {
  3872. var xAxis = firstPoint.series.xAxis, yAxis = secondPoint.series.yAxis, firstPointPixels = MockPoint.pointToPixels(firstPoint), secondPointPixels = MockPoint.pointToPixels(secondPoint), deltaX = secondPointPixels.x - firstPointPixels.x, deltaY = secondPointPixels.y - firstPointPixels.y, xAxisMin = xAxis.left, xAxisMax = xAxisMin + xAxis.width, yAxisMin = yAxis.top, yAxisMax = yAxisMin + yAxis.height, xLimit = deltaX < 0 ? xAxisMin : xAxisMax, yLimit = deltaY < 0 ? yAxisMin : yAxisMax, edgePoint = {
  3873. x: deltaX === 0 ? firstPointPixels.x : xLimit,
  3874. y: deltaY === 0 ? firstPointPixels.y : yLimit
  3875. }, edgePointX, edgePointY, swap;
  3876. if (deltaX !== 0 && deltaY !== 0) {
  3877. edgePointY = InfinityLine.findEdgeCoordinate(firstPointPixels, secondPointPixels, 'y', xLimit);
  3878. edgePointX = InfinityLine.findEdgeCoordinate(firstPointPixels, secondPointPixels, 'x', yLimit);
  3879. if (edgePointY >= yAxisMin && edgePointY <= yAxisMax) {
  3880. edgePoint.x = xLimit;
  3881. edgePoint.y = edgePointY;
  3882. }
  3883. else {
  3884. edgePoint.x = edgePointX;
  3885. edgePoint.y = yLimit;
  3886. }
  3887. }
  3888. edgePoint.x -= xAxisMin;
  3889. edgePoint.y -= yAxisMin;
  3890. if (firstPoint.series.chart.inverted) {
  3891. swap = edgePoint.x;
  3892. edgePoint.x = edgePoint.y;
  3893. edgePoint.y = swap;
  3894. }
  3895. return edgePoint;
  3896. };
  3897. /* *
  3898. *
  3899. * Functions
  3900. *
  3901. * */
  3902. InfinityLine.prototype.addShapes = function () {
  3903. var typeOptions = this.options.typeOptions, points = [
  3904. this.points[0],
  3905. InfinityLine.endEdgePoint
  3906. ];
  3907. if (typeOptions.type.match(/Line/g)) {
  3908. points[0] = InfinityLine.startEdgePoint;
  3909. }
  3910. var line = this.initShape(merge(typeOptions.line, {
  3911. type: 'path',
  3912. points: points
  3913. }), false);
  3914. typeOptions.line = line.options;
  3915. };
  3916. /**
  3917. *
  3918. * Static Properties
  3919. *
  3920. */
  3921. InfinityLine.endEdgePoint = InfinityLine.edgePoint(0, 1);
  3922. InfinityLine.startEdgePoint = InfinityLine.edgePoint(1, 0);
  3923. return InfinityLine;
  3924. }(CrookedLine));
  3925. InfinityLine.prototype.defaultOptions = merge(CrookedLine.prototype.defaultOptions, {});
  3926. /**
  3927. * An infinity line annotation.
  3928. *
  3929. * @sample highcharts/annotations-advanced/infinity-line/
  3930. * Infinity Line
  3931. *
  3932. * @extends annotations.crookedLine
  3933. * @product highstock
  3934. * @apioption annotations.infinityLine
  3935. */
  3936. Annotation.types.infinityLine = InfinityLine;
  3937. return InfinityLine;
  3938. });
  3939. _registerModule(_modules, 'annotations/types/Fibonacci.js', [_modules['annotations/annotations.src.js'], _modules['annotations/MockPoint.js'], _modules['annotations/types/Tunnel.js'], _modules['parts/Utilities.js']], function (Annotation, MockPoint, Tunnel, U) {
  3940. /* *
  3941. *
  3942. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  3943. *
  3944. * */
  3945. var __extends = (this && this.__extends) || (function () {
  3946. var extendStatics = function (d, b) {
  3947. extendStatics = Object.setPrototypeOf ||
  3948. ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
  3949. function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
  3950. return extendStatics(d, b);
  3951. };
  3952. return function (d, b) {
  3953. extendStatics(d, b);
  3954. function __() { this.constructor = d; }
  3955. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  3956. };
  3957. })();
  3958. var merge = U.merge;
  3959. /* eslint-disable no-invalid-this, valid-jsdoc */
  3960. var createPathDGenerator = function (retracementIndex, isBackground) {
  3961. return function () {
  3962. var annotation = this.annotation, leftTop = this.anchor(annotation.startRetracements[retracementIndex]).absolutePosition, rightTop = this.anchor(annotation.endRetracements[retracementIndex]).absolutePosition, d = [
  3963. ['M', Math.round(leftTop.x), Math.round(leftTop.y)],
  3964. ['L', Math.round(rightTop.x), Math.round(rightTop.y)]
  3965. ], rightBottom, leftBottom;
  3966. if (isBackground) {
  3967. rightBottom = this.anchor(annotation.endRetracements[retracementIndex - 1]).absolutePosition;
  3968. leftBottom = this.anchor(annotation.startRetracements[retracementIndex - 1]).absolutePosition;
  3969. d.push(['L', Math.round(rightBottom.x), Math.round(rightBottom.y)], ['L', Math.round(leftBottom.x), Math.round(leftBottom.y)]);
  3970. }
  3971. return d;
  3972. };
  3973. };
  3974. var Fibonacci = /** @class */ (function (_super) {
  3975. __extends(Fibonacci, _super);
  3976. /* *
  3977. *
  3978. * Constructors
  3979. *
  3980. * */
  3981. function Fibonacci(chart, options) {
  3982. return _super.call(this, chart, options) || this;
  3983. }
  3984. /* *
  3985. *
  3986. * Functions
  3987. *
  3988. * */
  3989. Fibonacci.prototype.linkPoints = function () {
  3990. _super.prototype.linkPoints.call(this);
  3991. this.linkRetracementsPoints();
  3992. return;
  3993. };
  3994. Fibonacci.prototype.linkRetracementsPoints = function () {
  3995. var points = this.points, startDiff = points[0].y - points[3].y, endDiff = points[1].y - points[2].y, startX = points[0].x, endX = points[1].x;
  3996. Fibonacci.levels.forEach(function (level, i) {
  3997. var startRetracement = points[0].y - startDiff * level, endRetracement = points[1].y - endDiff * level;
  3998. this.startRetracements = this.startRetracements || [];
  3999. this.endRetracements = this.endRetracements || [];
  4000. this.linkRetracementPoint(i, startX, startRetracement, this.startRetracements);
  4001. this.linkRetracementPoint(i, endX, endRetracement, this.endRetracements);
  4002. }, this);
  4003. };
  4004. Fibonacci.prototype.linkRetracementPoint = function (pointIndex, x, y, retracements) {
  4005. var point = retracements[pointIndex], typeOptions = this.options.typeOptions;
  4006. if (!point) {
  4007. retracements[pointIndex] = new MockPoint(this.chart, this, {
  4008. x: x,
  4009. y: y,
  4010. xAxis: typeOptions.xAxis,
  4011. yAxis: typeOptions.yAxis
  4012. });
  4013. }
  4014. else {
  4015. point.options.x = x;
  4016. point.options.y = y;
  4017. point.refresh();
  4018. }
  4019. };
  4020. Fibonacci.prototype.addShapes = function () {
  4021. Fibonacci.levels.forEach(function (_level, i) {
  4022. this.initShape({
  4023. type: 'path',
  4024. d: createPathDGenerator(i)
  4025. }, false);
  4026. if (i > 0) {
  4027. this.initShape({
  4028. type: 'path',
  4029. fill: this.options.typeOptions.backgroundColors[i - 1],
  4030. strokeWidth: 0,
  4031. d: createPathDGenerator(i, true)
  4032. });
  4033. }
  4034. }, this);
  4035. };
  4036. Fibonacci.prototype.addLabels = function () {
  4037. Fibonacci.levels.forEach(function (level, i) {
  4038. var options = this.options.typeOptions, label = this.initLabel(merge(options.labels[i], {
  4039. point: function (target) {
  4040. var point = MockPoint.pointToOptions(target.annotation.startRetracements[i]);
  4041. return point;
  4042. },
  4043. text: level.toString()
  4044. }));
  4045. options.labels[i] = label.options;
  4046. }, this);
  4047. };
  4048. /* *
  4049. *
  4050. * Static properties
  4051. *
  4052. * */
  4053. Fibonacci.levels = [0, 0.236, 0.382, 0.5, 0.618, 0.786, 1];
  4054. return Fibonacci;
  4055. }(Tunnel));
  4056. Fibonacci.prototype.defaultOptions = merge(Tunnel.prototype.defaultOptions,
  4057. /**
  4058. * A fibonacci annotation.
  4059. *
  4060. * @sample highcharts/annotations-advanced/fibonacci/
  4061. * Fibonacci
  4062. *
  4063. * @extends annotations.crookedLine
  4064. * @product highstock
  4065. * @optionparent annotations.fibonacci
  4066. */
  4067. {
  4068. typeOptions: {
  4069. /**
  4070. * The height of the fibonacci in terms of yAxis.
  4071. */
  4072. height: 2,
  4073. /**
  4074. * An array of background colors:
  4075. * Default to:
  4076. * ```
  4077. * [
  4078. * 'rgba(130, 170, 255, 0.4)',
  4079. * 'rgba(139, 191, 216, 0.4)',
  4080. * 'rgba(150, 216, 192, 0.4)',
  4081. * 'rgba(156, 229, 161, 0.4)',
  4082. * 'rgba(162, 241, 130, 0.4)',
  4083. * 'rgba(169, 255, 101, 0.4)'
  4084. * ]
  4085. * ```
  4086. */
  4087. backgroundColors: [
  4088. 'rgba(130, 170, 255, 0.4)',
  4089. 'rgba(139, 191, 216, 0.4)',
  4090. 'rgba(150, 216, 192, 0.4)',
  4091. 'rgba(156, 229, 161, 0.4)',
  4092. 'rgba(162, 241, 130, 0.4)',
  4093. 'rgba(169, 255, 101, 0.4)'
  4094. ],
  4095. /**
  4096. * The color of line.
  4097. */
  4098. lineColor: 'grey',
  4099. /**
  4100. * An array of colors for the lines.
  4101. */
  4102. lineColors: [],
  4103. /**
  4104. * An array with options for the labels.
  4105. *
  4106. * @type {Array<*>}
  4107. * @extends annotations.crookedLine.labelOptions
  4108. * @apioption annotations.fibonacci.typeOptions.labels
  4109. */
  4110. labels: []
  4111. },
  4112. labelOptions: {
  4113. allowOverlap: true,
  4114. align: 'right',
  4115. backgroundColor: 'none',
  4116. borderWidth: 0,
  4117. crop: false,
  4118. overflow: 'none',
  4119. shape: 'rect',
  4120. style: {
  4121. color: 'grey'
  4122. },
  4123. verticalAlign: 'middle',
  4124. y: 0
  4125. }
  4126. });
  4127. Annotation.types.fibonacci = Fibonacci;
  4128. return Fibonacci;
  4129. });
  4130. _registerModule(_modules, 'annotations/types/Pitchfork.js', [_modules['annotations/annotations.src.js'], _modules['annotations/types/InfinityLine.js'], _modules['annotations/MockPoint.js'], _modules['parts/Utilities.js']], function (Annotation, InfinityLine, MockPoint, U) {
  4131. /* *
  4132. *
  4133. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  4134. *
  4135. * */
  4136. var __extends = (this && this.__extends) || (function () {
  4137. var extendStatics = function (d, b) {
  4138. extendStatics = Object.setPrototypeOf ||
  4139. ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
  4140. function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
  4141. return extendStatics(d, b);
  4142. };
  4143. return function (d, b) {
  4144. extendStatics(d, b);
  4145. function __() { this.constructor = d; }
  4146. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  4147. };
  4148. })();
  4149. var merge = U.merge;
  4150. /* eslint-disable no-invalid-this, valid-jsdoc */
  4151. var Pitchfork = /** @class */ (function (_super) {
  4152. __extends(Pitchfork, _super);
  4153. /* *
  4154. *
  4155. * Constructors
  4156. *
  4157. * */
  4158. function Pitchfork(chart, options) {
  4159. return _super.call(this, chart, options) || this;
  4160. }
  4161. /* *
  4162. *
  4163. * Static Functions
  4164. *
  4165. * */
  4166. Pitchfork.outerLineEdgePoint = function (firstPointIndex) {
  4167. return function (target) {
  4168. var annotation = target.annotation, points = annotation.points;
  4169. return Pitchfork.findEdgePoint(points[firstPointIndex], points[0], new MockPoint(annotation.chart, target, annotation.midPointOptions()));
  4170. };
  4171. };
  4172. Pitchfork.findEdgePoint = function (point, firstAnglePoint, secondAnglePoint) {
  4173. var angle = Math.atan2(secondAnglePoint.plotY - firstAnglePoint.plotY, secondAnglePoint.plotX - firstAnglePoint.plotX), distance = 1e7;
  4174. return {
  4175. x: point.plotX + distance * Math.cos(angle),
  4176. y: point.plotY + distance * Math.sin(angle)
  4177. };
  4178. };
  4179. Pitchfork.middleLineEdgePoint = function (target) {
  4180. var annotation = target.annotation, points = annotation.points;
  4181. return InfinityLine.findEdgePoint(points[0], new MockPoint(annotation.chart, target, annotation.midPointOptions()));
  4182. };
  4183. /* *
  4184. *
  4185. * Functions
  4186. *
  4187. * */
  4188. Pitchfork.prototype.midPointOptions = function () {
  4189. var points = this.points;
  4190. return {
  4191. x: (points[1].x + points[2].x) / 2,
  4192. y: (points[1].y + points[2].y) / 2,
  4193. xAxis: points[0].series.xAxis,
  4194. yAxis: points[0].series.yAxis
  4195. };
  4196. };
  4197. Pitchfork.prototype.addShapes = function () {
  4198. this.addLines();
  4199. this.addBackgrounds();
  4200. };
  4201. Pitchfork.prototype.addLines = function () {
  4202. this.initShape({
  4203. type: 'path',
  4204. points: [
  4205. this.points[0],
  4206. Pitchfork.middleLineEdgePoint
  4207. ]
  4208. }, false);
  4209. this.initShape({
  4210. type: 'path',
  4211. points: [
  4212. this.points[1],
  4213. Pitchfork.topLineEdgePoint
  4214. ]
  4215. }, false);
  4216. this.initShape({
  4217. type: 'path',
  4218. points: [
  4219. this.points[2],
  4220. Pitchfork.bottomLineEdgePoint
  4221. ]
  4222. }, false);
  4223. };
  4224. Pitchfork.prototype.addBackgrounds = function () {
  4225. var shapes = this.shapes, typeOptions = this.options.typeOptions;
  4226. var innerBackground = this.initShape(merge(typeOptions.innerBackground, {
  4227. type: 'path',
  4228. points: [
  4229. function (target) {
  4230. var annotation = target.annotation, points = annotation.points, midPointOptions = annotation.midPointOptions();
  4231. return {
  4232. x: (points[1].x + midPointOptions.x) / 2,
  4233. y: (points[1].y + midPointOptions.y) / 2,
  4234. xAxis: midPointOptions.xAxis,
  4235. yAxis: midPointOptions.yAxis
  4236. };
  4237. },
  4238. shapes[1].points[1],
  4239. shapes[2].points[1],
  4240. function (target) {
  4241. var annotation = target.annotation, points = annotation.points, midPointOptions = annotation.midPointOptions();
  4242. return {
  4243. x: (midPointOptions.x + points[2].x) / 2,
  4244. y: (midPointOptions.y + points[2].y) / 2,
  4245. xAxis: midPointOptions.xAxis,
  4246. yAxis: midPointOptions.yAxis
  4247. };
  4248. }
  4249. ]
  4250. }));
  4251. var outerBackground = this.initShape(merge(typeOptions.outerBackground, {
  4252. type: 'path',
  4253. points: [
  4254. this.points[1],
  4255. shapes[1].points[1],
  4256. shapes[2].points[1],
  4257. this.points[2]
  4258. ]
  4259. }));
  4260. typeOptions.innerBackground = innerBackground.options;
  4261. typeOptions.outerBackground = outerBackground.options;
  4262. };
  4263. /**
  4264. *
  4265. * Static Properties
  4266. *
  4267. */
  4268. Pitchfork.topLineEdgePoint = Pitchfork.outerLineEdgePoint(1);
  4269. Pitchfork.bottomLineEdgePoint = Pitchfork.outerLineEdgePoint(0);
  4270. return Pitchfork;
  4271. }(InfinityLine));
  4272. Pitchfork.prototype.defaultOptions = merge(InfinityLine.prototype.defaultOptions,
  4273. /**
  4274. * A pitchfork annotation.
  4275. *
  4276. * @sample highcharts/annotations-advanced/pitchfork/
  4277. * Pitchfork
  4278. *
  4279. * @extends annotations.infinityLine
  4280. * @product highstock
  4281. * @optionparent annotations.pitchfork
  4282. */
  4283. {
  4284. typeOptions: {
  4285. /**
  4286. * Inner background options.
  4287. *
  4288. * @extends annotations.crookedLine.shapeOptions
  4289. * @excluding height, r, type, width
  4290. */
  4291. innerBackground: {
  4292. fill: 'rgba(130, 170, 255, 0.4)',
  4293. strokeWidth: 0
  4294. },
  4295. /**
  4296. * Outer background options.
  4297. *
  4298. * @extends annotations.crookedLine.shapeOptions
  4299. * @excluding height, r, type, width
  4300. */
  4301. outerBackground: {
  4302. fill: 'rgba(156, 229, 161, 0.4)',
  4303. strokeWidth: 0
  4304. }
  4305. }
  4306. });
  4307. Annotation.types.pitchfork = Pitchfork;
  4308. return Pitchfork;
  4309. });
  4310. _registerModule(_modules, 'annotations/types/VerticalLine.js', [_modules['annotations/annotations.src.js'], _modules['parts/Globals.js'], _modules['annotations/MockPoint.js'], _modules['parts/Utilities.js']], function (Annotation, H, MockPoint, U) {
  4311. /* *
  4312. *
  4313. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  4314. *
  4315. * */
  4316. var merge = U.merge;
  4317. /* eslint-disable no-invalid-this, valid-jsdoc */
  4318. var VerticalLine = function () {
  4319. Annotation.apply(this, arguments);
  4320. };
  4321. VerticalLine.connectorFirstPoint = function (target) {
  4322. var annotation = target.annotation, point = annotation.points[0], xy = MockPoint.pointToPixels(point, true), y = xy.y, offset = annotation.options.typeOptions.label.offset;
  4323. if (annotation.chart.inverted) {
  4324. y = xy.x;
  4325. }
  4326. return {
  4327. x: point.x,
  4328. xAxis: point.series.xAxis,
  4329. y: y + offset
  4330. };
  4331. };
  4332. VerticalLine.connectorSecondPoint = function (target) {
  4333. var annotation = target.annotation, typeOptions = annotation.options.typeOptions, point = annotation.points[0], yOffset = typeOptions.yOffset, xy = MockPoint.pointToPixels(point, true), y = xy[annotation.chart.inverted ? 'x' : 'y'];
  4334. if (typeOptions.label.offset < 0) {
  4335. yOffset *= -1;
  4336. }
  4337. return {
  4338. x: point.x,
  4339. xAxis: point.series.xAxis,
  4340. y: y + yOffset
  4341. };
  4342. };
  4343. H.extendAnnotation(VerticalLine, null, {
  4344. getPointsOptions: function () {
  4345. return [this.options.typeOptions.point];
  4346. },
  4347. addShapes: function () {
  4348. var typeOptions = this.options.typeOptions, connector = this.initShape(merge(typeOptions.connector, {
  4349. type: 'path',
  4350. points: [
  4351. VerticalLine.connectorFirstPoint,
  4352. VerticalLine.connectorSecondPoint
  4353. ]
  4354. }), false);
  4355. typeOptions.connector = connector.options;
  4356. },
  4357. addLabels: function () {
  4358. var typeOptions = this.options.typeOptions, labelOptions = typeOptions.label, x = 0, y = labelOptions.offset, verticalAlign = labelOptions.offset < 0 ? 'bottom' : 'top', align = 'center';
  4359. if (this.chart.inverted) {
  4360. x = labelOptions.offset;
  4361. y = 0;
  4362. verticalAlign = 'middle';
  4363. align = labelOptions.offset < 0 ? 'right' : 'left';
  4364. }
  4365. var label = this.initLabel(merge(labelOptions, {
  4366. verticalAlign: verticalAlign,
  4367. align: align,
  4368. x: x,
  4369. y: y
  4370. }));
  4371. typeOptions.label = label.options;
  4372. }
  4373. },
  4374. /**
  4375. * A vertical line annotation.
  4376. *
  4377. * @sample highcharts/annotations-advanced/vertical-line/
  4378. * Vertical line
  4379. *
  4380. * @extends annotations.crookedLine
  4381. * @excluding labels, shapes, controlPointOptions
  4382. * @product highstock
  4383. * @optionparent annotations.verticalLine
  4384. */
  4385. {
  4386. typeOptions: {
  4387. /**
  4388. * @ignore
  4389. */
  4390. yOffset: 10,
  4391. /**
  4392. * Label options.
  4393. *
  4394. * @extends annotations.crookedLine.labelOptions
  4395. */
  4396. label: {
  4397. offset: -40,
  4398. point: function (target) {
  4399. return target.annotation.points[0];
  4400. },
  4401. allowOverlap: true,
  4402. backgroundColor: 'none',
  4403. borderWidth: 0,
  4404. crop: true,
  4405. overflow: 'none',
  4406. shape: 'rect',
  4407. text: '{y:.2f}'
  4408. },
  4409. /**
  4410. * Connector options.
  4411. *
  4412. * @extends annotations.crookedLine.shapeOptions
  4413. * @excluding height, r, type, width
  4414. */
  4415. connector: {
  4416. strokeWidth: 1,
  4417. markerEnd: 'arrow'
  4418. }
  4419. }
  4420. });
  4421. Annotation.types.verticalLine = VerticalLine;
  4422. return VerticalLine;
  4423. });
  4424. _registerModule(_modules, 'annotations/types/Measure.js', [_modules['annotations/annotations.src.js'], _modules['annotations/ControlPoint.js'], _modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (Annotation, ControlPoint, H, U) {
  4425. /* *
  4426. *
  4427. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  4428. *
  4429. * */
  4430. var extend = U.extend, isNumber = U.isNumber, merge = U.merge;
  4431. /* eslint-disable no-invalid-this, valid-jsdoc */
  4432. var Measure = function () {
  4433. Annotation.apply(this, arguments);
  4434. };
  4435. Annotation.types.measure = Measure;
  4436. H.extendAnnotation(Measure, null, {
  4437. /**
  4438. * Init annotation object.
  4439. * @private
  4440. */
  4441. init: function () {
  4442. Annotation.prototype.init.apply(this, arguments);
  4443. this.offsetX = 0;
  4444. this.offsetY = 0;
  4445. this.resizeX = 0;
  4446. this.resizeY = 0;
  4447. this.calculations.init.call(this);
  4448. this.addValues();
  4449. this.addShapes();
  4450. },
  4451. /**
  4452. * Overrides default setter to get axes from typeOptions.
  4453. * @private
  4454. */
  4455. setClipAxes: function () {
  4456. this.clipXAxis = this.chart.xAxis[this.options.typeOptions.xAxis];
  4457. this.clipYAxis = this.chart.yAxis[this.options.typeOptions.yAxis];
  4458. },
  4459. /**
  4460. * Get measure points configuration objects.
  4461. * @private
  4462. * @return {Array<Highcharts.AnnotationMockPointOptionsObject>}
  4463. */
  4464. pointsOptions: function () {
  4465. return this.options.points;
  4466. },
  4467. /**
  4468. * Get points configuration objects for shapes.
  4469. * @private
  4470. * @return {Array<Highcharts.AnnotationMockPointOptionsObject>}
  4471. */
  4472. shapePointsOptions: function () {
  4473. var options = this.options.typeOptions, xAxis = options.xAxis, yAxis = options.yAxis;
  4474. return [
  4475. {
  4476. x: this.xAxisMin,
  4477. y: this.yAxisMin,
  4478. xAxis: xAxis,
  4479. yAxis: yAxis
  4480. },
  4481. {
  4482. x: this.xAxisMax,
  4483. y: this.yAxisMin,
  4484. xAxis: xAxis,
  4485. yAxis: yAxis
  4486. },
  4487. {
  4488. x: this.xAxisMax,
  4489. y: this.yAxisMax,
  4490. xAxis: xAxis,
  4491. yAxis: yAxis
  4492. },
  4493. {
  4494. x: this.xAxisMin,
  4495. y: this.yAxisMax,
  4496. xAxis: xAxis,
  4497. yAxis: yAxis
  4498. }
  4499. ];
  4500. },
  4501. addControlPoints: function () {
  4502. var selectType = this.options.typeOptions.selectType, controlPoint;
  4503. controlPoint = new ControlPoint(this.chart, this, this.options.controlPointOptions, 0);
  4504. this.controlPoints.push(controlPoint);
  4505. // add extra controlPoint for horizontal and vertical range
  4506. if (selectType !== 'xy') {
  4507. controlPoint = new ControlPoint(this.chart, this, this.options.controlPointOptions, 1);
  4508. this.controlPoints.push(controlPoint);
  4509. }
  4510. },
  4511. /**
  4512. * Add label with calculated values (min, max, average, bins).
  4513. * @private
  4514. * @param {boolean} [resize]
  4515. * The flag for resize shape
  4516. */
  4517. addValues: function (resize) {
  4518. var typeOptions = this.options.typeOptions, formatter = typeOptions.label.formatter;
  4519. // set xAxisMin, xAxisMax, yAxisMin, yAxisMax
  4520. this.calculations.recalculate.call(this, resize);
  4521. if (!typeOptions.label.enabled) {
  4522. return;
  4523. }
  4524. if (this.labels.length > 0) {
  4525. this.labels[0].text = (formatter && formatter.call(this)) ||
  4526. this.calculations.defaultFormatter.call(this);
  4527. }
  4528. else {
  4529. this.initLabel(extend({
  4530. shape: 'rect',
  4531. backgroundColor: 'none',
  4532. color: 'black',
  4533. borderWidth: 0,
  4534. dashStyle: 'dash',
  4535. overflow: 'none',
  4536. align: 'left',
  4537. vertical: 'top',
  4538. crop: true,
  4539. point: function (target) {
  4540. var annotation = target.annotation, chart = annotation.chart, inverted = chart.inverted, xAxis = chart.xAxis[typeOptions.xAxis], yAxis = chart.yAxis[typeOptions.yAxis], top = chart.plotTop, left = chart.plotLeft;
  4541. return {
  4542. x: (inverted ? top : 10) +
  4543. xAxis.toPixels(annotation.xAxisMin, !inverted),
  4544. y: (inverted ? -left + 10 : top) +
  4545. yAxis.toPixels(annotation.yAxisMin)
  4546. };
  4547. },
  4548. text: (formatter && formatter.call(this)) ||
  4549. this.calculations.defaultFormatter.call(this)
  4550. }, typeOptions.label));
  4551. }
  4552. },
  4553. /**
  4554. * Crosshair, background (rect).
  4555. * @private
  4556. */
  4557. addShapes: function () {
  4558. this.addCrosshairs();
  4559. this.addBackground();
  4560. },
  4561. /**
  4562. * Add background shape.
  4563. * @private
  4564. */
  4565. addBackground: function () {
  4566. var shapePoints = this.shapePointsOptions();
  4567. if (typeof shapePoints[0].x === 'undefined') {
  4568. return;
  4569. }
  4570. this.initShape(extend({
  4571. type: 'path',
  4572. points: this.shapePointsOptions()
  4573. }, this.options.typeOptions.background), false);
  4574. },
  4575. /**
  4576. * Add internal crosshair shapes (on top and bottom).
  4577. * @private
  4578. */
  4579. addCrosshairs: function () {
  4580. var chart = this.chart, options = this.options.typeOptions, point = this.options.typeOptions.point, xAxis = chart.xAxis[options.xAxis], yAxis = chart.yAxis[options.yAxis], inverted = chart.inverted, xAxisMin = xAxis.toPixels(this.xAxisMin), xAxisMax = xAxis.toPixels(this.xAxisMax), yAxisMin = yAxis.toPixels(this.yAxisMin), yAxisMax = yAxis.toPixels(this.yAxisMax), defaultOptions = {
  4581. point: point,
  4582. type: 'path'
  4583. }, pathH = [], pathV = [], crosshairOptionsX, crosshairOptionsY, temp;
  4584. if (inverted) {
  4585. temp = xAxisMin;
  4586. xAxisMin = yAxisMin;
  4587. yAxisMin = temp;
  4588. temp = xAxisMax;
  4589. xAxisMax = yAxisMax;
  4590. yAxisMax = temp;
  4591. }
  4592. // horizontal line
  4593. if (options.crosshairX.enabled) {
  4594. pathH = [[
  4595. 'M',
  4596. xAxisMin,
  4597. yAxisMin + ((yAxisMax - yAxisMin) / 2)
  4598. ], [
  4599. 'L',
  4600. xAxisMax,
  4601. yAxisMin + ((yAxisMax - yAxisMin) / 2)
  4602. ]];
  4603. }
  4604. // vertical line
  4605. if (options.crosshairY.enabled) {
  4606. pathV = [[
  4607. 'M',
  4608. xAxisMin + ((xAxisMax - xAxisMin) / 2),
  4609. yAxisMin
  4610. ], [
  4611. 'L',
  4612. xAxisMin + ((xAxisMax - xAxisMin) / 2),
  4613. yAxisMax
  4614. ]];
  4615. }
  4616. // Update existed crosshair
  4617. if (this.shapes.length > 0) {
  4618. this.shapes[0].options.d = pathH;
  4619. this.shapes[1].options.d = pathV;
  4620. }
  4621. else {
  4622. // Add new crosshairs
  4623. crosshairOptionsX = merge(defaultOptions, options.crosshairX);
  4624. crosshairOptionsY = merge(defaultOptions, options.crosshairY);
  4625. this.initShape(extend({
  4626. d: pathH
  4627. }, crosshairOptionsX), false);
  4628. this.initShape(extend({
  4629. d: pathV
  4630. }, crosshairOptionsY), false);
  4631. }
  4632. },
  4633. onDrag: function (e) {
  4634. var translation = this.mouseMoveToTranslation(e), selectType = this.options.typeOptions.selectType, x = selectType === 'y' ? 0 : translation.x, y = selectType === 'x' ? 0 : translation.y;
  4635. this.translate(x, y);
  4636. this.offsetX += x;
  4637. this.offsetY += y;
  4638. // animation, resize, setStartPoints
  4639. this.redraw(false, false, true);
  4640. },
  4641. /**
  4642. * Translate start or end ("left" or "right") side of the measure.
  4643. * Update start points (startXMin, startXMax, startYMin, startYMax)
  4644. * @private
  4645. * @param {number} dx - the amount of x translation
  4646. * @param {number} dy - the amount of y translation
  4647. * @param {number} cpIndex - index of control point
  4648. * @param {Highcharts.AnnotationDraggableValue} selectType - x / y / xy
  4649. */
  4650. resize: function (dx, dy, cpIndex, selectType) {
  4651. // background shape
  4652. var bckShape = this.shapes[2];
  4653. if (selectType === 'x') {
  4654. if (cpIndex === 0) {
  4655. bckShape.translatePoint(dx, 0, 0);
  4656. bckShape.translatePoint(dx, dy, 3);
  4657. }
  4658. else {
  4659. bckShape.translatePoint(dx, 0, 1);
  4660. bckShape.translatePoint(dx, dy, 2);
  4661. }
  4662. }
  4663. else if (selectType === 'y') {
  4664. if (cpIndex === 0) {
  4665. bckShape.translatePoint(0, dy, 0);
  4666. bckShape.translatePoint(0, dy, 1);
  4667. }
  4668. else {
  4669. bckShape.translatePoint(0, dy, 2);
  4670. bckShape.translatePoint(0, dy, 3);
  4671. }
  4672. }
  4673. else {
  4674. bckShape.translatePoint(dx, 0, 1);
  4675. bckShape.translatePoint(dx, dy, 2);
  4676. bckShape.translatePoint(0, dy, 3);
  4677. }
  4678. this.calculations.updateStartPoints
  4679. .call(this, false, true, cpIndex, dx, dy);
  4680. this.options.typeOptions.background.height = Math.abs(this.startYMax - this.startYMin);
  4681. this.options.typeOptions.background.width = Math.abs(this.startXMax - this.startXMin);
  4682. },
  4683. /**
  4684. * Redraw event which render elements and update start points if needed.
  4685. * @private
  4686. * @param {boolean} animation
  4687. * @param {boolean} [resize] - flag if resized
  4688. * @param {boolean} [setStartPoints] - update position of start points
  4689. */
  4690. redraw: function (animation, resize, setStartPoints) {
  4691. this.linkPoints();
  4692. if (!this.graphic) {
  4693. this.render();
  4694. }
  4695. if (setStartPoints) {
  4696. this.calculations.updateStartPoints.call(this, true, false);
  4697. }
  4698. // #11174 - clipBox was not recalculate during resize / redraw
  4699. if (this.clipRect) {
  4700. this.clipRect.animate(this.getClipBox());
  4701. }
  4702. this.addValues(resize);
  4703. this.addCrosshairs();
  4704. this.redrawItems(this.shapes, animation);
  4705. this.redrawItems(this.labels, animation);
  4706. // redraw control point to run positioner
  4707. this.controlPoints.forEach(function (controlPoint) {
  4708. controlPoint.redraw();
  4709. });
  4710. },
  4711. translate: function (dx, dy) {
  4712. this.shapes.forEach(function (item) {
  4713. item.translate(dx, dy);
  4714. });
  4715. this.options.typeOptions.point.x = this.startXMin;
  4716. this.options.typeOptions.point.y = this.startYMin;
  4717. },
  4718. calculations: {
  4719. /**
  4720. * Set starting points
  4721. * @private
  4722. */
  4723. init: function () {
  4724. var options = this.options.typeOptions, chart = this.chart, getPointPos = this.calculations.getPointPos, inverted = chart.inverted, xAxis = chart.xAxis[options.xAxis], yAxis = chart.yAxis[options.yAxis], bck = options.background, width = inverted ? bck.height : bck.width, height = inverted ? bck.width : bck.height, selectType = options.selectType, top = inverted ? chart.plotLeft : chart.plotTop, left = inverted ? chart.plotTop : chart.plotLeft;
  4725. this.startXMin = options.point.x;
  4726. this.startYMin = options.point.y;
  4727. if (isNumber(width)) {
  4728. this.startXMax = this.startXMin + width;
  4729. }
  4730. else {
  4731. this.startXMax = getPointPos(xAxis, this.startXMin, parseFloat(width));
  4732. }
  4733. if (isNumber(height)) {
  4734. this.startYMax = this.startYMin - height;
  4735. }
  4736. else {
  4737. this.startYMax = getPointPos(yAxis, this.startYMin, parseFloat(height));
  4738. }
  4739. // x / y selection type
  4740. if (selectType === 'x') {
  4741. this.startYMin = yAxis.toValue(top);
  4742. this.startYMax = yAxis.toValue(top + yAxis.len);
  4743. }
  4744. else if (selectType === 'y') {
  4745. this.startXMin = xAxis.toValue(left);
  4746. this.startXMax = xAxis.toValue(left + xAxis.len);
  4747. }
  4748. },
  4749. /**
  4750. * Set current xAxisMin, xAxisMax, yAxisMin, yAxisMax.
  4751. * Calculations of measure values (min, max, average, bins).
  4752. * @private
  4753. * @param {boolean} [resize]
  4754. * Flag if shape is resized.
  4755. */
  4756. recalculate: function (resize) {
  4757. var calc = this.calculations, options = this.options.typeOptions, xAxis = this.chart.xAxis[options.xAxis], yAxis = this.chart.yAxis[options.yAxis], getPointPos = this.calculations.getPointPos, offsetX = this.offsetX, offsetY = this.offsetY;
  4758. this.xAxisMin = getPointPos(xAxis, this.startXMin, offsetX);
  4759. this.xAxisMax = getPointPos(xAxis, this.startXMax, offsetX);
  4760. this.yAxisMin = getPointPos(yAxis, this.startYMin, offsetY);
  4761. this.yAxisMax = getPointPos(yAxis, this.startYMax, offsetY);
  4762. this.min = calc.min.call(this);
  4763. this.max = calc.max.call(this);
  4764. this.average = calc.average.call(this);
  4765. this.bins = calc.bins.call(this);
  4766. if (resize) {
  4767. this.resize(0, 0);
  4768. }
  4769. },
  4770. /**
  4771. * Set current xAxisMin, xAxisMax, yAxisMin, yAxisMax.
  4772. * Calculations of measure values (min, max, average, bins).
  4773. * @private
  4774. * @param {Highcharts.Axis} axis
  4775. * X or y axis reference
  4776. * @param {number} value
  4777. * Point's value (x or y)
  4778. * @param {number} offset
  4779. * Amount of pixels
  4780. */
  4781. getPointPos: function (axis, value, offset) {
  4782. return axis.toValue(axis.toPixels(value) + offset);
  4783. },
  4784. /**
  4785. * Update position of start points
  4786. * (startXMin, startXMax, startYMin, startYMax)
  4787. * @private
  4788. * @param {boolean} redraw
  4789. * Flag if shape is redraw
  4790. * @param {boolean} resize
  4791. * Flag if shape is resized
  4792. * @param {number} cpIndex
  4793. * Index of controlPoint
  4794. */
  4795. updateStartPoints: function (redraw, resize, cpIndex, dx, dy) {
  4796. var options = this.options.typeOptions, selectType = options.selectType, xAxis = this.chart.xAxis[options.xAxis], yAxis = this.chart.yAxis[options.yAxis], getPointPos = this.calculations.getPointPos, startXMin = this.startXMin, startXMax = this.startXMax, startYMin = this.startYMin, startYMax = this.startYMax, offsetX = this.offsetX, offsetY = this.offsetY;
  4797. if (resize) {
  4798. if (selectType === 'x') {
  4799. if (cpIndex === 0) {
  4800. this.startXMin = getPointPos(xAxis, startXMin, dx);
  4801. }
  4802. else {
  4803. this.startXMax = getPointPos(xAxis, startXMax, dx);
  4804. }
  4805. }
  4806. else if (selectType === 'y') {
  4807. if (cpIndex === 0) {
  4808. this.startYMin = getPointPos(yAxis, startYMin, dy);
  4809. }
  4810. else {
  4811. this.startYMax = getPointPos(yAxis, startYMax, dy);
  4812. }
  4813. }
  4814. else {
  4815. this.startXMax = getPointPos(xAxis, startXMax, dx);
  4816. this.startYMax = getPointPos(yAxis, startYMax, dy);
  4817. }
  4818. }
  4819. if (redraw) {
  4820. this.startXMin = getPointPos(xAxis, startXMin, offsetX);
  4821. this.startXMax = getPointPos(xAxis, startXMax, offsetX);
  4822. this.startYMin = getPointPos(yAxis, startYMin, offsetY);
  4823. this.startYMax = getPointPos(yAxis, startYMax, offsetY);
  4824. this.offsetX = 0;
  4825. this.offsetY = 0;
  4826. }
  4827. },
  4828. /**
  4829. * Default formatter of label's content
  4830. * @private
  4831. */
  4832. defaultFormatter: function () {
  4833. return 'Min: ' + this.min +
  4834. '<br>Max: ' + this.max +
  4835. '<br>Average: ' + this.average +
  4836. '<br>Bins: ' + this.bins;
  4837. },
  4838. /**
  4839. * Set values for xAxisMin, xAxisMax, yAxisMin, yAxisMax, also
  4840. * when chart is inverted
  4841. * @private
  4842. */
  4843. getExtremes: function (xAxisMin, xAxisMax, yAxisMin, yAxisMax) {
  4844. return {
  4845. xAxisMin: Math.min(xAxisMax, xAxisMin),
  4846. xAxisMax: Math.max(xAxisMax, xAxisMin),
  4847. yAxisMin: Math.min(yAxisMax, yAxisMin),
  4848. yAxisMax: Math.max(yAxisMax, yAxisMin)
  4849. };
  4850. },
  4851. /**
  4852. * Definitions of calculations (min, max, average, bins)
  4853. * @private
  4854. */
  4855. min: function () {
  4856. var min = Infinity, series = this.chart.series, ext = this.calculations.getExtremes(this.xAxisMin, this.xAxisMax, this.yAxisMin, this.yAxisMax), isCalculated = false; // to avoid Infinity in formatter
  4857. series.forEach(function (serie) {
  4858. if (serie.visible &&
  4859. serie.options.id !== 'highcharts-navigator-series') {
  4860. serie.points.forEach(function (point) {
  4861. if (!point.isNull &&
  4862. point.y < min &&
  4863. point.x > ext.xAxisMin &&
  4864. point.x <= ext.xAxisMax &&
  4865. point.y > ext.yAxisMin &&
  4866. point.y <= ext.yAxisMax) {
  4867. min = point.y;
  4868. isCalculated = true;
  4869. }
  4870. });
  4871. }
  4872. });
  4873. if (!isCalculated) {
  4874. min = '';
  4875. }
  4876. return min;
  4877. },
  4878. max: function () {
  4879. var max = -Infinity, series = this.chart.series, ext = this.calculations.getExtremes(this.xAxisMin, this.xAxisMax, this.yAxisMin, this.yAxisMax), isCalculated = false; // to avoid Infinity in formatter
  4880. series.forEach(function (serie) {
  4881. if (serie.visible &&
  4882. serie.options.id !== 'highcharts-navigator-series') {
  4883. serie.points.forEach(function (point) {
  4884. if (!point.isNull &&
  4885. point.y > max &&
  4886. point.x > ext.xAxisMin &&
  4887. point.x <= ext.xAxisMax &&
  4888. point.y > ext.yAxisMin &&
  4889. point.y <= ext.yAxisMax) {
  4890. max = point.y;
  4891. isCalculated = true;
  4892. }
  4893. });
  4894. }
  4895. });
  4896. if (!isCalculated) {
  4897. max = '';
  4898. }
  4899. return max;
  4900. },
  4901. average: function () {
  4902. var average = '';
  4903. if (this.max !== '' && this.min !== '') {
  4904. average = (this.max + this.min) / 2;
  4905. }
  4906. return average;
  4907. },
  4908. bins: function () {
  4909. var bins = 0, series = this.chart.series, ext = this.calculations.getExtremes(this.xAxisMin, this.xAxisMax, this.yAxisMin, this.yAxisMax), isCalculated = false; // to avoid Infinity in formatter
  4910. series.forEach(function (serie) {
  4911. if (serie.visible &&
  4912. serie.options.id !== 'highcharts-navigator-series') {
  4913. serie.points.forEach(function (point) {
  4914. if (!point.isNull &&
  4915. point.x > ext.xAxisMin &&
  4916. point.x <= ext.xAxisMax &&
  4917. point.y > ext.yAxisMin &&
  4918. point.y <= ext.yAxisMax) {
  4919. bins++;
  4920. isCalculated = true;
  4921. }
  4922. });
  4923. }
  4924. });
  4925. if (!isCalculated) {
  4926. bins = '';
  4927. }
  4928. return bins;
  4929. }
  4930. }
  4931. },
  4932. /**
  4933. * A measure annotation.
  4934. *
  4935. * @extends annotations.crookedLine
  4936. * @excluding labels, labelOptions, shapes, shapeOptions
  4937. * @sample highcharts/annotations-advanced/measure/
  4938. * Measure
  4939. * @product highstock
  4940. * @optionparent annotations.measure
  4941. */
  4942. {
  4943. typeOptions: {
  4944. /**
  4945. * Decides in what dimensions the user can resize by dragging the
  4946. * mouse. Can be one of x, y or xy.
  4947. */
  4948. selectType: 'xy',
  4949. /**
  4950. * This number defines which xAxis the point is connected to.
  4951. * It refers to either the axis id or the index of the axis
  4952. * in the xAxis array.
  4953. */
  4954. xAxis: 0,
  4955. /**
  4956. * This number defines which yAxis the point is connected to.
  4957. * It refers to either the axis id or the index of the axis
  4958. * in the yAxis array.
  4959. */
  4960. yAxis: 0,
  4961. background: {
  4962. /**
  4963. * The color of the rectangle.
  4964. */
  4965. fill: 'rgba(130, 170, 255, 0.4)',
  4966. /**
  4967. * The width of border.
  4968. */
  4969. strokeWidth: 0,
  4970. /**
  4971. * The color of border.
  4972. */
  4973. stroke: void 0
  4974. },
  4975. /**
  4976. * Configure a crosshair that is horizontally placed in middle of
  4977. * rectangle.
  4978. *
  4979. */
  4980. crosshairX: {
  4981. /**
  4982. * Enable or disable the horizontal crosshair.
  4983. *
  4984. */
  4985. enabled: true,
  4986. /**
  4987. * The Z index of the crosshair in annotation.
  4988. */
  4989. zIndex: 6,
  4990. /**
  4991. * The dash or dot style of the crosshair's line. For possible
  4992. * values, see
  4993. * [this demonstration](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/plotoptions/series-dashstyle-all/).
  4994. *
  4995. * @type {Highcharts.DashStyleValue}
  4996. * @default Dash
  4997. */
  4998. dashStyle: 'Dash',
  4999. /**
  5000. * The marker-end defines the arrowhead that will be drawn
  5001. * at the final vertex of the given crosshair's path.
  5002. *
  5003. * @type {string}
  5004. * @default arrow
  5005. */
  5006. markerEnd: 'arrow'
  5007. },
  5008. /**
  5009. * Configure a crosshair that is vertically placed in middle of
  5010. * rectangle.
  5011. */
  5012. crosshairY: {
  5013. /**
  5014. * Enable or disable the vertical crosshair.
  5015. *
  5016. */
  5017. enabled: true,
  5018. /**
  5019. * The Z index of the crosshair in annotation.
  5020. */
  5021. zIndex: 6,
  5022. /**
  5023. * The dash or dot style of the crosshair's line. For possible
  5024. * values, see [this demonstration](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/plotoptions/series-dashstyle-all/).
  5025. *
  5026. * @type {Highcharts.DashStyleValue}
  5027. * @default Dash
  5028. * @apioption annotations.measure.typeOptions.crosshairY.dashStyle
  5029. *
  5030. */
  5031. dashStyle: 'Dash',
  5032. /**
  5033. * The marker-end defines the arrowhead that will be drawn
  5034. * at the final vertex of the given crosshair's path.
  5035. *
  5036. * @type {string}
  5037. * @default arrow
  5038. * @validvalue ["none", "arrow"]
  5039. *
  5040. */
  5041. markerEnd: 'arrow'
  5042. },
  5043. label: {
  5044. /**
  5045. * Enable or disable the label text (min, max, average,
  5046. * bins values).
  5047. *
  5048. * Defaults to true.
  5049. */
  5050. enabled: true,
  5051. /**
  5052. * CSS styles for the measure label.
  5053. *
  5054. * @type {Highcharts.CSSObject}
  5055. * @default {"color": "#666666", "fontSize": "11px"}
  5056. */
  5057. style: {
  5058. fontSize: '11px',
  5059. color: '#666666'
  5060. },
  5061. /**
  5062. * Formatter function for the label text.
  5063. *
  5064. * Available data are:
  5065. *
  5066. * <table>
  5067. *
  5068. * <tbody>
  5069. *
  5070. * <tr>
  5071. *
  5072. * <td>`this.min`</td>
  5073. *
  5074. * <td>The mininimum value of the points in the selected
  5075. * range.</td>
  5076. *
  5077. * </tr>
  5078. *
  5079. * <tr>
  5080. *
  5081. * <td>`this.max`</td>
  5082. *
  5083. * <td>The maximum value of the points in the selected
  5084. * range.</td>
  5085. *
  5086. * </tr>
  5087. *
  5088. * <tr>
  5089. *
  5090. * <td>`this.average`</td>
  5091. *
  5092. * <td>The average value of the points in the selected
  5093. * range.</td>
  5094. *
  5095. * </tr>
  5096. *
  5097. * <tr>
  5098. *
  5099. * <td>`this.bins`</td>
  5100. *
  5101. * <td>The amount of the points in the selected range.</td>
  5102. *
  5103. * </tr>
  5104. *
  5105. * </table>
  5106. *
  5107. * @type {function}
  5108. *
  5109. */
  5110. formatter: void 0
  5111. }
  5112. },
  5113. controlPointOptions: {
  5114. positioner: function (target) {
  5115. var cpIndex = this.index, chart = target.chart, options = target.options, typeOptions = options.typeOptions, selectType = typeOptions.selectType, controlPointOptions = options.controlPointOptions, inverted = chart.inverted, xAxis = chart.xAxis[typeOptions.xAxis], yAxis = chart.yAxis[typeOptions.yAxis], targetX = target.xAxisMax, targetY = target.yAxisMax, ext = target.calculations.getExtremes(target.xAxisMin, target.xAxisMax, target.yAxisMin, target.yAxisMax), x, y;
  5116. if (selectType === 'x') {
  5117. targetY = (ext.yAxisMax - ext.yAxisMin) / 2;
  5118. // first control point
  5119. if (cpIndex === 0) {
  5120. targetX = target.xAxisMin;
  5121. }
  5122. }
  5123. if (selectType === 'y') {
  5124. targetX = ext.xAxisMin +
  5125. ((ext.xAxisMax - ext.xAxisMin) / 2);
  5126. // first control point
  5127. if (cpIndex === 0) {
  5128. targetY = target.yAxisMin;
  5129. }
  5130. }
  5131. if (inverted) {
  5132. x = yAxis.toPixels(targetY);
  5133. y = xAxis.toPixels(targetX);
  5134. }
  5135. else {
  5136. x = xAxis.toPixels(targetX);
  5137. y = yAxis.toPixels(targetY);
  5138. }
  5139. return {
  5140. x: x - (controlPointOptions.width / 2),
  5141. y: y - (controlPointOptions.height / 2)
  5142. };
  5143. },
  5144. events: {
  5145. drag: function (e, target) {
  5146. var translation = this.mouseMoveToTranslation(e), selectType = target.options.typeOptions.selectType, index = this.index, x = selectType === 'y' ? 0 : translation.x, y = selectType === 'x' ? 0 : translation.y;
  5147. target.resize(x, y, index, selectType);
  5148. target.resizeX += x;
  5149. target.resizeY += y;
  5150. target.redraw(false, true);
  5151. }
  5152. }
  5153. }
  5154. });
  5155. Annotation.types.measure = Measure;
  5156. return Measure;
  5157. });
  5158. _registerModule(_modules, 'mixins/navigation.js', [], function () {
  5159. /**
  5160. *
  5161. * (c) 2010-2018 Paweł Fus
  5162. *
  5163. * License: www.highcharts.com/license
  5164. *
  5165. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  5166. *
  5167. * */
  5168. var chartNavigation = {
  5169. /**
  5170. * Initializes `chart.navigation` object which delegates `update()` methods
  5171. * to all other common classes (used in exporting and navigationBindings).
  5172. *
  5173. * @private
  5174. * @param {Highcharts.Chart} chart
  5175. * The chart instance.
  5176. * @return {void}
  5177. */
  5178. initUpdate: function (chart) {
  5179. if (!chart.navigation) {
  5180. chart.navigation = {
  5181. updates: [],
  5182. update: function (options, redraw) {
  5183. this.updates.forEach(function (updateConfig) {
  5184. updateConfig.update.call(updateConfig.context, options, redraw);
  5185. });
  5186. }
  5187. };
  5188. }
  5189. },
  5190. /**
  5191. * Registers an `update()` method in the `chart.navigation` object.
  5192. *
  5193. * @private
  5194. * @param {Highcharts.ChartNavigationUpdateFunction} update
  5195. * The `update()` method that will be called in `chart.update()`.
  5196. * @param {Highcharts.Chart} chart
  5197. * The chart instance. `update()` will use that as a context
  5198. * (`this`).
  5199. * @return {void}
  5200. */
  5201. addUpdate: function (update, chart) {
  5202. if (!chart.navigation) {
  5203. this.initUpdate(chart);
  5204. }
  5205. chart.navigation.updates.push({
  5206. update: update,
  5207. context: chart
  5208. });
  5209. }
  5210. };
  5211. return chartNavigation;
  5212. });
  5213. _registerModule(_modules, 'annotations/navigationBindings.js', [_modules['annotations/annotations.src.js'], _modules['mixins/navigation.js'], _modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (Annotation, chartNavigationMixin, H, U) {
  5214. /* *
  5215. *
  5216. * (c) 2009-2017 Highsoft, Black Label
  5217. *
  5218. * License: www.highcharts.com/license
  5219. *
  5220. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  5221. *
  5222. * */
  5223. var addEvent = U.addEvent, attr = U.attr, extend = U.extend, format = U.format, fireEvent = U.fireEvent, isArray = U.isArray, isFunction = U.isFunction, isNumber = U.isNumber, isObject = U.isObject, merge = U.merge, objectEach = U.objectEach, pick = U.pick, setOptions = U.setOptions;
  5224. /**
  5225. * A config object for navigation bindings in annotations.
  5226. *
  5227. * @interface Highcharts.NavigationBindingsOptionsObject
  5228. */ /**
  5229. * ClassName of the element for a binding.
  5230. * @name Highcharts.NavigationBindingsOptionsObject#className
  5231. * @type {string|undefined}
  5232. */ /**
  5233. * Last event to be fired after last step event.
  5234. * @name Highcharts.NavigationBindingsOptionsObject#end
  5235. * @type {Function|undefined}
  5236. */ /**
  5237. * Initial event, fired on a button click.
  5238. * @name Highcharts.NavigationBindingsOptionsObject#init
  5239. * @type {Function|undefined}
  5240. */ /**
  5241. * Event fired on first click on a chart.
  5242. * @name Highcharts.NavigationBindingsOptionsObject#start
  5243. * @type {Function|undefined}
  5244. */ /**
  5245. * Last event to be fired after last step event. Array of step events to be
  5246. * called sequentially after each user click.
  5247. * @name Highcharts.NavigationBindingsOptionsObject#steps
  5248. * @type {Array<Function>|undefined}
  5249. */
  5250. var doc = H.doc, win = H.win, PREFIX = 'highcharts-';
  5251. /* eslint-disable no-invalid-this, valid-jsdoc */
  5252. /**
  5253. * IE 9-11 polyfill for Element.closest():
  5254. * @private
  5255. */
  5256. function closestPolyfill(el, s) {
  5257. var ElementProto = win.Element.prototype, elementMatches = ElementProto.matches ||
  5258. ElementProto.msMatchesSelector ||
  5259. ElementProto.webkitMatchesSelector, ret = null;
  5260. if (ElementProto.closest) {
  5261. ret = ElementProto.closest.call(el, s);
  5262. }
  5263. else {
  5264. do {
  5265. if (elementMatches.call(el, s)) {
  5266. return el;
  5267. }
  5268. el = el.parentElement || el.parentNode;
  5269. } while (el !== null && el.nodeType === 1);
  5270. }
  5271. return ret;
  5272. }
  5273. /**
  5274. * @private
  5275. * @interface bindingsUtils
  5276. */
  5277. var bindingsUtils = {
  5278. /**
  5279. * Update size of background (rect) in some annotations: Measure, Simple
  5280. * Rect.
  5281. *
  5282. * @private
  5283. * @function Highcharts.NavigationBindingsUtilsObject.updateRectSize
  5284. *
  5285. * @param {Highcharts.PointerEventObject} event
  5286. * Normalized browser event
  5287. *
  5288. * @param {Highcharts.Annotation} annotation
  5289. * Annotation to be updated
  5290. */
  5291. updateRectSize: function (event, annotation) {
  5292. var chart = annotation.chart, options = annotation.options.typeOptions, coords = chart.pointer.getCoordinates(event), width = coords.xAxis[0].value - options.point.x, height = options.point.y - coords.yAxis[0].value;
  5293. annotation.update({
  5294. typeOptions: {
  5295. background: {
  5296. width: chart.inverted ? height : width,
  5297. height: chart.inverted ? width : height
  5298. }
  5299. }
  5300. });
  5301. },
  5302. /**
  5303. * Get field type according to value
  5304. *
  5305. * @private
  5306. * @function Highcharts.NavigationBindingsUtilsObject.getFieldType
  5307. *
  5308. * @param {'boolean'|'number'|'string'} value
  5309. * Atomic type (one of: string, number, boolean)
  5310. *
  5311. * @return {'checkbox'|'number'|'text'}
  5312. * Field type (one of: text, number, checkbox)
  5313. */
  5314. getFieldType: function (value) {
  5315. return {
  5316. 'string': 'text',
  5317. 'number': 'number',
  5318. 'boolean': 'checkbox'
  5319. }[typeof value];
  5320. }
  5321. };
  5322. /**
  5323. * @private
  5324. */
  5325. var NavigationBindings = /** @class */ (function () {
  5326. /* *
  5327. *
  5328. * Constructors
  5329. *
  5330. * */
  5331. function NavigationBindings(chart, options) {
  5332. this.boundClassNames = void 0;
  5333. this.selectedButton = void 0;
  5334. this.chart = chart;
  5335. this.options = options;
  5336. this.eventsToUnbind = [];
  5337. this.container = doc.getElementsByClassName(this.options.bindingsClassName || '');
  5338. }
  5339. // Private properties added by bindings:
  5340. // Active (selected) annotation that is editted through popup/forms
  5341. // activeAnnotation: Annotation
  5342. // Holder for current step, used on mouse move to update bound object
  5343. // mouseMoveEvent: function () {}
  5344. // Next event in `step` array to be called on chart's click
  5345. // nextEvent: function () {}
  5346. // Index in the `step` array of the current event
  5347. // stepIndex: 0
  5348. // Flag to determine if current binding has steps
  5349. // steps: true|false
  5350. // Bindings holder for all events
  5351. // selectedButton: {}
  5352. // Holder for user options, returned from `start` event, and passed on to
  5353. // `step`'s' and `end`.
  5354. // currentUserDetails: {}
  5355. /* *
  5356. *
  5357. * Functions
  5358. *
  5359. * */
  5360. /**
  5361. * Initi all events conencted to NavigationBindings.
  5362. *
  5363. * @private
  5364. * @function Highcharts.NavigationBindings#initEvents
  5365. */
  5366. NavigationBindings.prototype.initEvents = function () {
  5367. var navigation = this, chart = navigation.chart, bindingsContainer = navigation.container, options = navigation.options;
  5368. // Shorthand object for getting events for buttons:
  5369. navigation.boundClassNames = {};
  5370. objectEach((options.bindings || {}), function (value) {
  5371. navigation.boundClassNames[value.className] = value;
  5372. });
  5373. // Handle multiple containers with the same class names:
  5374. [].forEach.call(bindingsContainer, function (subContainer) {
  5375. navigation.eventsToUnbind.push(addEvent(subContainer, 'click', function (event) {
  5376. var bindings = navigation.getButtonEvents(subContainer, event);
  5377. if (bindings) {
  5378. navigation.bindingsButtonClick(bindings.button, bindings.events, event);
  5379. }
  5380. }));
  5381. });
  5382. objectEach(options.events || {}, function (callback, eventName) {
  5383. if (isFunction(callback)) {
  5384. navigation.eventsToUnbind.push(addEvent(navigation, eventName, callback));
  5385. }
  5386. });
  5387. navigation.eventsToUnbind.push(addEvent(chart.container, 'click', function (e) {
  5388. if (!chart.cancelClick &&
  5389. chart.isInsidePlot(e.chartX - chart.plotLeft, e.chartY - chart.plotTop)) {
  5390. navigation.bindingsChartClick(this, e);
  5391. }
  5392. }));
  5393. navigation.eventsToUnbind.push(addEvent(chart.container, H.isTouchDevice ? 'touchmove' : 'mousemove', function (e) {
  5394. navigation.bindingsContainerMouseMove(this, e);
  5395. }));
  5396. };
  5397. /**
  5398. * Common chart.update() delegation, shared between bindings and exporting.
  5399. *
  5400. * @private
  5401. * @function Highcharts.NavigationBindings#initUpdate
  5402. */
  5403. NavigationBindings.prototype.initUpdate = function () {
  5404. var navigation = this;
  5405. chartNavigationMixin.addUpdate(function (options) {
  5406. navigation.update(options);
  5407. }, this.chart);
  5408. };
  5409. /**
  5410. * Hook for click on a button, method selcts/unselects buttons,
  5411. * then calls `bindings.init` callback.
  5412. *
  5413. * @private
  5414. * @function Highcharts.NavigationBindings#bindingsButtonClick
  5415. *
  5416. * @param {Highcharts.HTMLDOMElement} [button]
  5417. * Clicked button
  5418. *
  5419. * @param {object} events
  5420. * Events passed down from bindings (`init`, `start`, `step`, `end`)
  5421. *
  5422. * @param {Highcharts.PointerEventObject} clickEvent
  5423. * Browser's click event
  5424. */
  5425. NavigationBindings.prototype.bindingsButtonClick = function (button, events, clickEvent) {
  5426. var navigation = this, chart = navigation.chart;
  5427. if (navigation.selectedButtonElement) {
  5428. fireEvent(navigation, 'deselectButton', { button: navigation.selectedButtonElement });
  5429. if (navigation.nextEvent) {
  5430. // Remove in-progress annotations adders:
  5431. if (navigation.currentUserDetails &&
  5432. navigation.currentUserDetails.coll === 'annotations') {
  5433. chart.removeAnnotation(navigation.currentUserDetails);
  5434. }
  5435. navigation.mouseMoveEvent = navigation.nextEvent = false;
  5436. }
  5437. }
  5438. navigation.selectedButton = events;
  5439. navigation.selectedButtonElement = button;
  5440. fireEvent(navigation, 'selectButton', { button: button });
  5441. // Call "init" event, for example to open modal window
  5442. if (events.init) {
  5443. events.init.call(navigation, button, clickEvent);
  5444. }
  5445. if (events.start || events.steps) {
  5446. chart.renderer.boxWrapper.addClass(PREFIX + 'draw-mode');
  5447. }
  5448. };
  5449. /**
  5450. * Hook for click on a chart, first click on a chart calls `start` event,
  5451. * then on all subsequent clicks iterate over `steps` array.
  5452. * When finished, calls `end` event.
  5453. *
  5454. * @private
  5455. * @function Highcharts.NavigationBindings#bindingsChartClick
  5456. *
  5457. * @param {Highcharts.Chart} chart
  5458. * Chart that click was performed on.
  5459. *
  5460. * @param {Highcharts.PointerEventObject} clickEvent
  5461. * Browser's click event.
  5462. */
  5463. NavigationBindings.prototype.bindingsChartClick = function (chart, clickEvent) {
  5464. var navigation = this, chart = navigation.chart, selectedButton = navigation.selectedButton, svgContainer = chart.renderer.boxWrapper;
  5465. // Click outside popups, should close them and deselect the annotation
  5466. if (navigation.activeAnnotation &&
  5467. !clickEvent.activeAnnotation &&
  5468. // Element could be removed in the child action, e.g. button
  5469. clickEvent.target.parentNode &&
  5470. // TO DO: Polyfill for IE11?
  5471. !closestPolyfill(clickEvent.target, '.' + PREFIX + 'popup')) {
  5472. fireEvent(navigation, 'closePopup');
  5473. navigation.deselectAnnotation();
  5474. }
  5475. if (!selectedButton || !selectedButton.start) {
  5476. return;
  5477. }
  5478. if (!navigation.nextEvent) {
  5479. // Call init method:
  5480. navigation.currentUserDetails = selectedButton.start.call(navigation, clickEvent);
  5481. // If steps exists (e.g. Annotations), bind them:
  5482. if (selectedButton.steps) {
  5483. navigation.stepIndex = 0;
  5484. navigation.steps = true;
  5485. navigation.mouseMoveEvent = navigation.nextEvent =
  5486. selectedButton.steps[navigation.stepIndex];
  5487. }
  5488. else {
  5489. fireEvent(navigation, 'deselectButton', { button: navigation.selectedButtonElement });
  5490. svgContainer.removeClass(PREFIX + 'draw-mode');
  5491. navigation.steps = false;
  5492. navigation.selectedButton = null;
  5493. // First click is also the last one:
  5494. if (selectedButton.end) {
  5495. selectedButton.end.call(navigation, clickEvent, navigation.currentUserDetails);
  5496. }
  5497. }
  5498. }
  5499. else {
  5500. navigation.nextEvent(clickEvent, navigation.currentUserDetails);
  5501. if (navigation.steps) {
  5502. navigation.stepIndex++;
  5503. if (selectedButton.steps[navigation.stepIndex]) {
  5504. // If we have more steps, bind them one by one:
  5505. navigation.mouseMoveEvent = navigation.nextEvent =
  5506. selectedButton.steps[navigation.stepIndex];
  5507. }
  5508. else {
  5509. fireEvent(navigation, 'deselectButton', { button: navigation.selectedButtonElement });
  5510. svgContainer.removeClass(PREFIX + 'draw-mode');
  5511. // That was the last step, call end():
  5512. if (selectedButton.end) {
  5513. selectedButton.end.call(navigation, clickEvent, navigation.currentUserDetails);
  5514. }
  5515. navigation.nextEvent = false;
  5516. navigation.mouseMoveEvent = false;
  5517. navigation.selectedButton = null;
  5518. }
  5519. }
  5520. }
  5521. };
  5522. /**
  5523. * Hook for mouse move on a chart's container. It calls current step.
  5524. *
  5525. * @private
  5526. * @function Highcharts.NavigationBindings#bindingsContainerMouseMove
  5527. *
  5528. * @param {Highcharts.HTMLDOMElement} container
  5529. * Chart's container.
  5530. *
  5531. * @param {global.Event} moveEvent
  5532. * Browser's move event.
  5533. */
  5534. NavigationBindings.prototype.bindingsContainerMouseMove = function (_container, moveEvent) {
  5535. if (this.mouseMoveEvent) {
  5536. this.mouseMoveEvent(moveEvent, this.currentUserDetails);
  5537. }
  5538. };
  5539. /**
  5540. * Translate fields (e.g. `params.period` or `marker.styles.color`) to
  5541. * Highcharts options object (e.g. `{ params: { period } }`).
  5542. *
  5543. * @private
  5544. * @function Highcharts.NavigationBindings#fieldsToOptions<T>
  5545. *
  5546. * @param {Highcharts.Dictionary<string>} fields
  5547. * Fields from popup form.
  5548. *
  5549. * @param {T} config
  5550. * Default config to be modified.
  5551. *
  5552. * @return {T}
  5553. * Modified config
  5554. */
  5555. NavigationBindings.prototype.fieldsToOptions = function (fields, config) {
  5556. objectEach(fields, function (value, field) {
  5557. var parsedValue = parseFloat(value), path = field.split('.'), parent = config, pathLength = path.length - 1;
  5558. // If it's a number (not "format" options), parse it:
  5559. if (isNumber(parsedValue) &&
  5560. !value.match(/px/g) &&
  5561. !field.match(/format/g)) {
  5562. value = parsedValue;
  5563. }
  5564. // Remove empty strings or values like 0
  5565. if (value !== '' && value !== 'undefined') {
  5566. path.forEach(function (name, index) {
  5567. var nextName = pick(path[index + 1], '');
  5568. if (pathLength === index) {
  5569. // Last index, put value:
  5570. parent[name] = value;
  5571. }
  5572. else if (!parent[name]) {
  5573. // Create middle property:
  5574. parent[name] = nextName.match(/\d/g) ? [] : {};
  5575. parent = parent[name];
  5576. }
  5577. else {
  5578. // Jump into next property
  5579. parent = parent[name];
  5580. }
  5581. });
  5582. }
  5583. });
  5584. return config;
  5585. };
  5586. /**
  5587. * Shorthand method to deselect an annotation.
  5588. *
  5589. * @function Highcharts.NavigationBindings#deselectAnnotation
  5590. */
  5591. NavigationBindings.prototype.deselectAnnotation = function () {
  5592. if (this.activeAnnotation) {
  5593. this.activeAnnotation.setControlPointsVisibility(false);
  5594. this.activeAnnotation = false;
  5595. }
  5596. };
  5597. /**
  5598. * Generates API config for popup in the same format as options for
  5599. * Annotation object.
  5600. *
  5601. * @function Highcharts.NavigationBindings#annotationToFields
  5602. *
  5603. * @param {Highcharts.Annotation} annotation
  5604. * Annotations object
  5605. *
  5606. * @return {Highcharts.Dictionary<string>}
  5607. * Annotation options to be displayed in popup box
  5608. */
  5609. NavigationBindings.prototype.annotationToFields = function (annotation) {
  5610. var options = annotation.options, editables = NavigationBindings.annotationsEditable, nestedEditables = editables.nestedOptions, getFieldType = this.utils.getFieldType, type = pick(options.type, options.shapes && options.shapes[0] &&
  5611. options.shapes[0].type, options.labels && options.labels[0] &&
  5612. options.labels[0].itemType, 'label'), nonEditables = NavigationBindings.annotationsNonEditable[options.langKey] || [], visualOptions = {
  5613. langKey: options.langKey,
  5614. type: type
  5615. };
  5616. /**
  5617. * Nested options traversing. Method goes down to the options and copies
  5618. * allowed options (with values) to new object, which is last parameter:
  5619. * "parent".
  5620. *
  5621. * @private
  5622. *
  5623. * @param {*} option
  5624. * Atomic type or object/array
  5625. *
  5626. * @param {string} key
  5627. * Option name, for example "visible" or "x", "y"
  5628. *
  5629. * @param {object} parentEditables
  5630. * Editables from NavigationBindings.annotationsEditable
  5631. *
  5632. * @param {object} parent
  5633. * Where new options will be assigned
  5634. */
  5635. function traverse(option, key, parentEditables, parent) {
  5636. var nextParent;
  5637. if (parentEditables &&
  5638. nonEditables.indexOf(key) === -1 &&
  5639. ((parentEditables.indexOf &&
  5640. parentEditables.indexOf(key)) >= 0 ||
  5641. parentEditables[key] || // nested array
  5642. parentEditables === true // simple array
  5643. )) {
  5644. // Roots:
  5645. if (isArray(option)) {
  5646. parent[key] = [];
  5647. option.forEach(function (arrayOption, i) {
  5648. if (!isObject(arrayOption)) {
  5649. // Simple arrays, e.g. [String, Number, Boolean]
  5650. traverse(arrayOption, 0, nestedEditables[key], parent[key]);
  5651. }
  5652. else {
  5653. // Advanced arrays, e.g. [Object, Object]
  5654. parent[key][i] = {};
  5655. objectEach(arrayOption, function (nestedOption, nestedKey) {
  5656. traverse(nestedOption, nestedKey, nestedEditables[key], parent[key][i]);
  5657. });
  5658. }
  5659. });
  5660. }
  5661. else if (isObject(option)) {
  5662. nextParent = {};
  5663. if (isArray(parent)) {
  5664. parent.push(nextParent);
  5665. nextParent[key] = {};
  5666. nextParent = nextParent[key];
  5667. }
  5668. else {
  5669. parent[key] = nextParent;
  5670. }
  5671. objectEach(option, function (nestedOption, nestedKey) {
  5672. traverse(nestedOption, nestedKey, key === 0 ? parentEditables : nestedEditables[key], nextParent);
  5673. });
  5674. }
  5675. else {
  5676. // Leaf:
  5677. if (key === 'format') {
  5678. parent[key] = [
  5679. format(option, annotation.labels[0].points[0]).toString(),
  5680. 'text'
  5681. ];
  5682. }
  5683. else if (isArray(parent)) {
  5684. parent.push([option, getFieldType(option)]);
  5685. }
  5686. else {
  5687. parent[key] = [option, getFieldType(option)];
  5688. }
  5689. }
  5690. }
  5691. }
  5692. objectEach(options, function (option, key) {
  5693. if (key === 'typeOptions') {
  5694. visualOptions[key] = {};
  5695. objectEach(options[key], function (typeOption, typeKey) {
  5696. traverse(typeOption, typeKey, nestedEditables, visualOptions[key], true);
  5697. });
  5698. }
  5699. else {
  5700. traverse(option, key, editables[type], visualOptions);
  5701. }
  5702. });
  5703. return visualOptions;
  5704. };
  5705. /**
  5706. * Get all class names for all parents in the element. Iterates until finds
  5707. * main container.
  5708. *
  5709. * @function Highcharts.NavigationBindings#getClickedClassNames
  5710. *
  5711. * @param {Highcharts.HTMLDOMElement}
  5712. * Container that event is bound to.
  5713. *
  5714. * @param {global.Event} event
  5715. * Browser's event.
  5716. *
  5717. * @return {Array<Array<string, Highcharts.HTMLDOMElement>>}
  5718. * Array of class names with corresponding elements
  5719. */
  5720. NavigationBindings.prototype.getClickedClassNames = function (container, event) {
  5721. var element = event.target, classNames = [], elemClassName;
  5722. while (element) {
  5723. elemClassName = attr(element, 'class');
  5724. if (elemClassName) {
  5725. classNames = classNames.concat(elemClassName
  5726. .split(' ')
  5727. .map(function (name) {
  5728. return [
  5729. name,
  5730. element
  5731. ];
  5732. }));
  5733. }
  5734. element = element.parentNode;
  5735. if (element === container) {
  5736. return classNames;
  5737. }
  5738. }
  5739. return classNames;
  5740. };
  5741. /**
  5742. * Get events bound to a button. It's a custom event delegation to find all
  5743. * events connected to the element.
  5744. *
  5745. * @private
  5746. * @function Highcharts.NavigationBindings#getButtonEvents
  5747. *
  5748. * @param {Highcharts.HTMLDOMElement} container
  5749. * Container that event is bound to.
  5750. *
  5751. * @param {global.Event} event
  5752. * Browser's event.
  5753. *
  5754. * @return {object}
  5755. * Object with events (init, start, steps, and end)
  5756. */
  5757. NavigationBindings.prototype.getButtonEvents = function (container, event) {
  5758. var navigation = this, classNames = this.getClickedClassNames(container, event), bindings;
  5759. classNames.forEach(function (className) {
  5760. if (navigation.boundClassNames[className[0]] && !bindings) {
  5761. bindings = {
  5762. events: navigation.boundClassNames[className[0]],
  5763. button: className[1]
  5764. };
  5765. }
  5766. });
  5767. return bindings;
  5768. };
  5769. /**
  5770. * Bindings are just events, so the whole update process is simply
  5771. * removing old events and adding new ones.
  5772. *
  5773. * @private
  5774. * @function Highcharts.NavigationBindings#update
  5775. */
  5776. NavigationBindings.prototype.update = function (options) {
  5777. this.options = merge(true, this.options, options);
  5778. this.removeEvents();
  5779. this.initEvents();
  5780. };
  5781. /**
  5782. * Remove all events created in the navigation.
  5783. *
  5784. * @private
  5785. * @function Highcharts.NavigationBindings#removeEvents
  5786. */
  5787. NavigationBindings.prototype.removeEvents = function () {
  5788. this.eventsToUnbind.forEach(function (unbinder) {
  5789. unbinder();
  5790. });
  5791. };
  5792. NavigationBindings.prototype.destroy = function () {
  5793. this.removeEvents();
  5794. };
  5795. /* *
  5796. *
  5797. * Static Properties
  5798. *
  5799. * */
  5800. // Define which options from annotations should show up in edit box:
  5801. NavigationBindings.annotationsEditable = {
  5802. // `typeOptions` are always available
  5803. // Nested and shared options:
  5804. nestedOptions: {
  5805. labelOptions: ['style', 'format', 'backgroundColor'],
  5806. labels: ['style'],
  5807. label: ['style'],
  5808. style: ['fontSize', 'color'],
  5809. background: ['fill', 'strokeWidth', 'stroke'],
  5810. innerBackground: ['fill', 'strokeWidth', 'stroke'],
  5811. outerBackground: ['fill', 'strokeWidth', 'stroke'],
  5812. shapeOptions: ['fill', 'strokeWidth', 'stroke'],
  5813. shapes: ['fill', 'strokeWidth', 'stroke'],
  5814. line: ['strokeWidth', 'stroke'],
  5815. backgroundColors: [true],
  5816. connector: ['fill', 'strokeWidth', 'stroke'],
  5817. crosshairX: ['strokeWidth', 'stroke'],
  5818. crosshairY: ['strokeWidth', 'stroke']
  5819. },
  5820. // Simple shapes:
  5821. circle: ['shapes'],
  5822. verticalLine: [],
  5823. label: ['labelOptions'],
  5824. // Measure
  5825. measure: ['background', 'crosshairY', 'crosshairX'],
  5826. // Others:
  5827. fibonacci: [],
  5828. tunnel: ['background', 'line', 'height'],
  5829. pitchfork: ['innerBackground', 'outerBackground'],
  5830. rect: ['shapes'],
  5831. // Crooked lines, elliots, arrows etc:
  5832. crookedLine: [],
  5833. basicAnnotation: []
  5834. };
  5835. // Define non editable fields per annotation, for example Rectangle inherits
  5836. // options from Measure, but crosshairs are not available
  5837. NavigationBindings.annotationsNonEditable = {
  5838. rectangle: ['crosshairX', 'crosshairY', 'label']
  5839. };
  5840. return NavigationBindings;
  5841. }());
  5842. /**
  5843. * General utils for bindings
  5844. *
  5845. * @private
  5846. * @name Highcharts.NavigationBindings.utils
  5847. * @type {bindingsUtils}
  5848. */
  5849. NavigationBindings.prototype.utils = bindingsUtils;
  5850. H.Chart.prototype.initNavigationBindings = function () {
  5851. var chart = this, options = chart.options;
  5852. if (options && options.navigation && options.navigation.bindings) {
  5853. chart.navigationBindings = new NavigationBindings(chart, options.navigation);
  5854. chart.navigationBindings.initEvents();
  5855. chart.navigationBindings.initUpdate();
  5856. }
  5857. };
  5858. addEvent(H.Chart, 'load', function () {
  5859. this.initNavigationBindings();
  5860. });
  5861. addEvent(H.Chart, 'destroy', function () {
  5862. if (this.navigationBindings) {
  5863. this.navigationBindings.destroy();
  5864. }
  5865. });
  5866. addEvent(NavigationBindings, 'deselectButton', function () {
  5867. this.selectedButtonElement = null;
  5868. });
  5869. addEvent(Annotation, 'remove', function () {
  5870. if (this.chart.navigationBindings) {
  5871. this.chart.navigationBindings.deselectAnnotation();
  5872. }
  5873. });
  5874. /**
  5875. * Show edit-annotation form:
  5876. * @private
  5877. */
  5878. function selectableAnnotation(annotationType) {
  5879. var originalClick = annotationType.prototype.defaultOptions.events &&
  5880. annotationType.prototype.defaultOptions.events.click;
  5881. /**
  5882. * @private
  5883. */
  5884. function selectAndshowPopup(event) {
  5885. var annotation = this, navigation = annotation.chart.navigationBindings, prevAnnotation = navigation.activeAnnotation;
  5886. if (originalClick) {
  5887. originalClick.call(annotation, event);
  5888. }
  5889. if (prevAnnotation !== annotation) {
  5890. // Select current:
  5891. navigation.deselectAnnotation();
  5892. navigation.activeAnnotation = annotation;
  5893. annotation.setControlPointsVisibility(true);
  5894. fireEvent(navigation, 'showPopup', {
  5895. annotation: annotation,
  5896. formType: 'annotation-toolbar',
  5897. options: navigation.annotationToFields(annotation),
  5898. onSubmit: function (data) {
  5899. var config = {}, typeOptions;
  5900. if (data.actionType === 'remove') {
  5901. navigation.activeAnnotation = false;
  5902. navigation.chart.removeAnnotation(annotation);
  5903. }
  5904. else {
  5905. navigation.fieldsToOptions(data.fields, config);
  5906. navigation.deselectAnnotation();
  5907. typeOptions = config.typeOptions;
  5908. if (annotation.options.type === 'measure') {
  5909. // Manually disable crooshars according to
  5910. // stroke width of the shape:
  5911. typeOptions.crosshairY.enabled =
  5912. typeOptions.crosshairY.strokeWidth !== 0;
  5913. typeOptions.crosshairX.enabled =
  5914. typeOptions.crosshairX.strokeWidth !== 0;
  5915. }
  5916. annotation.update(config);
  5917. }
  5918. }
  5919. });
  5920. }
  5921. else {
  5922. // Deselect current:
  5923. navigation.deselectAnnotation();
  5924. fireEvent(navigation, 'closePopup');
  5925. }
  5926. // Let bubble event to chart.click:
  5927. event.activeAnnotation = true;
  5928. }
  5929. merge(true, annotationType.prototype.defaultOptions.events, {
  5930. click: selectAndshowPopup
  5931. });
  5932. }
  5933. if (H.Annotation) {
  5934. // Basic shapes:
  5935. selectableAnnotation(Annotation);
  5936. // Advanced annotations:
  5937. objectEach(Annotation.types, function (annotationType) {
  5938. selectableAnnotation(annotationType);
  5939. });
  5940. }
  5941. setOptions({
  5942. /**
  5943. * @optionparent lang
  5944. *
  5945. * @private
  5946. */
  5947. lang: {
  5948. /**
  5949. * Configure the Popup strings in the chart. Requires the
  5950. * `annotations.js` or `annotations-advanced.src.js` module to be
  5951. * loaded.
  5952. *
  5953. * @since 7.0.0
  5954. * @product highcharts highstock
  5955. */
  5956. navigation: {
  5957. /**
  5958. * Translations for all field names used in popup.
  5959. *
  5960. * @product highcharts highstock
  5961. */
  5962. popup: {
  5963. simpleShapes: 'Simple shapes',
  5964. lines: 'Lines',
  5965. circle: 'Circle',
  5966. rectangle: 'Rectangle',
  5967. label: 'Label',
  5968. shapeOptions: 'Shape options',
  5969. typeOptions: 'Details',
  5970. fill: 'Fill',
  5971. format: 'Text',
  5972. strokeWidth: 'Line width',
  5973. stroke: 'Line color',
  5974. title: 'Title',
  5975. name: 'Name',
  5976. labelOptions: 'Label options',
  5977. labels: 'Labels',
  5978. backgroundColor: 'Background color',
  5979. backgroundColors: 'Background colors',
  5980. borderColor: 'Border color',
  5981. borderRadius: 'Border radius',
  5982. borderWidth: 'Border width',
  5983. style: 'Style',
  5984. padding: 'Padding',
  5985. fontSize: 'Font size',
  5986. color: 'Color',
  5987. height: 'Height',
  5988. shapes: 'Shape options'
  5989. }
  5990. }
  5991. },
  5992. /**
  5993. * @optionparent navigation
  5994. * @product highcharts highstock
  5995. *
  5996. * @private
  5997. */
  5998. navigation: {
  5999. /**
  6000. * A CSS class name where all bindings will be attached to. Multiple
  6001. * charts on the same page should have separate class names to prevent
  6002. * duplicating events.
  6003. *
  6004. * Default value of versions < 7.0.4 `highcharts-bindings-wrapper`
  6005. *
  6006. * @since 7.0.0
  6007. * @type {string}
  6008. */
  6009. bindingsClassName: 'highcharts-bindings-container',
  6010. /**
  6011. * Bindings definitions for custom HTML buttons. Each binding implements
  6012. * simple event-driven interface:
  6013. *
  6014. * - `className`: classname used to bind event to
  6015. *
  6016. * - `init`: initial event, fired on button click
  6017. *
  6018. * - `start`: fired on first click on a chart
  6019. *
  6020. * - `steps`: array of sequential events fired one after another on each
  6021. * of users clicks
  6022. *
  6023. * - `end`: last event to be called after last step event
  6024. *
  6025. * @type {Highcharts.Dictionary<Highcharts.NavigationBindingsOptionsObject>|*}
  6026. * @sample stock/stocktools/stocktools-thresholds
  6027. * Custom bindings in Highstock
  6028. * @since 7.0.0
  6029. * @product highcharts highstock
  6030. */
  6031. bindings: {
  6032. /**
  6033. * A circle annotation bindings. Includes `start` and one event in
  6034. * `steps` array.
  6035. *
  6036. * @type {Highcharts.NavigationBindingsOptionsObject}
  6037. * @default {"className": "highcharts-circle-annotation", "start": function() {}, "steps": [function() {}], "annotationsOptions": {}}
  6038. */
  6039. circleAnnotation: {
  6040. /** @ignore-option */
  6041. className: 'highcharts-circle-annotation',
  6042. /** @ignore-option */
  6043. start: function (e) {
  6044. var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation;
  6045. return this.chart.addAnnotation(merge({
  6046. langKey: 'circle',
  6047. type: 'basicAnnotation',
  6048. shapes: [{
  6049. type: 'circle',
  6050. point: {
  6051. xAxis: 0,
  6052. yAxis: 0,
  6053. x: coords.xAxis[0].value,
  6054. y: coords.yAxis[0].value
  6055. },
  6056. r: 5
  6057. }]
  6058. }, navigation
  6059. .annotationsOptions, navigation
  6060. .bindings
  6061. .circleAnnotation
  6062. .annotationsOptions));
  6063. },
  6064. /** @ignore-option */
  6065. steps: [
  6066. function (e, annotation) {
  6067. var point = annotation.options.shapes[0].point, x = this.chart.xAxis[0].toPixels(point.x), y = this.chart.yAxis[0].toPixels(point.y), inverted = this.chart.inverted, distance = Math.max(Math.sqrt(Math.pow(inverted ? y - e.chartX : x - e.chartX, 2) +
  6068. Math.pow(inverted ? x - e.chartY : y - e.chartY, 2)), 5);
  6069. annotation.update({
  6070. shapes: [{
  6071. r: distance
  6072. }]
  6073. });
  6074. }
  6075. ]
  6076. },
  6077. /**
  6078. * A rectangle annotation bindings. Includes `start` and one event
  6079. * in `steps` array.
  6080. *
  6081. * @type {Highcharts.NavigationBindingsOptionsObject}
  6082. * @default {"className": "highcharts-rectangle-annotation", "start": function() {}, "steps": [function() {}], "annotationsOptions": {}}
  6083. */
  6084. rectangleAnnotation: {
  6085. /** @ignore-option */
  6086. className: 'highcharts-rectangle-annotation',
  6087. /** @ignore-option */
  6088. start: function (e) {
  6089. var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation, x = coords.xAxis[0].value, y = coords.yAxis[0].value;
  6090. return this.chart.addAnnotation(merge({
  6091. langKey: 'rectangle',
  6092. type: 'basicAnnotation',
  6093. shapes: [{
  6094. type: 'path',
  6095. points: [{
  6096. xAxis: 0,
  6097. yAxis: 0,
  6098. x: x,
  6099. y: y
  6100. }, {
  6101. xAxis: 0,
  6102. yAxis: 0,
  6103. x: x,
  6104. y: y
  6105. }, {
  6106. xAxis: 0,
  6107. yAxis: 0,
  6108. x: x,
  6109. y: y
  6110. }, {
  6111. xAxis: 0,
  6112. yAxis: 0,
  6113. x: x,
  6114. y: y
  6115. }]
  6116. }]
  6117. }, navigation
  6118. .annotationsOptions, navigation
  6119. .bindings
  6120. .rectangleAnnotation
  6121. .annotationsOptions));
  6122. },
  6123. /** @ignore-option */
  6124. steps: [
  6125. function (e, annotation) {
  6126. var points = annotation.options.shapes[0].points, coords = this.chart.pointer.getCoordinates(e), x = coords.xAxis[0].value, y = coords.yAxis[0].value;
  6127. // Top right point
  6128. points[1].x = x;
  6129. // Bottom right point (cursor position)
  6130. points[2].x = x;
  6131. points[2].y = y;
  6132. // Bottom left
  6133. points[3].y = y;
  6134. annotation.update({
  6135. shapes: [{
  6136. points: points
  6137. }]
  6138. });
  6139. }
  6140. ]
  6141. },
  6142. /**
  6143. * A label annotation bindings. Includes `start` event only.
  6144. *
  6145. * @type {Highcharts.NavigationBindingsOptionsObject}
  6146. * @default {"className": "highcharts-label-annotation", "start": function() {}, "steps": [function() {}], "annotationsOptions": {}}
  6147. */
  6148. labelAnnotation: {
  6149. /** @ignore-option */
  6150. className: 'highcharts-label-annotation',
  6151. /** @ignore-option */
  6152. start: function (e) {
  6153. var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation;
  6154. return this.chart.addAnnotation(merge({
  6155. langKey: 'label',
  6156. type: 'basicAnnotation',
  6157. labelOptions: {
  6158. format: '{y:.2f}'
  6159. },
  6160. labels: [{
  6161. point: {
  6162. xAxis: 0,
  6163. yAxis: 0,
  6164. x: coords.xAxis[0].value,
  6165. y: coords.yAxis[0].value
  6166. },
  6167. overflow: 'none',
  6168. crop: true
  6169. }]
  6170. }, navigation
  6171. .annotationsOptions, navigation
  6172. .bindings
  6173. .labelAnnotation
  6174. .annotationsOptions));
  6175. }
  6176. }
  6177. },
  6178. /**
  6179. * Path where Highcharts will look for icons. Change this to use icons
  6180. * from a different server.
  6181. *
  6182. * @type {string}
  6183. * @default https://code.highcharts.com/8.1.2/gfx/stock-icons/
  6184. * @since 7.1.3
  6185. * @apioption navigation.iconsURL
  6186. */
  6187. /**
  6188. * A `showPopup` event. Fired when selecting for example an annotation.
  6189. *
  6190. * @type {Function}
  6191. * @apioption navigation.events.showPopup
  6192. */
  6193. /**
  6194. * A `closePopup` event. Fired when Popup should be hidden, for example
  6195. * when clicking on an annotation again.
  6196. *
  6197. * @type {Function}
  6198. * @apioption navigation.events.closePopup
  6199. */
  6200. /**
  6201. * Event fired on a button click.
  6202. *
  6203. * @type {Function}
  6204. * @sample highcharts/annotations/gui/
  6205. * Change icon in a dropddown on event
  6206. * @sample highcharts/annotations/gui-buttons/
  6207. * Change button class on event
  6208. * @apioption navigation.events.selectButton
  6209. */
  6210. /**
  6211. * Event fired when button state should change, for example after
  6212. * adding an annotation.
  6213. *
  6214. * @type {Function}
  6215. * @sample highcharts/annotations/gui/
  6216. * Change icon in a dropddown on event
  6217. * @sample highcharts/annotations/gui-buttons/
  6218. * Change button class on event
  6219. * @apioption navigation.events.deselectButton
  6220. */
  6221. /**
  6222. * Events to communicate between Stock Tools and custom GUI.
  6223. *
  6224. * @since 7.0.0
  6225. * @product highcharts highstock
  6226. * @optionparent navigation.events
  6227. */
  6228. events: {},
  6229. /**
  6230. * Additional options to be merged into all annotations.
  6231. *
  6232. * @sample stock/stocktools/navigation-annotation-options
  6233. * Set red color of all line annotations
  6234. *
  6235. * @type {Highcharts.AnnotationsOptions}
  6236. * @extends annotations
  6237. * @exclude crookedLine, elliottWave, fibonacci, infinityLine,
  6238. * measure, pitchfork, tunnel, verticalLine, basicAnnotation
  6239. * @apioption navigation.annotationsOptions
  6240. */
  6241. annotationsOptions: {}
  6242. }
  6243. });
  6244. return NavigationBindings;
  6245. });
  6246. _registerModule(_modules, 'annotations/popup.js', [_modules['parts/Globals.js'], _modules['annotations/navigationBindings.js'], _modules['parts/Pointer.js'], _modules['parts/Utilities.js']], function (H, NavigationBindings, Pointer, U) {
  6247. /* *
  6248. *
  6249. * Popup generator for Stock tools
  6250. *
  6251. * (c) 2009-2017 Sebastian Bochan
  6252. *
  6253. * License: www.highcharts.com/license
  6254. *
  6255. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  6256. *
  6257. * */
  6258. var addEvent = U.addEvent, createElement = U.createElement, defined = U.defined, getOptions = U.getOptions, isArray = U.isArray, isObject = U.isObject, isString = U.isString, objectEach = U.objectEach, pick = U.pick, wrap = U.wrap;
  6259. var indexFilter = /\d/g, PREFIX = 'highcharts-', DIV = 'div', INPUT = 'input', LABEL = 'label', BUTTON = 'button', SELECT = 'select', OPTION = 'option', SPAN = 'span', UL = 'ul', LI = 'li', H3 = 'h3';
  6260. /* eslint-disable no-invalid-this, valid-jsdoc */
  6261. // onContainerMouseDown blocks internal popup events, due to e.preventDefault.
  6262. // Related issue #4606
  6263. wrap(Pointer.prototype, 'onContainerMouseDown', function (proceed, e) {
  6264. var popupClass = e.target && e.target.className;
  6265. // elements is not in popup
  6266. if (!(isString(popupClass) &&
  6267. popupClass.indexOf(PREFIX + 'popup-field') >= 0)) {
  6268. proceed.apply(this, Array.prototype.slice.call(arguments, 1));
  6269. }
  6270. });
  6271. H.Popup = function (parentDiv, iconsURL) {
  6272. this.init(parentDiv, iconsURL);
  6273. };
  6274. H.Popup.prototype = {
  6275. /**
  6276. * Initialize the popup. Create base div and add close button.
  6277. * @private
  6278. * @param {Highcharts.HTMLDOMElement} parentDiv
  6279. * Container where popup should be placed
  6280. * @param {string} iconsURL
  6281. * Icon URL
  6282. */
  6283. init: function (parentDiv, iconsURL) {
  6284. // create popup div
  6285. this.container = createElement(DIV, {
  6286. className: PREFIX + 'popup'
  6287. }, null, parentDiv);
  6288. this.lang = this.getLangpack();
  6289. this.iconsURL = iconsURL;
  6290. // add close button
  6291. this.addCloseBtn();
  6292. },
  6293. /**
  6294. * Create HTML element and attach click event (close popup).
  6295. * @private
  6296. */
  6297. addCloseBtn: function () {
  6298. var _self = this, closeBtn;
  6299. // create close popup btn
  6300. closeBtn = createElement(DIV, {
  6301. className: PREFIX + 'popup-close'
  6302. }, null, this.container);
  6303. closeBtn.style['background-image'] = 'url(' +
  6304. this.iconsURL + 'close.svg)';
  6305. ['click', 'touchstart'].forEach(function (eventName) {
  6306. addEvent(closeBtn, eventName, function () {
  6307. _self.closePopup();
  6308. });
  6309. });
  6310. },
  6311. /**
  6312. * Create two columns (divs) in HTML.
  6313. * @private
  6314. * @param {Highcharts.HTMLDOMElement} container
  6315. * Container of columns
  6316. * @return {Highcharts.Dictionary<Highcharts.HTMLDOMElement>}
  6317. * Reference to two HTML columns (lhsCol, rhsCol)
  6318. */
  6319. addColsContainer: function (container) {
  6320. var rhsCol, lhsCol;
  6321. // left column
  6322. lhsCol = createElement(DIV, {
  6323. className: PREFIX + 'popup-lhs-col'
  6324. }, null, container);
  6325. // right column
  6326. rhsCol = createElement(DIV, {
  6327. className: PREFIX + 'popup-rhs-col'
  6328. }, null, container);
  6329. // wrapper content
  6330. createElement(DIV, {
  6331. className: PREFIX + 'popup-rhs-col-wrapper'
  6332. }, null, rhsCol);
  6333. return {
  6334. lhsCol: lhsCol,
  6335. rhsCol: rhsCol
  6336. };
  6337. },
  6338. /**
  6339. * Create input with label.
  6340. * @private
  6341. * @param {string} option
  6342. * Chain of fields i.e params.styles.fontSize
  6343. * @param {string} type
  6344. * Indicator type
  6345. * @param {Highhcharts.HTMLDOMElement}
  6346. * Container where elements should be added
  6347. * @param {string} value
  6348. * Default value of input i.e period value is 14, extracted from
  6349. * defaultOptions (ADD mode) or series options (EDIT mode)
  6350. */
  6351. addInput: function (option, type, parentDiv, value) {
  6352. var optionParamList = option.split('.'), optionName = optionParamList[optionParamList.length - 1], lang = this.lang, inputName = PREFIX + type + '-' + optionName;
  6353. if (!inputName.match(indexFilter)) {
  6354. // add label
  6355. createElement(LABEL, {
  6356. innerHTML: lang[optionName] || optionName,
  6357. htmlFor: inputName
  6358. }, null, parentDiv);
  6359. }
  6360. // add input
  6361. createElement(INPUT, {
  6362. name: inputName,
  6363. value: value[0],
  6364. type: value[1],
  6365. className: PREFIX + 'popup-field'
  6366. }, null, parentDiv).setAttribute(PREFIX + 'data-name', option);
  6367. },
  6368. /**
  6369. * Create button.
  6370. * @private
  6371. * @param {Highcharts.HTMLDOMElement} parentDiv
  6372. * Container where elements should be added
  6373. * @param {string} label
  6374. * Text placed as button label
  6375. * @param {string} type
  6376. * add | edit | remove
  6377. * @param {Function} callback
  6378. * On click callback
  6379. * @param {Highcharts.HTMLDOMElement} fieldsDiv
  6380. * Container where inputs are generated
  6381. * @return {Highcharts.HTMLDOMElement}
  6382. * HTML button
  6383. */
  6384. addButton: function (parentDiv, label, type, callback, fieldsDiv) {
  6385. var _self = this, closePopup = this.closePopup, getFields = this.getFields, button;
  6386. button = createElement(BUTTON, {
  6387. innerHTML: label
  6388. }, null, parentDiv);
  6389. ['click', 'touchstart'].forEach(function (eventName) {
  6390. addEvent(button, eventName, function () {
  6391. closePopup.call(_self);
  6392. return callback(getFields(fieldsDiv, type));
  6393. });
  6394. });
  6395. return button;
  6396. },
  6397. /**
  6398. * Get values from all inputs and create JSON.
  6399. * @private
  6400. * @param {Highcharts.HTMLDOMElement} - container where inputs are created
  6401. * @param {string} - add | edit | remove
  6402. * @return {Highcharts.PopupFieldsObject} - fields
  6403. */
  6404. getFields: function (parentDiv, type) {
  6405. var inputList = parentDiv.querySelectorAll('input'), optionSeries = '#' + PREFIX + 'select-series > option:checked', optionVolume = '#' + PREFIX + 'select-volume > option:checked', linkedTo = parentDiv.querySelectorAll(optionSeries)[0], volumeTo = parentDiv.querySelectorAll(optionVolume)[0], seriesId, param, fieldsOutput;
  6406. fieldsOutput = {
  6407. actionType: type,
  6408. linkedTo: linkedTo && linkedTo.getAttribute('value'),
  6409. fields: {}
  6410. };
  6411. [].forEach.call(inputList, function (input) {
  6412. param = input.getAttribute(PREFIX + 'data-name');
  6413. seriesId = input.getAttribute(PREFIX + 'data-series-id');
  6414. // params
  6415. if (seriesId) {
  6416. fieldsOutput.seriesId = input.value;
  6417. }
  6418. else if (param) {
  6419. fieldsOutput.fields[param] = input.value;
  6420. }
  6421. else {
  6422. // type like sma / ema
  6423. fieldsOutput.type = input.value;
  6424. }
  6425. });
  6426. if (volumeTo) {
  6427. fieldsOutput.fields['params.volumeSeriesID'] = volumeTo.getAttribute('value');
  6428. }
  6429. return fieldsOutput;
  6430. },
  6431. /**
  6432. * Reset content of the current popup and show.
  6433. * @private
  6434. */
  6435. showPopup: function () {
  6436. var popupDiv = this.container, toolbarClass = PREFIX + 'annotation-toolbar', popupCloseBtn = popupDiv
  6437. .querySelectorAll('.' + PREFIX + 'popup-close')[0];
  6438. // reset content
  6439. popupDiv.innerHTML = '';
  6440. // reset toolbar styles if exists
  6441. if (popupDiv.className.indexOf(toolbarClass) >= 0) {
  6442. popupDiv.classList.remove(toolbarClass);
  6443. // reset toolbar inline styles
  6444. popupDiv.removeAttribute('style');
  6445. }
  6446. // add close button
  6447. popupDiv.appendChild(popupCloseBtn);
  6448. popupDiv.style.display = 'block';
  6449. },
  6450. /**
  6451. * Hide popup.
  6452. * @private
  6453. */
  6454. closePopup: function () {
  6455. this.popup.container.style.display = 'none';
  6456. },
  6457. /**
  6458. * Create content and show popup.
  6459. * @private
  6460. * @param {string} - type of popup i.e indicators
  6461. * @param {Highcharts.Chart} - chart
  6462. * @param {Highcharts.AnnotationsOptions} - options
  6463. * @param {Function} - on click callback
  6464. */
  6465. showForm: function (type, chart, options, callback) {
  6466. this.popup = chart.navigationBindings.popup;
  6467. // show blank popup
  6468. this.showPopup();
  6469. // indicator form
  6470. if (type === 'indicators') {
  6471. this.indicators.addForm.call(this, chart, options, callback);
  6472. }
  6473. // annotation small toolbar
  6474. if (type === 'annotation-toolbar') {
  6475. this.annotations.addToolbar.call(this, chart, options, callback);
  6476. }
  6477. // annotation edit form
  6478. if (type === 'annotation-edit') {
  6479. this.annotations.addForm.call(this, chart, options, callback);
  6480. }
  6481. // flags form - add / edit
  6482. if (type === 'flag') {
  6483. this.annotations.addForm.call(this, chart, options, callback, true);
  6484. }
  6485. },
  6486. /**
  6487. * Return lang definitions for popup.
  6488. * @private
  6489. * @return {Highcharts.Dictionary<string>} - elements translations.
  6490. */
  6491. getLangpack: function () {
  6492. return getOptions().lang.navigation.popup;
  6493. },
  6494. annotations: {
  6495. /**
  6496. * Create annotation simple form. It contains two buttons
  6497. * (edit / remove) and text label.
  6498. * @private
  6499. * @param {Highcharts.Chart} - chart
  6500. * @param {Highcharts.AnnotationsOptions} - options
  6501. * @param {Function} - on click callback
  6502. */
  6503. addToolbar: function (chart, options, callback) {
  6504. var _self = this, lang = this.lang, popupDiv = this.popup.container, showForm = this.showForm, toolbarClass = PREFIX + 'annotation-toolbar', button;
  6505. // set small size
  6506. if (popupDiv.className.indexOf(toolbarClass) === -1) {
  6507. popupDiv.className += ' ' + toolbarClass;
  6508. }
  6509. // set position
  6510. popupDiv.style.top = chart.plotTop + 10 + 'px';
  6511. // create label
  6512. createElement(SPAN, {
  6513. innerHTML: pick(
  6514. // Advanced annotations:
  6515. lang[options.langKey] || options.langKey,
  6516. // Basic shapes:
  6517. options.shapes && options.shapes[0].type)
  6518. }, null, popupDiv);
  6519. // add buttons
  6520. button = this.addButton(popupDiv, lang.removeButton || 'remove', 'remove', callback, popupDiv);
  6521. button.className += ' ' + PREFIX + 'annotation-remove-button';
  6522. button.style['background-image'] = 'url(' +
  6523. this.iconsURL + 'destroy.svg)';
  6524. button = this.addButton(popupDiv, lang.editButton || 'edit', 'edit', function () {
  6525. showForm.call(_self, 'annotation-edit', chart, options, callback);
  6526. }, popupDiv);
  6527. button.className += ' ' + PREFIX + 'annotation-edit-button';
  6528. button.style['background-image'] = 'url(' +
  6529. this.iconsURL + 'edit.svg)';
  6530. },
  6531. /**
  6532. * Create annotation simple form.
  6533. * It contains fields with param names.
  6534. * @private
  6535. * @param {Highcharts.Chart} chart
  6536. * Chart
  6537. * @param {Object} options
  6538. * Options
  6539. * @param {Function} callback
  6540. * On click callback
  6541. * @param {boolean} [isInit]
  6542. * If it is a form declared for init annotation
  6543. */
  6544. addForm: function (chart, options, callback, isInit) {
  6545. var popupDiv = this.popup.container, lang = this.lang, bottomRow, lhsCol;
  6546. // create title of annotations
  6547. lhsCol = createElement('h2', {
  6548. innerHTML: lang[options.langKey] || options.langKey,
  6549. className: PREFIX + 'popup-main-title'
  6550. }, null, popupDiv);
  6551. // left column
  6552. lhsCol = createElement(DIV, {
  6553. className: PREFIX + 'popup-lhs-col ' + PREFIX + 'popup-lhs-full'
  6554. }, null, popupDiv);
  6555. bottomRow = createElement(DIV, {
  6556. className: PREFIX + 'popup-bottom-row'
  6557. }, null, popupDiv);
  6558. this.annotations.addFormFields.call(this, lhsCol, chart, '', options, [], true);
  6559. this.addButton(bottomRow, isInit ?
  6560. (lang.addButton || 'add') :
  6561. (lang.saveButton || 'save'), isInit ? 'add' : 'save', callback, popupDiv);
  6562. },
  6563. /**
  6564. * Create annotation's form fields.
  6565. * @private
  6566. * @param {Highcharts.HTMLDOMElement} parentDiv
  6567. * Div where inputs are placed
  6568. * @param {Highcharts.Chart} chart
  6569. * Chart
  6570. * @param {string} parentNode
  6571. * Name of parent to create chain of names
  6572. * @param {Highcharts.AnnotationsOptions} options
  6573. * Options
  6574. * @param {Array<unknown>} storage
  6575. * Array where all items are stored
  6576. * @param {boolean} [isRoot]
  6577. * Recursive flag for root
  6578. */
  6579. addFormFields: function (parentDiv, chart, parentNode, options, storage, isRoot) {
  6580. var _self = this, addFormFields = this.annotations.addFormFields, addInput = this.addInput, lang = this.lang, parentFullName, titleName;
  6581. objectEach(options, function (value, option) {
  6582. // create name like params.styles.fontSize
  6583. parentFullName = parentNode !== '' ?
  6584. parentNode + '.' + option : option;
  6585. if (isObject(value)) {
  6586. if (
  6587. // value is object of options
  6588. !isArray(value) ||
  6589. // array of objects with params. i.e labels in Fibonacci
  6590. (isArray(value) && isObject(value[0]))) {
  6591. titleName = lang[option] || option;
  6592. if (!titleName.match(indexFilter)) {
  6593. storage.push([
  6594. true,
  6595. titleName,
  6596. parentDiv
  6597. ]);
  6598. }
  6599. addFormFields.call(_self, parentDiv, chart, parentFullName, value, storage, false);
  6600. }
  6601. else {
  6602. storage.push([
  6603. _self,
  6604. parentFullName,
  6605. 'annotation',
  6606. parentDiv,
  6607. value
  6608. ]);
  6609. }
  6610. }
  6611. });
  6612. if (isRoot) {
  6613. storage = storage.sort(function (a) {
  6614. return a[1].match(/format/g) ? -1 : 1;
  6615. });
  6616. storage.forEach(function (genInput) {
  6617. if (genInput[0] === true) {
  6618. createElement(SPAN, {
  6619. className: PREFIX + 'annotation-title',
  6620. innerHTML: genInput[1]
  6621. }, null, genInput[2]);
  6622. }
  6623. else {
  6624. addInput.apply(genInput[0], genInput.splice(1));
  6625. }
  6626. });
  6627. }
  6628. }
  6629. },
  6630. indicators: {
  6631. /**
  6632. * Create indicator's form. It contains two tabs (ADD and EDIT) with
  6633. * content.
  6634. * @private
  6635. */
  6636. addForm: function (chart, _options, callback) {
  6637. var tabsContainers, indicators = this.indicators, lang = this.lang, buttonParentDiv;
  6638. // add tabs
  6639. this.tabs.init.call(this, chart);
  6640. // get all tabs content divs
  6641. tabsContainers = this.popup.container
  6642. .querySelectorAll('.' + PREFIX + 'tab-item-content');
  6643. // ADD tab
  6644. this.addColsContainer(tabsContainers[0]);
  6645. indicators.addIndicatorList.call(this, chart, tabsContainers[0], 'add');
  6646. buttonParentDiv = tabsContainers[0]
  6647. .querySelectorAll('.' + PREFIX + 'popup-rhs-col')[0];
  6648. this.addButton(buttonParentDiv, lang.addButton || 'add', 'add', callback, buttonParentDiv);
  6649. // EDIT tab
  6650. this.addColsContainer(tabsContainers[1]);
  6651. indicators.addIndicatorList.call(this, chart, tabsContainers[1], 'edit');
  6652. buttonParentDiv = tabsContainers[1]
  6653. .querySelectorAll('.' + PREFIX + 'popup-rhs-col')[0];
  6654. this.addButton(buttonParentDiv, lang.saveButton || 'save', 'edit', callback, buttonParentDiv);
  6655. this.addButton(buttonParentDiv, lang.removeButton || 'remove', 'remove', callback, buttonParentDiv);
  6656. },
  6657. /**
  6658. * Create HTML list of all indicators (ADD mode) or added indicators
  6659. * (EDIT mode).
  6660. * @private
  6661. */
  6662. addIndicatorList: function (chart, parentDiv, listType) {
  6663. var _self = this, lhsCol = parentDiv.querySelectorAll('.' + PREFIX + 'popup-lhs-col')[0], rhsCol = parentDiv.querySelectorAll('.' + PREFIX + 'popup-rhs-col')[0], isEdit = listType === 'edit', series = (isEdit ?
  6664. chart.series : // EDIT mode
  6665. chart.options.plotOptions // ADD mode
  6666. ), addFormFields = this.indicators.addFormFields, rhsColWrapper, indicatorList, item;
  6667. // create wrapper for list
  6668. indicatorList = createElement(UL, {
  6669. className: PREFIX + 'indicator-list'
  6670. }, null, lhsCol);
  6671. rhsColWrapper = rhsCol
  6672. .querySelectorAll('.' + PREFIX + 'popup-rhs-col-wrapper')[0];
  6673. objectEach(series, function (serie, value) {
  6674. var seriesOptions = serie.options;
  6675. if (serie.params ||
  6676. seriesOptions && seriesOptions.params) {
  6677. var indicatorNameType = _self.indicators.getNameType(serie, value), indicatorType = indicatorNameType.type;
  6678. item = createElement(LI, {
  6679. className: PREFIX + 'indicator-list',
  6680. innerHTML: indicatorNameType.name
  6681. }, null, indicatorList);
  6682. ['click', 'touchstart'].forEach(function (eventName) {
  6683. addEvent(item, eventName, function () {
  6684. addFormFields.call(_self, chart, isEdit ? serie : series[indicatorType], indicatorNameType.type, rhsColWrapper);
  6685. // add hidden input with series.id
  6686. if (isEdit && serie.options) {
  6687. createElement(INPUT, {
  6688. type: 'hidden',
  6689. name: PREFIX + 'id-' + indicatorType,
  6690. value: serie.options.id
  6691. }, null, rhsColWrapper)
  6692. .setAttribute(PREFIX + 'data-series-id', serie.options.id);
  6693. }
  6694. });
  6695. });
  6696. }
  6697. });
  6698. // select first item from the list
  6699. if (indicatorList.childNodes.length > 0) {
  6700. indicatorList.childNodes[0].click();
  6701. }
  6702. },
  6703. /**
  6704. * Extract full name and type of requested indicator.
  6705. * @private
  6706. * @param {Highcharts.Series} series
  6707. * Series which name is needed. (EDIT mode - defaultOptions.series, ADD
  6708. * mode - indicator series).
  6709. * @param {string} - indicator type like: sma, ema, etc.
  6710. * @return {Object} - series name and type like: sma, ema, etc.
  6711. */
  6712. getNameType: function (series, type) {
  6713. var options = series.options, seriesTypes = H.seriesTypes,
  6714. // add mode
  6715. seriesName = seriesTypes[type] &&
  6716. seriesTypes[type].prototype.nameBase || type.toUpperCase(), seriesType = type;
  6717. // edit
  6718. if (options && options.type) {
  6719. seriesType = series.options.type;
  6720. seriesName = series.name;
  6721. }
  6722. return {
  6723. name: seriesName,
  6724. type: seriesType
  6725. };
  6726. },
  6727. /**
  6728. * List all series with unique ID. Its mandatory for indicators to set
  6729. * correct linking.
  6730. * @private
  6731. * @param {string} type
  6732. * Indicator type like: sma, ema, etc.
  6733. * @param {string} optionName
  6734. * Type of select i.e series or volume.
  6735. * @param {Highcharts.Chart} chart
  6736. * Chart
  6737. * @param {Highcharts.HTMLDOMElement} parentDiv
  6738. * Element where created HTML list is added
  6739. * @param {string} selectedOption
  6740. * optional param for default value in dropdown
  6741. */
  6742. listAllSeries: function (type, optionName, chart, parentDiv, selectedOption) {
  6743. var selectName = PREFIX + optionName + '-type-' + type, lang = this.lang, selectBox, seriesOptions;
  6744. createElement(LABEL, {
  6745. innerHTML: lang[optionName] || optionName,
  6746. htmlFor: selectName
  6747. }, null, parentDiv);
  6748. // select type
  6749. selectBox = createElement(SELECT, {
  6750. name: selectName,
  6751. className: PREFIX + 'popup-field'
  6752. }, null, parentDiv);
  6753. selectBox.setAttribute('id', PREFIX + 'select-' + optionName);
  6754. // list all series which have id - mandatory for creating indicator
  6755. chart.series.forEach(function (serie) {
  6756. seriesOptions = serie.options;
  6757. if (!seriesOptions.params &&
  6758. seriesOptions.id &&
  6759. seriesOptions.id !== PREFIX + 'navigator-series') {
  6760. createElement(OPTION, {
  6761. innerHTML: seriesOptions.name || seriesOptions.id,
  6762. value: seriesOptions.id
  6763. }, null, selectBox);
  6764. }
  6765. });
  6766. if (defined(selectedOption)) {
  6767. selectBox.value = selectedOption;
  6768. }
  6769. },
  6770. /**
  6771. * Create typical inputs for chosen indicator. Fields are extracted from
  6772. * defaultOptions (ADD mode) or current indicator (ADD mode). Two extra
  6773. * fields are added:
  6774. * - hidden input - contains indicator type (required for callback)
  6775. * - select - list of series which can be linked with indicator
  6776. * @private
  6777. * @param {Highcharts.Chart} chart
  6778. * Chart
  6779. * @param {Highcharts.Series} series
  6780. * Indicator
  6781. * @param {string} seriesType
  6782. * Indicator type like: sma, ema, etc.
  6783. * @param {Highcharts.HTMLDOMElement} rhsColWrapper
  6784. * Element where created HTML list is added
  6785. */
  6786. addFormFields: function (chart, series, seriesType, rhsColWrapper) {
  6787. var fields = series.params || series.options.params, getNameType = this.indicators.getNameType;
  6788. // reset current content
  6789. rhsColWrapper.innerHTML = '';
  6790. // create title (indicator name in the right column)
  6791. createElement(H3, {
  6792. className: PREFIX + 'indicator-title',
  6793. innerHTML: getNameType(series, seriesType).name
  6794. }, null, rhsColWrapper);
  6795. // input type
  6796. createElement(INPUT, {
  6797. type: 'hidden',
  6798. name: PREFIX + 'type-' + seriesType,
  6799. value: seriesType
  6800. }, null, rhsColWrapper);
  6801. // list all series with id
  6802. this.indicators.listAllSeries.call(this, seriesType, 'series', chart, rhsColWrapper, series.linkedParent && fields.volumeSeriesID);
  6803. if (fields.volumeSeriesID) {
  6804. this.indicators.listAllSeries.call(this, seriesType, 'volume', chart, rhsColWrapper, series.linkedParent && series.linkedParent.options.id);
  6805. }
  6806. // add param fields
  6807. this.indicators.addParamInputs.call(this, chart, 'params', fields, seriesType, rhsColWrapper);
  6808. },
  6809. /**
  6810. * Recurent function which lists all fields, from params object and
  6811. * create them as inputs. Each input has unique `data-name` attribute,
  6812. * which keeps chain of fields i.e params.styles.fontSize.
  6813. * @private
  6814. * @param {Highcharts.Chart} chart
  6815. * Chart
  6816. * @param {string} parentNode
  6817. * Name of parent to create chain of names
  6818. * @param {Highcharts.PopupFieldsDictionary<string>} fields
  6819. * Params which are based for input create
  6820. * @param {string} type
  6821. * Indicator type like: sma, ema, etc.
  6822. * @param {Highcharts.HTMLDOMElement} parentDiv
  6823. * Element where created HTML list is added
  6824. */
  6825. addParamInputs: function (chart, parentNode, fields, type, parentDiv) {
  6826. var _self = this, addParamInputs = this.indicators.addParamInputs, addInput = this.addInput, parentFullName;
  6827. objectEach(fields, function (value, fieldName) {
  6828. // create name like params.styles.fontSize
  6829. parentFullName = parentNode + '.' + fieldName;
  6830. if (isObject(value)) {
  6831. addParamInputs.call(_self, chart, parentFullName, value, type, parentDiv);
  6832. }
  6833. else if (
  6834. // skip volume field which is created by addFormFields
  6835. parentFullName !== 'params.volumeSeriesID') {
  6836. addInput.call(_self, parentFullName, type, parentDiv, [value, 'text'] // all inputs are text type
  6837. );
  6838. }
  6839. });
  6840. },
  6841. /**
  6842. * Get amount of indicators added to chart.
  6843. * @private
  6844. * @return {number} - Amount of indicators
  6845. */
  6846. getAmount: function () {
  6847. var series = this.series, counter = 0;
  6848. series.forEach(function (serie) {
  6849. var seriesOptions = serie.options;
  6850. if (serie.params ||
  6851. seriesOptions && seriesOptions.params) {
  6852. counter++;
  6853. }
  6854. });
  6855. return counter;
  6856. }
  6857. },
  6858. tabs: {
  6859. /**
  6860. * Init tabs. Create tab menu items, tabs containers
  6861. * @private
  6862. * @param {Highcharts.Chart} chart
  6863. * Reference to current chart
  6864. */
  6865. init: function (chart) {
  6866. var tabs = this.tabs, indicatorsCount = this.indicators.getAmount.call(chart), firstTab; // run by default
  6867. // create menu items
  6868. firstTab = tabs.addMenuItem.call(this, 'add');
  6869. tabs.addMenuItem.call(this, 'edit', indicatorsCount);
  6870. // create tabs containers
  6871. tabs.addContentItem.call(this, 'add');
  6872. tabs.addContentItem.call(this, 'edit');
  6873. tabs.switchTabs.call(this, indicatorsCount);
  6874. // activate first tab
  6875. tabs.selectTab.call(this, firstTab, 0);
  6876. },
  6877. /**
  6878. * Create tab menu item
  6879. * @private
  6880. * @param {string} tabName
  6881. * `add` or `edit`
  6882. * @param {number} [disableTab]
  6883. * Disable tab when 0
  6884. * @return {Highcharts.HTMLDOMElement}
  6885. * Created HTML tab-menu element
  6886. */
  6887. addMenuItem: function (tabName, disableTab) {
  6888. var popupDiv = this.popup.container, className = PREFIX + 'tab-item', lang = this.lang, menuItem;
  6889. if (disableTab === 0) {
  6890. className += ' ' + PREFIX + 'tab-disabled';
  6891. }
  6892. // tab 1
  6893. menuItem = createElement(SPAN, {
  6894. innerHTML: lang[tabName + 'Button'] || tabName,
  6895. className: className
  6896. }, null, popupDiv);
  6897. menuItem.setAttribute(PREFIX + 'data-tab-type', tabName);
  6898. return menuItem;
  6899. },
  6900. /**
  6901. * Create tab content
  6902. * @private
  6903. * @return {HTMLDOMElement} - created HTML tab-content element
  6904. */
  6905. addContentItem: function () {
  6906. var popupDiv = this.popup.container;
  6907. return createElement(DIV, {
  6908. className: PREFIX + 'tab-item-content'
  6909. }, null, popupDiv);
  6910. },
  6911. /**
  6912. * Add click event to each tab
  6913. * @private
  6914. * @param {number} disableTab
  6915. * Disable tab when 0
  6916. */
  6917. switchTabs: function (disableTab) {
  6918. var _self = this, popupDiv = this.popup.container, tabs = popupDiv.querySelectorAll('.' + PREFIX + 'tab-item'), dataParam;
  6919. tabs.forEach(function (tab, i) {
  6920. dataParam = tab.getAttribute(PREFIX + 'data-tab-type');
  6921. if (dataParam === 'edit' && disableTab === 0) {
  6922. return;
  6923. }
  6924. ['click', 'touchstart'].forEach(function (eventName) {
  6925. addEvent(tab, eventName, function () {
  6926. // reset class on other elements
  6927. _self.tabs.deselectAll.call(_self);
  6928. _self.tabs.selectTab.call(_self, this, i);
  6929. });
  6930. });
  6931. });
  6932. },
  6933. /**
  6934. * Set tab as visible
  6935. * @private
  6936. * @param {globals.Element} - current tab
  6937. * @param {number} - Index of tab in menu
  6938. */
  6939. selectTab: function (tab, index) {
  6940. var allTabs = this.popup.container
  6941. .querySelectorAll('.' + PREFIX + 'tab-item-content');
  6942. tab.className += ' ' + PREFIX + 'tab-item-active';
  6943. allTabs[index].className += ' ' + PREFIX + 'tab-item-show';
  6944. },
  6945. /**
  6946. * Set all tabs as invisible.
  6947. * @private
  6948. */
  6949. deselectAll: function () {
  6950. var popupDiv = this.popup.container, tabs = popupDiv
  6951. .querySelectorAll('.' + PREFIX + 'tab-item'), tabsContent = popupDiv
  6952. .querySelectorAll('.' + PREFIX + 'tab-item-content'), i;
  6953. for (i = 0; i < tabs.length; i++) {
  6954. tabs[i].classList.remove(PREFIX + 'tab-item-active');
  6955. tabsContent[i].classList.remove(PREFIX + 'tab-item-show');
  6956. }
  6957. }
  6958. }
  6959. };
  6960. addEvent(NavigationBindings, 'showPopup', function (config) {
  6961. if (!this.popup) {
  6962. // Add popup to main container
  6963. this.popup = new H.Popup(this.chart.container, (this.chart.options.navigation.iconsURL ||
  6964. (this.chart.options.stockTools &&
  6965. this.chart.options.stockTools.gui.iconsURL) ||
  6966. 'https://code.highcharts.com/8.1.2/gfx/stock-icons/'));
  6967. }
  6968. this.popup.showForm(config.formType, this.chart, config.options, config.onSubmit);
  6969. });
  6970. addEvent(NavigationBindings, 'closePopup', function () {
  6971. if (this.popup) {
  6972. this.popup.closePopup();
  6973. }
  6974. });
  6975. });
  6976. _registerModule(_modules, 'masters/modules/annotations-advanced.src.js', [], function () {
  6977. });
  6978. }));