highcharts-android.js.soonsu 181 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529
  1. (function() {
  2. var doc = document,
  3. win = window,
  4. math = Math,
  5. mathRound = math.round,
  6. mathFloor = math.floor,
  7. mathCeil = math.ceil,
  8. mathMax = math.max,
  9. mathMin = math.min,
  10. mathAbs = math.abs,
  11. mathCos = math.cos,
  12. mathSin = math.sin,
  13. mathPI = math.PI,
  14. deg2rad = mathPI * 2 / 360,
  15. userAgent = navigator.userAgent,
  16. isIE = /msie/i.test(userAgent) && !win.opera,
  17. docMode8 = doc.documentMode == 8,
  18. isWebKit = /AppleWebKit/.test(userAgent),
  19. hasSVG = win.SVGAngle || doc.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"),
  20. useCanVG = !hasSVG && !isIE && !!doc.createElement('canvas').getContext,
  21. hasTouch = 'ontouchstart' in doc.documentElement,
  22. colorCounter,
  23. symbolCounter,
  24. symbolSizes = {},
  25. idCounter = 0,
  26. timeFactor = 1,
  27. garbageBin,
  28. defaultOptions,
  29. dateFormat,
  30. globalAnimation,
  31. pathAnim,
  32. UNDEFINED,
  33. DIV = 'div',
  34. ABSOLUTE = 'absolute',
  35. RELATIVE = 'relative',
  36. HIDDEN = 'hidden',
  37. PREFIX = 'highcharts-',
  38. VISIBLE = 'visible',
  39. PX = 'px',
  40. NONE = 'none',
  41. M = 'M',
  42. L = 'L',
  43. TRACKER_FILL = 'rgba(192,192,192,'+ (hasSVG ? 0.000001 : 0.002) +')',
  44. NORMAL_STATE = '',
  45. HOVER_STATE = 'hover',
  46. SELECT_STATE = 'select',
  47. makeTime,
  48. getMinutes,
  49. getHours,
  50. getDay,
  51. getDate,
  52. getMonth,
  53. getFullYear,
  54. setMinutes,
  55. setHours,
  56. setDate,
  57. setMonth,
  58. setFullYear,
  59. globalAdapter = win.HighchartsAdapter,
  60. adapter = globalAdapter || {},
  61. each = adapter.each,
  62. grep = adapter.grep,
  63. map = adapter.map,
  64. merge = adapter.merge,
  65. hyphenate = adapter.hyphenate,
  66. addEvent = adapter.addEvent,
  67. removeEvent = adapter.removeEvent,
  68. fireEvent = adapter.fireEvent,
  69. animate = adapter.animate,
  70. stop = adapter.stop,
  71. seriesTypes = {};
  72. function extend(a, b) {
  73. if (!a) {
  74. a = {};
  75. }
  76. for (var n in b) {
  77. a[n] = b[n];
  78. }
  79. return a;
  80. }
  81. function pInt(s, mag) {
  82. return parseInt(s, mag || 10);
  83. }
  84. function isString(s) {
  85. return typeof s == 'string';
  86. }
  87. function isObject(obj) {
  88. return typeof obj == 'object';
  89. }
  90. function isNumber(n) {
  91. return typeof n == 'number';
  92. }
  93. function erase(arr, item) {
  94. var i = arr.length;
  95. while (i--) {
  96. if (arr[i] == item) {
  97. arr.splice(i, 1);
  98. break;
  99. }
  100. }
  101. }
  102. function defined (obj) {
  103. return obj !== UNDEFINED && obj !== null;
  104. }
  105. function attr(elem, prop, value) {
  106. var key,
  107. setAttribute = 'setAttribute',
  108. ret;
  109. if (isString(prop)) {
  110. if (defined(value)) {
  111. elem[setAttribute](prop, value);
  112. } else if (elem && elem.getAttribute) {
  113. ret = elem.getAttribute(prop);
  114. }
  115. } else if (defined(prop) && isObject(prop)) {
  116. for (key in prop) {
  117. elem[setAttribute](key, prop[key]);
  118. }
  119. }
  120. return ret;
  121. }
  122. function splat(obj) {
  123. if (!obj || obj.constructor != Array) {
  124. obj = [obj];
  125. }
  126. return obj;
  127. }
  128. function pick() {
  129. var args = arguments,
  130. i,
  131. arg;
  132. for (i = 0; i < args.length; i++) {
  133. arg = args[i];
  134. if (defined(arg)) {
  135. return arg;
  136. }
  137. }
  138. }
  139. function serializeCSS(style) {
  140. var s = '',
  141. key;
  142. for (key in style) {
  143. s += hyphenate(key) +':'+ style[key] + ';';
  144. }
  145. return s;
  146. }
  147. function css (el, styles) {
  148. if (isIE) {
  149. if (styles && styles.opacity !== UNDEFINED) {
  150. styles.filter = 'alpha(opacity='+ (styles.opacity * 100) +')';
  151. }
  152. }
  153. extend(el.style, styles);
  154. }
  155. function createElement (tag, attribs, styles, parent, nopad) {
  156. var el = doc.createElement(tag);
  157. if (attribs) {
  158. extend(el, attribs);
  159. }
  160. if (nopad) {
  161. css(el, {padding: 0, border: NONE, margin: 0});
  162. }
  163. if (styles) {
  164. css(el, styles);
  165. }
  166. if (parent) {
  167. parent.appendChild(el);
  168. }
  169. return el;
  170. }
  171. function setAnimation(animation, chart) {
  172. globalAnimation = pick(animation, chart.animation);
  173. }
  174. if (globalAdapter && globalAdapter.init) {
  175. globalAdapter.init();
  176. }
  177. if (!globalAdapter && win.jQuery) {
  178. var jQ = jQuery;
  179. each = function(arr, fn) {
  180. for (var i = 0, len = arr.length; i < len; i++) {
  181. if (fn.call(arr[i], arr[i], i, arr) === false) {
  182. return i;
  183. }
  184. }
  185. };
  186. grep = jQ.grep;
  187. map = function(arr, fn){
  188. var results = [];
  189. for (var i = 0, len = arr.length; i < len; i++) {
  190. results[i] = fn.call(arr[i], arr[i], i, arr);
  191. }
  192. return results;
  193. };
  194. merge = function(){
  195. var args = arguments;
  196. return jQ.extend(true, null, args[0], args[1], args[2], args[3]);
  197. };
  198. hyphenate = function (str) {
  199. return str.replace(/([A-Z])/g, function(a, b){ return '-'+ b.toLowerCase(); });
  200. };
  201. addEvent = function (el, event, fn){
  202. jQ(el).bind(event, fn);
  203. };
  204. removeEvent = function(el, eventType, handler) {
  205. var func = doc.removeEventListener ? 'removeEventListener' : 'detachEvent';
  206. if (doc[func] && !el[func]) {
  207. el[func] = function() {};
  208. }
  209. jQ(el).unbind(eventType, handler);
  210. };
  211. fireEvent = function(el, type, eventArguments, defaultFunction) {
  212. var m_event = jQ.Event(type),
  213. detachedType = 'detached'+ type;
  214. extend(event, eventArguments);
  215. if (el[type]) {
  216. el[detachedType] = el[type];
  217. el[type] = null;
  218. }
  219. jQ(el).trigger(m_event);
  220. if (el[detachedType]) {
  221. el[type] = el[detachedType];
  222. el[detachedType] = null;
  223. }
  224. if (defaultFunction && !m_event.isDefaultPrevented()) {
  225. defaultFunction(m_event);
  226. }
  227. };
  228. animate = function (el, params, options) {
  229. var $el = jQ(el);
  230. if (params.d) {
  231. el.toD = params.d;
  232. params.d = 1;
  233. }
  234. $el.stop();
  235. $el.animate(params, options);
  236. };
  237. stop = function (el) {
  238. jQ(el).stop();
  239. };
  240. jQ.extend( jQ.easing, {
  241. easeOutQuad: function (x, t, b, c, d) {
  242. return -c *(t/=d)*(t-2) + b;
  243. }
  244. });
  245. var oldStepDefault = jQuery.fx.step._default,
  246. oldCur = jQuery.fx.prototype.cur;
  247. jQ.fx.step._default = function(fx){
  248. var elem = fx.elem;
  249. if (elem.attr) {
  250. elem.attr(fx.prop, fx.now);
  251. } else {
  252. oldStepDefault.apply(this, arguments);
  253. }
  254. };
  255. jQ.fx.step.d = function(fx) {
  256. var elem = fx.elem;
  257. if (!fx.started) {
  258. var ends = pathAnim.init(elem, elem.d, elem.toD);
  259. fx.start = ends[0];
  260. fx.end = ends[1];
  261. fx.started = true;
  262. }
  263. elem.attr('d', pathAnim.step(fx.start, fx.end, fx.pos, elem.toD));
  264. };
  265. jQ.fx.prototype.cur = function() {
  266. var elem = this.elem,
  267. r;
  268. if (elem.attr) {
  269. r = elem.attr(this.prop);
  270. } else {
  271. r = oldCur.apply(this, arguments);
  272. }
  273. return r;
  274. };
  275. }
  276. pathAnim = {
  277. init: function(elem, fromD, toD) {
  278. fromD = fromD || '';
  279. var shift = elem.shift,
  280. bezier = fromD.indexOf('C') > -1,
  281. numParams = bezier ? 7 : 3,
  282. endLength,
  283. slice,
  284. i,
  285. start = fromD.split(' '),
  286. end = [].concat(toD),
  287. startBaseLine,
  288. endBaseLine,
  289. sixify = function(arr) {
  290. i = arr.length;
  291. while (i--) {
  292. if (arr[i] == M) {
  293. arr.splice(i + 1, 0, arr[i+1], arr[i+2], arr[i+1], arr[i+2]);
  294. }
  295. }
  296. };
  297. if (bezier) {
  298. sixify(start);
  299. sixify(end);
  300. }
  301. if (elem.isArea) {
  302. startBaseLine = start.splice(start.length - 6, 6);
  303. endBaseLine = end.splice(end.length - 6, 6);
  304. }
  305. if (shift) {
  306. end = [].concat(end).splice(0, numParams).concat(end);
  307. elem.shift = false;
  308. }
  309. endLength = end.length;
  310. while (start.length < endLength) {
  311. slice = [].concat(start).splice(start.length - numParams, numParams);
  312. if (bezier) {
  313. slice[numParams - 6] = slice[numParams - 2];
  314. slice[numParams - 5] = slice[numParams - 1];
  315. }
  316. start = start.concat(slice);
  317. }
  318. if (startBaseLine) {
  319. start = start.concat(startBaseLine);
  320. end = end.concat(endBaseLine);
  321. }
  322. return [start, end];
  323. },
  324. step: function(start, end, pos, complete) {
  325. var ret = [],
  326. i = start.length,
  327. startVal;
  328. if (pos == 1) {
  329. ret = complete;
  330. } else if (i == end.length && pos < 1) {
  331. while (i--) {
  332. startVal = parseFloat(start[i]);
  333. ret[i] =
  334. isNaN(startVal) ?
  335. start[i] :
  336. pos * (parseFloat(end[i] - startVal)) + startVal;
  337. }
  338. } else {
  339. ret = end;
  340. }
  341. return ret;
  342. }
  343. };
  344. function setTimeMethods() {
  345. var useUTC = defaultOptions.global.useUTC;
  346. makeTime = useUTC ? Date.UTC : function(year, month, date, hours, minutes, seconds) {
  347. return new Date(
  348. year,
  349. month,
  350. pick(date, 1),
  351. pick(hours, 0),
  352. pick(minutes, 0),
  353. pick(seconds, 0)
  354. ).getTime();
  355. };
  356. getMinutes = useUTC ? 'getUTCMinutes' : 'getMinutes';
  357. getHours = useUTC ? 'getUTCHours' : 'getHours';
  358. getDay = useUTC ? 'getUTCDay' : 'getDay';
  359. getDate = useUTC ? 'getUTCDate' : 'getDate';
  360. getMonth = useUTC ? 'getUTCMonth' : 'getMonth';
  361. getFullYear = useUTC ? 'getUTCFullYear' : 'getFullYear';
  362. setMinutes = useUTC ? 'setUTCMinutes' : 'setMinutes';
  363. setHours = useUTC ? 'setUTCHours' : 'setHours';
  364. setDate = useUTC ? 'setUTCDate' : 'setDate';
  365. setMonth = useUTC ? 'setUTCMonth' : 'setMonth';
  366. setFullYear = useUTC ? 'setUTCFullYear' : 'setFullYear';
  367. }
  368. function setOptions(options) {
  369. defaultOptions = merge(defaultOptions, options);
  370. setTimeMethods();
  371. return defaultOptions;
  372. }
  373. function getOptions() {
  374. return defaultOptions;
  375. }
  376. function discardElement(element) {
  377. if (!garbageBin) {
  378. garbageBin = createElement(DIV);
  379. }
  380. if (element) {
  381. garbageBin.appendChild(element);
  382. }
  383. garbageBin.innerHTML = '';
  384. }
  385. var deferredCanvases = [];
  386. function drawDeferredCanvases() {
  387. each(deferredCanvases, function(fn) {
  388. fn();
  389. erase(deferredCanvases, fn);
  390. });
  391. }
  392. var
  393. defaultLabelOptions = {
  394. enabled: true,
  395. align: 'center',
  396. x: 0,
  397. y: 15,
  398. style: {
  399. color: '#666',
  400. fontSize: '11px'
  401. }
  402. };
  403. defaultOptions = {
  404. colors: ['#4572A7', '#AA4643', '#89A54E', '#80699B', '#3D96AE',
  405. '#DB843D', '#92A8CD', '#A47D7C', '#B5CA92'],
  406. symbols: ['circle', 'diamond', 'square', 'triangle', 'triangle-down'],
  407. lang: {
  408. loading: 'Loading...',
  409. months: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
  410. 'August', 'September', 'October', 'November', 'December'],
  411. weekdays: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
  412. decimalPoint: '.',
  413. resetZoom: 'Reset zoom',
  414. resetZoomTitle: 'Reset zoom level 1:1',
  415. thousandsSep: ','
  416. },
  417. global: {
  418. useUTC: true
  419. },
  420. chart: {
  421. borderColor: '#4572A7',
  422. borderRadius: 5,
  423. defaultSeriesType: 'line',
  424. ignoreHiddenSeries: true,
  425. spacingTop: 10,
  426. spacingRight: 10,
  427. spacingBottom: 15,
  428. spacingLeft: 10,
  429. style: {
  430. fontFamily: '"Lucida Grande", "Lucida Sans Unicode", Verdana, Arial, Helvetica, sans-serif',
  431. fontSize: '12px'
  432. },
  433. backgroundColor: '#FFFFFF',
  434. plotBorderColor: '#C0C0C0'
  435. },
  436. title: {
  437. text: 'Chart title',
  438. align: 'center',
  439. y: 15,
  440. style: {
  441. color: '#3E576F',
  442. fontSize: '16px'
  443. }
  444. },
  445. subtitle: {
  446. text: '',
  447. align: 'center',
  448. y: 30,
  449. style: {
  450. color: '#6D869F'
  451. }
  452. },
  453. plotOptions: {
  454. line: {
  455. allowPointSelect: false,
  456. showCheckbox: false,
  457. animation: {
  458. duration: 1000
  459. },
  460. events: {},
  461. lineWidth: 2,
  462. shadow: true,
  463. marker: {
  464. enabled: true,
  465. lineWidth: 0,
  466. radius: 4,
  467. lineColor: '#FFFFFF',
  468. states: {
  469. hover: {
  470. },
  471. select: {
  472. fillColor: '#FFFFFF',
  473. lineColor: '#000000',
  474. lineWidth: 2
  475. }
  476. }
  477. },
  478. point: {
  479. events: {}
  480. },
  481. dataLabels: merge(defaultLabelOptions, {
  482. enabled: false,
  483. y: -6,
  484. formatter: function() {
  485. return this.y;
  486. }
  487. }),
  488. showInLegend: true,
  489. states: {
  490. hover: {
  491. marker: {
  492. }
  493. },
  494. select: {
  495. marker: {}
  496. }
  497. },
  498. stickyTracking: true
  499. }
  500. },
  501. labels: {
  502. style: {
  503. position: ABSOLUTE,
  504. color: '#3E576F'
  505. }
  506. },
  507. legend: {
  508. enabled: true,
  509. align: 'center',
  510. layout: 'horizontal',
  511. labelFormatter: function() {
  512. return this.name;
  513. },
  514. borderWidth: 1,
  515. borderColor: '#909090',
  516. borderRadius: 5,
  517. shadow: false,
  518. style: {
  519. padding: '5px'
  520. },
  521. itemStyle: {
  522. cursor: 'pointer',
  523. color: '#3E576F'
  524. },
  525. itemHoverStyle: {
  526. cursor: 'pointer',
  527. color: '#000000'
  528. },
  529. itemHiddenStyle: {
  530. color: '#C0C0C0'
  531. },
  532. itemCheckboxStyle: {
  533. position: ABSOLUTE,
  534. width: '13px',
  535. height: '13px'
  536. },
  537. symbolWidth: 16,
  538. symbolPadding: 5,
  539. verticalAlign: 'bottom',
  540. x: 0,
  541. y: 0
  542. },
  543. loading: {
  544. hideDuration: 100,
  545. labelStyle: {
  546. fontWeight: 'bold',
  547. position: RELATIVE,
  548. top: '1em'
  549. },
  550. showDuration: 100,
  551. style: {
  552. position: ABSOLUTE,
  553. backgroundColor: 'white',
  554. opacity: 0.5,
  555. textAlign: 'center'
  556. }
  557. },
  558. tooltip: {
  559. enabled: true,
  560. backgroundColor: 'rgba(255, 255, 255, .85)',
  561. borderWidth: 2,
  562. borderRadius: 5,
  563. shadow: true,
  564. snap: hasTouch ? 25 : 10,
  565. style: {
  566. color: '#333333',
  567. fontSize: '12px',
  568. padding: '5px',
  569. whiteSpace: 'nowrap'
  570. }
  571. },
  572. toolbar: {
  573. itemStyle: {
  574. color: '#4572A7',
  575. cursor: 'pointer'
  576. }
  577. },
  578. credits: {
  579. enabled: true,
  580. text: 'Highcharts.com',
  581. href: 'http://www.highcharts.com',
  582. position: {
  583. align: 'right',
  584. x: -10,
  585. verticalAlign: 'bottom',
  586. y: -5
  587. },
  588. style: {
  589. cursor: 'pointer',
  590. color: '#909090',
  591. fontSize: '10px'
  592. }
  593. }
  594. };
  595. var defaultXAxisOptions = {
  596. dateTimeLabelFormats: {
  597. second: '%H:%M:%S',
  598. minute: '%H:%M',
  599. hour: '%H:%M',
  600. day: '%e. %b',
  601. week: '%e. %b',
  602. month: '%b \'%y',
  603. year: '%Y'
  604. },
  605. endOnTick: false,
  606. gridLineColor: '#C0C0C0',
  607. labels: defaultLabelOptions,
  608. lineColor: '#C0D0E0',
  609. lineWidth: 1,
  610. max: null,
  611. min: null,
  612. minPadding: 0.01,
  613. maxPadding: 0.01,
  614. minorGridLineColor: '#E0E0E0',
  615. minorGridLineWidth: 1,
  616. minorTickColor: '#A0A0A0',
  617. minorTickLength: 2,
  618. minorTickPosition: 'outside',
  619. startOfWeek: 1,
  620. startOnTick: false,
  621. tickColor: '#C0D0E0',
  622. tickLength: 5,
  623. tickmarkPlacement: 'between',
  624. tickPixelInterval: 100,
  625. tickPosition: 'outside',
  626. tickWidth: 1,
  627. title: {
  628. align: 'middle',
  629. style: {
  630. color: '#6D869F',
  631. fontWeight: 'bold'
  632. }
  633. },
  634. type: 'linear'
  635. },
  636. defaultYAxisOptions = merge(defaultXAxisOptions, {
  637. endOnTick: true,
  638. gridLineWidth: 1,
  639. tickPixelInterval: 72,
  640. showLastLabel: true,
  641. labels: {
  642. align: 'right',
  643. x: -8,
  644. y: 3
  645. },
  646. lineWidth: 0,
  647. maxPadding: 0.05,
  648. minPadding: 0.05,
  649. startOnTick: true,
  650. tickWidth: 0,
  651. title: {
  652. rotation: 270,
  653. text: 'Y-values'
  654. }
  655. }),
  656. defaultLeftAxisOptions = {
  657. labels: {
  658. align: 'right',
  659. x: -8,
  660. y: 3
  661. },
  662. title: {
  663. rotation: 270
  664. }
  665. },
  666. defaultRightAxisOptions = {
  667. labels: {
  668. align: 'left',
  669. x: 8,
  670. y: 3
  671. },
  672. title: {
  673. rotation: 90
  674. }
  675. },
  676. defaultBottomAxisOptions = {
  677. labels: {
  678. align: 'center',
  679. x: 0,
  680. y: 14
  681. },
  682. title: {
  683. rotation: 0
  684. }
  685. },
  686. defaultTopAxisOptions = merge(defaultBottomAxisOptions, {
  687. labels: {
  688. y: -5
  689. }
  690. });
  691. var defaultPlotOptions = defaultOptions.plotOptions,
  692. defaultSeriesOptions = defaultPlotOptions.line;
  693. defaultPlotOptions.spline = merge(defaultSeriesOptions);
  694. defaultPlotOptions.scatter = merge(defaultSeriesOptions, {
  695. lineWidth: 0,
  696. states: {
  697. hover: {
  698. lineWidth: 0
  699. }
  700. }
  701. });
  702. defaultPlotOptions.area = merge(defaultSeriesOptions, {
  703. });
  704. defaultPlotOptions.areaspline = merge(defaultPlotOptions.area);
  705. defaultPlotOptions.column = merge(defaultSeriesOptions, {
  706. borderColor: '#FFFFFF',
  707. borderWidth: 1,
  708. borderRadius: 0,
  709. groupPadding: 0.2,
  710. marker: null,
  711. pointPadding: 0.1,
  712. minPointLength: 0,
  713. states: {
  714. hover: {
  715. brightness: 0.1,
  716. shadow: false
  717. },
  718. select: {
  719. color: '#C0C0C0',
  720. borderColor: '#000000',
  721. shadow: false
  722. }
  723. }
  724. });
  725. defaultPlotOptions.bar = merge(defaultPlotOptions.column, {
  726. dataLabels: {
  727. align: 'left',
  728. x: 5,
  729. y: 0
  730. }
  731. });
  732. defaultPlotOptions.pie = merge(defaultSeriesOptions, {
  733. borderColor: '#FFFFFF',
  734. borderWidth: 1,
  735. center: ['50%', '50%'],
  736. colorByPoint: true,
  737. dataLabels: {
  738. distance: 30,
  739. enabled: true,
  740. formatter: function() {
  741. return this.point.name;
  742. },
  743. y: 5
  744. },
  745. legendType: 'point',
  746. marker: null,
  747. size: '75%',
  748. showInLegend: false,
  749. slicedOffset: 10,
  750. states: {
  751. hover: {
  752. brightness: 0.1,
  753. shadow: false
  754. }
  755. }
  756. });
  757. setTimeMethods();
  758. function extendClass(parent, members) {
  759. var object = function(){};
  760. object.prototype = new parent();
  761. extend(object.prototype, members);
  762. return object;
  763. }
  764. var Color = function(input) {
  765. var rgba = [], result;
  766. function init(input) {
  767. if((result = /rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]?(?:\.[0-9]+)?)\s*\)/.exec(input))) {
  768. rgba = [pInt(result[1]), pInt(result[2]), pInt(result[3]), parseFloat(result[4], 10)];
  769. }
  770. else if((result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(input))) {
  771. rgba = [pInt(result[1],16), pInt(result[2],16), pInt(result[3],16), 1];
  772. }
  773. }
  774. function get(format) {
  775. var ret;
  776. if (rgba && !isNaN(rgba[0])) {
  777. if (format == 'rgb') {
  778. ret = 'rgb('+ rgba[0] +','+ rgba[1] +','+ rgba[2] +')';
  779. } else if (format == 'a') {
  780. ret = rgba[3];
  781. } else {
  782. ret = 'rgba('+ rgba.join(',') +')';
  783. }
  784. } else {
  785. ret = input;
  786. }
  787. return ret;
  788. }
  789. function brighten(alpha) {
  790. if (isNumber(alpha) && alpha !== 0) {
  791. var i;
  792. for (i = 0; i < 3; i++) {
  793. rgba[i] += pInt(alpha * 255);
  794. if (rgba[i] < 0) {
  795. rgba[i] = 0;
  796. }
  797. if (rgba[i] > 255) {
  798. rgba[i] = 255;
  799. }
  800. }
  801. }
  802. return this;
  803. }
  804. function setOpacity(alpha) {
  805. rgba[3] = alpha;
  806. return this;
  807. }
  808. init(input);
  809. return {
  810. get: get,
  811. brighten: brighten,
  812. setOpacity: setOpacity
  813. };
  814. };
  815. function numberFormat (number, decimals, decPoint, thousandsSep) {
  816. var lang = defaultOptions.lang,
  817. n = number, c = isNaN(decimals = mathAbs(decimals)) ? 2 : decimals,
  818. d = decPoint === undefined ? lang.decimalPoint : decPoint,
  819. t = thousandsSep === undefined ? lang.thousandsSep : thousandsSep, s = n < 0 ? "-" : "",
  820. i = pInt(n = mathAbs(+n || 0).toFixed(c)) + "", j = (j = i.length) > 3 ? j % 3 : 0;
  821. return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) +
  822. (c ? d + mathAbs(n - i).toFixed(c).slice(2) : "");
  823. }
  824. dateFormat = function (format, timestamp, capitalize) {
  825. function pad (number) {
  826. return number.toString().replace(/^([0-9])$/, '0$1');
  827. }
  828. if (!defined(timestamp) || isNaN(timestamp)) {
  829. return 'Invalid date';
  830. }
  831. format = pick(format, '%Y-%m-%d %H:%M:%S');
  832. var date = new Date(timestamp * timeFactor),
  833. hours = date[getHours](),
  834. day = date[getDay](),
  835. dayOfMonth = date[getDate](),
  836. month = date[getMonth](),
  837. fullYear = date[getFullYear](),
  838. lang = defaultOptions.lang,
  839. langWeekdays = lang.weekdays,
  840. langMonths = lang.months,
  841. replacements = {
  842. 'a': langWeekdays[day].substr(0, 3),
  843. 'A': langWeekdays[day],
  844. 'd': pad(dayOfMonth),
  845. 'e': dayOfMonth,
  846. 'b': langMonths[month].substr(0, 3),
  847. 'B': langMonths[month],
  848. 'm': pad(month + 1),
  849. 'y': fullYear.toString().substr(2, 2),
  850. 'Y': fullYear,
  851. 'H': pad(hours),
  852. 'I': pad((hours % 12) || 12),
  853. 'l': (hours % 12) || 12,
  854. 'M': pad(date[getMinutes]()),
  855. 'p': hours < 12 ? 'AM' : 'PM',
  856. 'P': hours < 12 ? 'am' : 'pm',
  857. 'S': pad(date.getSeconds())
  858. };
  859. for (var key in replacements) {
  860. format = format.replace('%'+ key, replacements[key]);
  861. }
  862. return capitalize ? format.substr(0, 1).toUpperCase() + format.substr(1) : format;
  863. };
  864. function getPosition (el) {
  865. var p = { left: el.offsetLeft, top: el.offsetTop };
  866. while ((el = el.offsetParent)) {
  867. p.left += el.offsetLeft;
  868. p.top += el.offsetTop;
  869. if (el != doc.body && el != doc.documentElement) {
  870. p.left -= el.scrollLeft;
  871. p.top -= el.scrollTop;
  872. }
  873. }
  874. return p;
  875. }
  876. function SVGElement () {}
  877. SVGElement.prototype = {
  878. init: function(renderer, nodeName) {
  879. this.element = doc.createElementNS('http://www.w3.org/2000/svg', nodeName);
  880. this.renderer = renderer;
  881. },
  882. animate: function(params, options, complete) {
  883. var animOptions = pick(options, globalAnimation, true);
  884. if (animOptions) {
  885. animOptions = merge(animOptions);
  886. if (complete) {
  887. animOptions.complete = complete;
  888. }
  889. animate(this, params, animOptions);
  890. } else {
  891. this.attr(params);
  892. if (complete) {
  893. complete();
  894. }
  895. }
  896. },
  897. attr: function(hash, val) {
  898. var key,
  899. value,
  900. i,
  901. child,
  902. element = this.element,
  903. nodeName = element.nodeName,
  904. renderer = this.renderer,
  905. skipAttr,
  906. shadows = this.shadows,
  907. hasSetSymbolSize,
  908. ret = this;
  909. if (isString(hash) && defined(val)) {
  910. key = hash;
  911. hash = {};
  912. hash[key] = val;
  913. }
  914. if (isString(hash)) {
  915. key = hash;
  916. if (nodeName == 'circle') {
  917. key = { x: 'cx', y: 'cy' }[key] || key;
  918. } else if (key == 'strokeWidth') {
  919. key = 'stroke-width';
  920. }
  921. ret = attr(element, key) || this[key] || 0;
  922. if (key != 'd' && key != 'visibility') {
  923. ret = parseFloat(ret);
  924. }
  925. } else {
  926. for (key in hash) {
  927. skipAttr = false;
  928. value = hash[key];
  929. if (key == 'd') {
  930. if (value && value.join) {
  931. value = value.join(' ');
  932. }
  933. if (/(NaN| {2}|^$)/.test(value)) {
  934. value = 'M 0 0';
  935. }
  936. this.d = value;
  937. } else if (key == 'x' && nodeName == 'text') {
  938. for (i = 0; i < element.childNodes.length; i++ ) {
  939. child = element.childNodes[i];
  940. if (attr(child, 'x') == attr(element, 'x')) {
  941. attr(child, 'x', value);
  942. }
  943. }
  944. if (this.rotation) {
  945. attr(element, 'transform', 'rotate('+ this.rotation +' '+ value +' '+
  946. pInt(hash.y || attr(element, 'y')) +')');
  947. }
  948. } else if (key == 'fill') {
  949. value = renderer.color(value, element, key);
  950. } else if (nodeName == 'circle' && (key == 'x' || key == 'y')) {
  951. key = { x: 'cx', y: 'cy' }[key] || key;
  952. } else if (key == 'translateX' || key == 'translateY' || key == 'rotation') {
  953. this[key] = value;
  954. this.updateTransform();
  955. skipAttr = true;
  956. } else if (key == 'stroke') {
  957. value = renderer.color(value, element, key);
  958. } else if (key == 'dashstyle') {
  959. key = 'stroke-dasharray';
  960. if (value) {
  961. value = value.toLowerCase()
  962. .replace('shortdashdotdot', '3,1,1,1,1,1,')
  963. .replace('shortdashdot', '3,1,1,1')
  964. .replace('shortdot', '1,1,')
  965. .replace('shortdash', '3,1,')
  966. .replace('longdash', '8,3,')
  967. .replace(/dot/g, '1,3,')
  968. .replace('dash', '4,3,')
  969. .replace(/,$/, '')
  970. .split(',');
  971. i = value.length;
  972. while (i--) {
  973. value[i] = pInt(value[i]) * hash['stroke-width'];
  974. }
  975. value = value.join(',');
  976. }
  977. } else if (key == 'isTracker') {
  978. this[key] = value;
  979. } else if (key == 'width') {
  980. value = pInt(value);
  981. } else if (key == 'align') {
  982. key = 'text-anchor';
  983. value = { left: 'start', center: 'middle', right: 'end' }[value];
  984. }
  985. if (key == 'strokeWidth') {
  986. key = 'stroke-width';
  987. }
  988. if (isWebKit && key == 'stroke-width' && value === 0) {
  989. value = 0.000001;
  990. }
  991. if (this.symbolName && /^(x|y|r|start|end|innerR)/.test(key)) {
  992. if (!hasSetSymbolSize) {
  993. this.symbolAttr(hash);
  994. hasSetSymbolSize = true;
  995. }
  996. skipAttr = true;
  997. }
  998. if (shadows && /^(width|height|visibility|x|y|d)$/.test(key)) {
  999. i = shadows.length;
  1000. while (i--) {
  1001. attr(shadows[i], key, value);
  1002. }
  1003. }
  1004. if (key == 'text') {
  1005. renderer.buildText(element, value);
  1006. } else if (!skipAttr) {
  1007. attr(element, key, value);
  1008. }
  1009. }
  1010. }
  1011. return ret;
  1012. },
  1013. symbolAttr: function(hash) {
  1014. var wrapper = this;
  1015. wrapper.x = pick(hash.x, wrapper.x);
  1016. wrapper.y = parseFloat(pick(hash.y, wrapper.y));
  1017. wrapper.r = pick(hash.r, wrapper.r);
  1018. wrapper.start = pick(hash.start, wrapper.start);
  1019. wrapper.end = pick(hash.end, wrapper.end);
  1020. wrapper.setWidth(pick(hash.width, wrapper.width));
  1021. wrapper.setHeight(parseFloat(pick(hash.height, wrapper.height)));
  1022. wrapper.innerR = pick(hash.innerR, wrapper.innerR);
  1023. wrapper.attr({
  1024. d: wrapper.renderer.symbols[wrapper.symbolName](wrapper.x, wrapper.y, wrapper.r, {
  1025. start: wrapper.start,
  1026. end: wrapper.end,
  1027. width: wrapper.width,
  1028. height: wrapper.height,
  1029. innerR: wrapper.innerR
  1030. })
  1031. });
  1032. },
  1033. clip: function(clipRect) {
  1034. return this.attr('clip-path', 'url('+ this.renderer.URL +'#'+ clipRect.id +')');
  1035. },
  1036. css: function(styles) {
  1037. var elemWrapper = this;
  1038. if (styles && styles.color) {
  1039. styles.fill = styles.color;
  1040. }
  1041. styles = extend(
  1042. elemWrapper.styles,
  1043. styles
  1044. );
  1045. elemWrapper.attr({
  1046. style: serializeCSS(styles)
  1047. });
  1048. elemWrapper.styles = styles;
  1049. return elemWrapper;
  1050. },
  1051. on: function(eventType, handler) {
  1052. var fn = handler;
  1053. if (hasTouch && eventType == 'click') {
  1054. eventType = 'touchstart';
  1055. fn = function(e) {
  1056. e.preventDefault();
  1057. handler();
  1058. }
  1059. }
  1060. this.element['on'+ eventType] = fn;
  1061. return this;
  1062. },
  1063. translate: function(x, y) {
  1064. return this.attr({
  1065. translateX: x,
  1066. translateY: y
  1067. });
  1068. },
  1069. invert: function() {
  1070. var wrapper = this;
  1071. wrapper.inverted = true;
  1072. wrapper.updateTransform();
  1073. return wrapper;
  1074. },
  1075. updateTransform: function() {
  1076. var wrapper = this,
  1077. translateX = wrapper.translateX || 0,
  1078. translateY = wrapper.translateY || 0,
  1079. inverted = wrapper.inverted,
  1080. rotation = wrapper.rotation,
  1081. transform = [];
  1082. if (inverted) {
  1083. translateX += wrapper.attr('width');
  1084. translateY += wrapper.attr('height');
  1085. }
  1086. if (translateX || translateY) {
  1087. transform.push('translate('+ translateX +','+ translateY +')');
  1088. }
  1089. if (inverted) {
  1090. transform.push('rotate(90) scale(-1,1)');
  1091. } else if (rotation) {
  1092. transform.push('rotate('+ rotation +' '+ wrapper.x +' '+ wrapper.y +')');
  1093. }
  1094. if (transform.length) {
  1095. attr(wrapper.element, 'transform', transform.join(' '));
  1096. }
  1097. },
  1098. toFront: function() {
  1099. var element = this.element;
  1100. element.parentNode.appendChild(element);
  1101. return this;
  1102. },
  1103. align: function(alignOptions, alignByTranslate, box) {
  1104. if (!alignOptions) {
  1105. alignOptions = this.alignOptions;
  1106. alignByTranslate = this.alignByTranslate;
  1107. } else {
  1108. this.alignOptions = alignOptions;
  1109. this.alignByTranslate = alignByTranslate;
  1110. if (!box) {
  1111. this.renderer.alignedObjects.push(this);
  1112. }
  1113. }
  1114. box = pick(box, this.renderer);
  1115. var align = alignOptions.align,
  1116. vAlign = alignOptions.verticalAlign,
  1117. x = (box.x || 0) + (alignOptions.x || 0),
  1118. y = (box.y || 0) + (alignOptions.y || 0),
  1119. attribs = {};
  1120. if (/^(right|center)$/.test(align)) {
  1121. x += (box.width - (alignOptions.width || 0) ) /
  1122. { right: 1, center: 2 }[align];
  1123. }
  1124. attribs[alignByTranslate ? 'translateX' : 'x'] = x;
  1125. if (/^(bottom|middle)$/.test(vAlign)) {
  1126. y += (box.height - (alignOptions.height || 0)) /
  1127. ({ bottom: 1, middle: 2 }[vAlign] || 1);
  1128. }
  1129. attribs[alignByTranslate ? 'translateY' : 'y'] = y;
  1130. this[this.placed ? 'animate' : 'attr'](attribs);
  1131. this.placed = true;
  1132. return this;
  1133. },
  1134. getBBox: function() {
  1135. var bBox,
  1136. width,
  1137. height,
  1138. element = this.element,
  1139. rotation = this.rotation,
  1140. rad = rotation * deg2rad;
  1141. try {
  1142. bBox = element.getBBox ?
  1143. extend({}, element.getBBox()) :
  1144. {
  1145. width: element.offsetWidth,
  1146. height: element.offsetHeight
  1147. };
  1148. } catch(e) {
  1149. bBox = { width: 0, height: 0 };
  1150. }
  1151. width = bBox.width;
  1152. height = bBox.height;
  1153. if (rotation) {
  1154. bBox.setWidth(mathAbs(height * mathSin(rad)) + mathAbs(width * mathCos(rad)));
  1155. bBox.setHeight(mathAbs(height * mathCos(rad)) + mathAbs(width * mathSin(rad)));
  1156. }
  1157. return bBox;
  1158. },
  1159. show: function() {
  1160. return this.attr({ visibility: VISIBLE });
  1161. },
  1162. hide: function() {
  1163. return this.attr({ visibility: HIDDEN });
  1164. },
  1165. add: function(parent) {
  1166. var renderer = this.renderer,
  1167. parentWrapper = parent || renderer,
  1168. parentNode = parentWrapper.element || renderer.box,
  1169. childNodes = parentNode.childNodes,
  1170. element = this.element,
  1171. zIndex = attr(element, 'zIndex'),
  1172. otherElement,
  1173. otherZIndex,
  1174. i;
  1175. this.parentInverted = parent && parent.inverted;
  1176. if (zIndex) {
  1177. parentWrapper.handleZ = true;
  1178. zIndex = pInt(zIndex);
  1179. }
  1180. if (parentWrapper.handleZ) {
  1181. for (i = 0; i < childNodes.length; i++) {
  1182. otherElement = childNodes[i];
  1183. otherZIndex = attr(otherElement, 'zIndex');
  1184. if (otherElement != element && (
  1185. pInt(otherZIndex) > zIndex ||
  1186. (!defined(zIndex) && defined(otherZIndex))
  1187. )) {
  1188. parentNode.insertBefore(element, otherElement);
  1189. return this;
  1190. }
  1191. }
  1192. }
  1193. parentNode.appendChild(element);
  1194. return this;
  1195. },
  1196. destroy: function() {
  1197. var wrapper = this,
  1198. element = wrapper.element || {},
  1199. shadows = wrapper.shadows,
  1200. parentNode = element.parentNode,
  1201. key;
  1202. element.onclick = element.onmouseout = element.onmouseover = element.onmousemove = null;
  1203. stop(wrapper);
  1204. if (parentNode) {
  1205. parentNode.removeChild(element);
  1206. }
  1207. if (shadows) {
  1208. each(shadows, function(shadow) {
  1209. parentNode = shadow.parentNode;
  1210. if (parentNode) {
  1211. parentNode.removeChild(shadow);
  1212. }
  1213. });
  1214. }
  1215. erase(wrapper.renderer.alignedObjects, wrapper);
  1216. for (key in wrapper) {
  1217. delete wrapper[key];
  1218. }
  1219. return null;
  1220. },
  1221. empty: function() {
  1222. var element = this.element,
  1223. childNodes = element.childNodes,
  1224. i = childNodes.length;
  1225. while (i--) {
  1226. element.removeChild(childNodes[i]);
  1227. }
  1228. },
  1229. shadow: function(apply) {
  1230. var shadows = [],
  1231. i,
  1232. shadow,
  1233. element = this.element,
  1234. transform = this.parentInverted ? '(-1,-1)' : '(1,1)';
  1235. if (apply) {
  1236. for (i = 1; i <= 3; i++) {
  1237. shadow = element.cloneNode(0);
  1238. attr(shadow, {
  1239. 'isShadow': 'true',
  1240. 'stroke': 'rgb(0, 0, 0)',
  1241. 'stroke-opacity': 0.05 * i,
  1242. 'stroke-width': 7 - 2 * i,
  1243. 'transform': 'translate'+ transform,
  1244. 'fill': NONE
  1245. });
  1246. element.parentNode.insertBefore(shadow, element);
  1247. shadows.push(shadow);
  1248. }
  1249. this.shadows = shadows;
  1250. }
  1251. return this;
  1252. }
  1253. };
  1254. var SVGRenderer = function() {
  1255. this.init.apply(this, arguments);
  1256. };
  1257. SVGRenderer.prototype = {
  1258. init: function(container, width, height) {
  1259. var renderer = this,
  1260. loc = location,
  1261. boxWrapper;
  1262. renderer.Element = SVGElement;
  1263. boxWrapper = renderer.createElement('svg')
  1264. .attr({
  1265. xmlns: 'http://www.w3.org/2000/svg',
  1266. version: '1.1'
  1267. });
  1268. container.appendChild(boxWrapper.element);
  1269. renderer.box = boxWrapper.element;
  1270. renderer.boxWrapper = boxWrapper;
  1271. renderer.alignedObjects = [];
  1272. renderer.URL = isIE ? '' : loc.href.replace(/#.*?$/, '');
  1273. renderer.defs = this.createElement('defs').add();
  1274. renderer.setSize(width, height, false);
  1275. },
  1276. createElement: function(nodeName) {
  1277. var wrapper = new this.Element();
  1278. wrapper.init(this, nodeName);
  1279. return wrapper;
  1280. },
  1281. draw: function() {},
  1282. buildText: function(textNode, str) {
  1283. var lines = str.toString()
  1284. .replace(/<(b|strong)>/g, '<span style="font-weight:bold">')
  1285. .replace(/<(i|em)>/g, '<span style="font-style:italic">')
  1286. .replace(/<a/g, '<span')
  1287. .replace(/<\/(b|strong|i|em|a)>/g, '</span>')
  1288. .split(/<br[^>]?>/g),
  1289. childNodes = textNode.childNodes,
  1290. styleRegex = /style="([^"]+)"/,
  1291. hrefRegex = /href="([^"]+)"/,
  1292. parentX = attr(textNode, 'x'),
  1293. lastLine,
  1294. i = childNodes.length;
  1295. while (i--) {
  1296. textNode.removeChild(childNodes[i]);
  1297. }
  1298. each(lines, function(line, lineNo) {
  1299. var spans, spanNo = 0, lineHeight;
  1300. line = line.replace(/<span/g, '|||<span').replace(/<\/span>/g, '</span>|||');
  1301. spans = line.split('|||');
  1302. each(spans, function (span) {
  1303. if (span !== '' || spans.length == 1) {
  1304. var attributes = {},
  1305. tspan = doc.createElementNS('http://www.w3.org/2000/svg', 'tspan');
  1306. if (styleRegex.test(span)) {
  1307. attr(
  1308. tspan,
  1309. 'style',
  1310. span.match(styleRegex)[1].replace(/(;| |^)color([ :])/, '$1fill$2')
  1311. );
  1312. }
  1313. if (hrefRegex.test(span)) {
  1314. attr(tspan, 'onclick', 'location.href=\"'+ span.match(hrefRegex)[1] +'\"');
  1315. css(tspan, { cursor: 'pointer' });
  1316. }
  1317. span = span.replace(/<(.|\n)*?>/g, '');
  1318. tspan.appendChild(doc.createTextNode(span || ' '));
  1319. if (!spanNo) {
  1320. attributes.x = parentX;
  1321. } else {
  1322. attributes.dx = 3;
  1323. }
  1324. if (!spanNo) {
  1325. if (lineNo) {
  1326. lineHeight = pInt(window.getComputedStyle(lastLine, null).getPropertyValue('line-height'));
  1327. if (isNaN(lineHeight)) {
  1328. lineHeight = lastLine.offsetHeight || 18;
  1329. }
  1330. attr(tspan, 'dy', lineHeight);
  1331. }
  1332. lastLine = tspan;
  1333. }
  1334. attr(tspan, attributes);
  1335. textNode.appendChild(tspan);
  1336. spanNo++;
  1337. }
  1338. });
  1339. });
  1340. },
  1341. crispLine: function(points, width) {
  1342. if (points[1] == points[4]) {
  1343. points[1] = points[4] = mathRound(points[1]) + (width % 2 / 2);
  1344. }
  1345. if (points[2] == points[5]) {
  1346. points[2] = points[5] = mathRound(points[2]) + (width % 2 / 2);
  1347. }
  1348. return points;
  1349. },
  1350. path: function (path) {
  1351. return this.createElement('path').attr({
  1352. d: path,
  1353. fill: NONE
  1354. });
  1355. },
  1356. circle: function (x, y, r) {
  1357. var attr = isObject(x) ?
  1358. x :
  1359. {
  1360. x: x,
  1361. y: y,
  1362. r: r
  1363. };
  1364. return this.createElement('circle').attr(attr);
  1365. },
  1366. arc: function (x, y, r, innerR, start, end) {
  1367. if (isObject(x)) {
  1368. y = x.y;
  1369. r = x.r;
  1370. innerR = x.innerR;
  1371. start = x.start;
  1372. end = x.end;
  1373. x = x.x;
  1374. }
  1375. return this.symbol('arc', x || 0, y || 0, r || 0, {
  1376. innerR: innerR || 0,
  1377. start: start || 0,
  1378. end: end || 0
  1379. });
  1380. },
  1381. rect: function (x, y, width, height, r, strokeWidth) {
  1382. if (arguments.length > 1) {
  1383. var normalizer = (strokeWidth || 0) % 2 / 2;
  1384. x = mathRound(x || 0) + normalizer;
  1385. y = mathRound(y || 0) + normalizer;
  1386. width = mathRound((width || 0) - 2 * normalizer);
  1387. height = mathRound((height || 0) - 2 * normalizer);
  1388. }
  1389. var attr = isObject(x) ?
  1390. x :
  1391. {
  1392. x: x,
  1393. y: y,
  1394. width: mathMax(width, 0),
  1395. height: mathMax(height, 0)
  1396. };
  1397. return this.createElement('rect').attr(extend(attr, {
  1398. rx: r || attr.r,
  1399. ry: r || attr.r,
  1400. fill: NONE
  1401. }));
  1402. },
  1403. setSize: function(width, height, animate) {
  1404. var renderer = this,
  1405. alignedObjects = renderer.alignedObjects,
  1406. i = alignedObjects.length;
  1407. renderer.setWidth(width);
  1408. renderer.setHeight(height);
  1409. renderer.boxWrapper[pick(animate, true) ? 'animate' : 'attr']({
  1410. width: width,
  1411. height: height
  1412. });
  1413. while (i--) {
  1414. alignedObjects[i].align();
  1415. }
  1416. },
  1417. g: function(name) {
  1418. return this.createElement('g').attr(
  1419. defined(name) && { 'class': PREFIX + name }
  1420. );
  1421. },
  1422. image: function(src, x, y, width, height) {
  1423. var attribs = {
  1424. preserveAspectRatio: NONE
  1425. },
  1426. elemWrapper;
  1427. if (arguments.length > 1) {
  1428. extend(attribs, {
  1429. x: x,
  1430. y: y,
  1431. width: width,
  1432. height: height
  1433. });
  1434. }
  1435. elemWrapper = this.createElement('image').attr(attribs);
  1436. elemWrapper.element.setAttributeNS('http://www.w3.org/1999/xlink',
  1437. 'href', src);
  1438. return elemWrapper;
  1439. },
  1440. symbol: function(symbol, x, y, radius, options) {
  1441. var obj,
  1442. symbolFn = this.symbols[symbol],
  1443. path = symbolFn && symbolFn(
  1444. x,
  1445. y,
  1446. radius,
  1447. options
  1448. ),
  1449. imageRegex = /^url\((.*?)\)$/,
  1450. imageSrc;
  1451. if (path) {
  1452. obj = this.path(path);
  1453. extend(obj, {
  1454. symbolName: symbol,
  1455. x: x,
  1456. y: y,
  1457. r: radius
  1458. });
  1459. if (options) {
  1460. extend(obj, options);
  1461. }
  1462. } else if (imageRegex.test(symbol)) {
  1463. imageSrc = symbol.match(imageRegex)[1];
  1464. obj = this.image(imageSrc)
  1465. .attr({
  1466. x: x,
  1467. y: y
  1468. });
  1469. createElement('img', {
  1470. onload: function() {
  1471. var img = this,
  1472. size = symbolSizes[img.src] || [img.width, img.height];
  1473. obj.attr({
  1474. width: size[0],
  1475. height: size[1]
  1476. }).translate(
  1477. -mathRound(size[0] / 2),
  1478. -mathRound(size[1] / 2)
  1479. );
  1480. },
  1481. src: imageSrc
  1482. });
  1483. } else {
  1484. obj = this.circle(x, y, radius);
  1485. }
  1486. return obj;
  1487. },
  1488. symbols: {
  1489. 'square': function (x, y, radius) {
  1490. var len = 0.707 * radius;
  1491. return [
  1492. M, x-len, y-len,
  1493. L, x+len, y-len,
  1494. x+len, y+len,
  1495. x-len, y+len,
  1496. 'Z'
  1497. ];
  1498. },
  1499. 'triangle': function (x, y, radius) {
  1500. return [
  1501. M, x, y-1.33 * radius,
  1502. L, x+radius, y + 0.67 * radius,
  1503. x-radius, y + 0.67 * radius,
  1504. 'Z'
  1505. ];
  1506. },
  1507. 'triangle-down': function (x, y, radius) {
  1508. return [
  1509. M, x, y + 1.33 * radius,
  1510. L, x-radius, y-0.67 * radius,
  1511. x+radius, y-0.67 * radius,
  1512. 'Z'
  1513. ];
  1514. },
  1515. 'diamond': function (x, y, radius) {
  1516. return [
  1517. M, x, y-radius,
  1518. L, x+radius, y,
  1519. x, y+radius,
  1520. x-radius, y,
  1521. 'Z'
  1522. ];
  1523. },
  1524. 'arc': function (x, y, radius, options) {
  1525. var start = options.start,
  1526. end = options.end - 0.000001,
  1527. innerRadius = options.innerR,
  1528. cosStart = mathCos(start),
  1529. sinStart = mathSin(start),
  1530. cosEnd = mathCos(end),
  1531. sinEnd = mathSin(end),
  1532. longArc = options.end - start < mathPI ? 0 : 1;
  1533. return [
  1534. M,
  1535. x + radius * cosStart,
  1536. y + radius * sinStart,
  1537. 'A',
  1538. radius,
  1539. radius,
  1540. 0,
  1541. longArc,
  1542. 1,
  1543. x + radius * cosEnd,
  1544. y + radius * sinEnd,
  1545. L,
  1546. x + innerRadius * cosEnd,
  1547. y + innerRadius * sinEnd,
  1548. 'A',
  1549. innerRadius,
  1550. innerRadius,
  1551. 0,
  1552. longArc,
  1553. 0,
  1554. x + innerRadius * cosStart,
  1555. y + innerRadius * sinStart,
  1556. 'Z'
  1557. ];
  1558. }
  1559. },
  1560. clipRect: function (x, y, width, height) {
  1561. var wrapper,
  1562. id = PREFIX + idCounter++,
  1563. clipPath = this.createElement('clipPath').attr({
  1564. id: id
  1565. }).add(this.defs);
  1566. wrapper = this.rect(x, y, width, height, 0).add(clipPath);
  1567. wrapper.id = id;
  1568. return wrapper;
  1569. },
  1570. color: function(color, elem, prop) {
  1571. var colorObject,
  1572. regexRgba = /^rgba/;
  1573. if (color && color.linearGradient) {
  1574. var renderer = this,
  1575. strLinearGradient = 'linearGradient',
  1576. linearGradient = color[strLinearGradient],
  1577. id = PREFIX + idCounter++,
  1578. gradientObject,
  1579. stopColor,
  1580. stopOpacity;
  1581. gradientObject = renderer.createElement(strLinearGradient).attr({
  1582. id: id,
  1583. gradientUnits: 'userSpaceOnUse',
  1584. x1: linearGradient[0],
  1585. y1: linearGradient[1],
  1586. x2: linearGradient[2],
  1587. y2: linearGradient[3]
  1588. }).add(renderer.defs);
  1589. each(color.stops, function(stop) {
  1590. if (regexRgba.test(stop[1])) {
  1591. colorObject = Color(stop[1]);
  1592. stopColor = colorObject.get('rgb');
  1593. stopOpacity = colorObject.get('a');
  1594. } else {
  1595. stopColor = stop[1];
  1596. stopOpacity = 1;
  1597. }
  1598. renderer.createElement('stop').attr({
  1599. offset: stop[0],
  1600. 'stop-color': stopColor,
  1601. 'stop-opacity': stopOpacity
  1602. }).add(gradientObject);
  1603. });
  1604. return 'url('+ this.URL +'#'+ id +')';
  1605. } else if (regexRgba.test(color)) {
  1606. colorObject = Color(color);
  1607. attr(elem, prop +'-opacity', colorObject.get('a'));
  1608. return colorObject.get('rgb');
  1609. } else {
  1610. return color;
  1611. }
  1612. },
  1613. text: function(str, x, y) {
  1614. var defaultChartStyle = defaultOptions.chart.style,
  1615. wrapper;
  1616. x = mathRound(pick(x, 0));
  1617. y = mathRound(pick(y, 0));
  1618. wrapper = this.createElement('text')
  1619. .attr({
  1620. x: x,
  1621. y: y,
  1622. text: str
  1623. })
  1624. .css({
  1625. 'font-family': defaultChartStyle.fontFamily,
  1626. 'font-size': defaultChartStyle.fontSize
  1627. });
  1628. wrapper.x = x;
  1629. wrapper.y = y;
  1630. return wrapper;
  1631. }
  1632. };
  1633. var VMLRenderer;
  1634. if (!hasSVG && !useCanVG) {
  1635. var VMLElement = extendClass( SVGElement, {
  1636. init: function(renderer, nodeName) {
  1637. var markup = ['<', nodeName, ' filled="f" stroked="f"'],
  1638. style = ['position: ', ABSOLUTE, ';'];
  1639. if (nodeName == 'shape' || nodeName == DIV) {
  1640. style.push('left:0;top:0;width:10px;height:10px;');
  1641. }
  1642. if (docMode8) {
  1643. style.push('visibility: ', nodeName == DIV ? HIDDEN : VISIBLE);
  1644. }
  1645. markup.push(' style="', style.join(''), '"/>');
  1646. if (nodeName) {
  1647. markup = nodeName == DIV || nodeName == 'span' || nodeName == 'img' ?
  1648. markup.join('')
  1649. : renderer.prepVML(markup);
  1650. this.element = createElement(markup);
  1651. }
  1652. this.renderer = renderer;
  1653. },
  1654. add: function(parent) {
  1655. var wrapper = this,
  1656. renderer = wrapper.renderer,
  1657. element = wrapper.element,
  1658. box = renderer.box,
  1659. inverted = parent && parent.inverted,
  1660. parentNode = parent ?
  1661. parent.element || parent :
  1662. box;
  1663. if (inverted) {
  1664. renderer.invertChild(element, parentNode);
  1665. }
  1666. if (docMode8 && parentNode.gVis == HIDDEN) {
  1667. css(element, { visibility: HIDDEN });
  1668. }
  1669. parentNode.appendChild(element);
  1670. wrapper.added = true;
  1671. if (wrapper.alignOnAdd) {
  1672. wrapper.updateTransform();
  1673. }
  1674. return wrapper;
  1675. },
  1676. attr: function(hash, val) {
  1677. var key,
  1678. value,
  1679. i,
  1680. element = this.element || {},
  1681. elemStyle = element.style,
  1682. nodeName = element.nodeName,
  1683. renderer = this.renderer,
  1684. symbolName = this.symbolName,
  1685. childNodes,
  1686. hasSetSymbolSize,
  1687. shadows = this.shadows,
  1688. skipAttr,
  1689. ret = this;
  1690. if (isString(hash) && defined(val)) {
  1691. key = hash;
  1692. hash = {};
  1693. hash[key] = val;
  1694. }
  1695. if (isString(hash)) {
  1696. key = hash;
  1697. if (key == 'strokeWidth' || key == 'stroke-width') {
  1698. ret = this.strokeweight;
  1699. } else {
  1700. ret = this[key];
  1701. }
  1702. } else {
  1703. for (key in hash) {
  1704. value = hash[key];
  1705. skipAttr = false;
  1706. if (symbolName && /^(x|y|r|start|end|width|height|innerR)/.test(key)) {
  1707. if (!hasSetSymbolSize) {
  1708. this.symbolAttr(hash);
  1709. hasSetSymbolSize = true;
  1710. }
  1711. skipAttr = true;
  1712. } else if (key == 'd') {
  1713. value = value || [];
  1714. this.d = value.join(' ');
  1715. i = value.length;
  1716. var convertedPath = [];
  1717. while (i--) {
  1718. if (isNumber(value[i])) {
  1719. convertedPath[i] = mathRound(value[i] * 10) - 5;
  1720. }
  1721. else if (value[i] == 'Z') {
  1722. convertedPath[i] = 'x';
  1723. }
  1724. else {
  1725. convertedPath[i] = value[i];
  1726. }
  1727. }
  1728. value = convertedPath.join(' ') || 'x';
  1729. element.path = value;
  1730. if (shadows) {
  1731. i = shadows.length;
  1732. while (i--) {
  1733. shadows[i].path = value;
  1734. }
  1735. }
  1736. skipAttr = true;
  1737. } else if (key == 'zIndex' || key == 'visibility') {
  1738. if (docMode8 && key == 'visibility' && nodeName == 'DIV') {
  1739. element.gVis = value;
  1740. childNodes = element.childNodes;
  1741. i = childNodes.length;
  1742. while (i--) {
  1743. css(childNodes[i], { visibility: value });
  1744. }
  1745. if (value == VISIBLE) {
  1746. value = null;
  1747. }
  1748. }
  1749. if (value) {
  1750. elemStyle[key] = value;
  1751. }
  1752. skipAttr = true;
  1753. } else if (/^(width|height)$/.test(key)) {
  1754. if (this.updateClipping) {
  1755. this[key] = value;
  1756. this.updateClipping();
  1757. } else {
  1758. elemStyle[key] = value;
  1759. }
  1760. skipAttr = true;
  1761. } else if (/^(x|y)$/.test(key)) {
  1762. this[key] = value;
  1763. if (element.tagName == 'SPAN') {
  1764. this.updateTransform();
  1765. } else {
  1766. elemStyle[{ x: 'left', y: 'top' }[key]] = value;
  1767. }
  1768. } else if (key == 'class') {
  1769. element.className = value;
  1770. } else if (key == 'stroke') {
  1771. value = renderer.color(value, element, key);
  1772. key = 'strokecolor';
  1773. } else if (key == 'stroke-width' || key == 'strokeWidth') {
  1774. element.stroked = value ? true : false;
  1775. key = 'strokeweight';
  1776. this[key] = value;
  1777. if (isNumber(value)) {
  1778. value += PX;
  1779. }
  1780. } else if (key == 'dashstyle') {
  1781. var strokeElem = element.getElementsByTagName('stroke')[0] ||
  1782. createElement(renderer.prepVML(['<stroke/>']), null, null, element);
  1783. strokeElem[key] = value || 'solid';
  1784. this.dashstyle = value;
  1785. skipAttr = true;
  1786. } else if (key == 'fill') {
  1787. if (nodeName == 'SPAN') {
  1788. elemStyle.color = value;
  1789. } else {
  1790. element.filled = value != NONE ? true : false;
  1791. value = renderer.color(value, element, key);
  1792. key = 'fillcolor';
  1793. }
  1794. } else if (key == 'translateX' || key == 'translateY' || key == 'rotation' || key == 'align') {
  1795. if (key == 'align') {
  1796. key = 'textAlign';
  1797. }
  1798. this[key] = value;
  1799. this.updateTransform();
  1800. skipAttr = true;
  1801. }
  1802. else if (key == 'text') {
  1803. element.innerHTML = value;
  1804. skipAttr = true;
  1805. }
  1806. if (shadows && key == 'visibility') {
  1807. i = shadows.length;
  1808. while (i--) {
  1809. shadows[i].style[key] = value;
  1810. }
  1811. }
  1812. if (!skipAttr) {
  1813. if (docMode8) {
  1814. element[key] = value;
  1815. } else {
  1816. attr(element, key, value);
  1817. }
  1818. }
  1819. }
  1820. }
  1821. return ret;
  1822. },
  1823. clip: function(clipRect) {
  1824. var wrapper = this,
  1825. clipMembers = clipRect.members,
  1826. index = clipMembers.length;
  1827. clipMembers.push(wrapper);
  1828. wrapper.destroyClip = function() {
  1829. clipMembers.splice(index, 1);
  1830. };
  1831. return wrapper.css(clipRect.getCSS(wrapper.inverted));
  1832. },
  1833. css: function(styles) {
  1834. var wrapper = this;
  1835. css(wrapper.element, styles);
  1836. return wrapper;
  1837. },
  1838. destroy: function() {
  1839. var wrapper = this;
  1840. if (wrapper.destroyClip) {
  1841. wrapper.destroyClip();
  1842. }
  1843. SVGElement.prototype.destroy.apply(this);
  1844. },
  1845. empty: function() {
  1846. var element = this.element,
  1847. childNodes = element.childNodes,
  1848. i = childNodes.length,
  1849. node;
  1850. while (i--) {
  1851. node = childNodes[i];
  1852. node.parentNode.removeChild(node);
  1853. }
  1854. },
  1855. getBBox: function() {
  1856. var element = this.element;
  1857. if (element.nodeName == 'text') {
  1858. element.style.position = ABSOLUTE;
  1859. }
  1860. return {
  1861. x: element.offsetLeft,
  1862. y: element.offsetTop,
  1863. width: element.offsetWidth,
  1864. height: element.offsetHeight
  1865. };
  1866. },
  1867. on: function(eventType, handler) {
  1868. this.element['on'+ eventType] = function() {
  1869. var evt = win.m_event;
  1870. evt.target = evt.srcElement;
  1871. handler(evt);
  1872. };
  1873. return this;
  1874. },
  1875. updateTransform: function(hash) {
  1876. if (!this.added) {
  1877. this.alignOnAdd = true;
  1878. return;
  1879. }
  1880. var wrapper = this,
  1881. elem = wrapper.element,
  1882. translateX = wrapper.translateX || 0,
  1883. translateY = wrapper.translateY || 0,
  1884. x = wrapper.x || 0,
  1885. y = wrapper.y || 0,
  1886. rotation = wrapper.rotation || 0,
  1887. radians = rotation * deg2rad,
  1888. costheta = mathCos(radians),
  1889. sintheta = mathSin(radians),
  1890. align = wrapper.textAlign || 'left',
  1891. alignCorrection = { right: 1, center: 2 }[align],
  1892. nonLeft = align && align != 'left';
  1893. if (translateX || translateY) {
  1894. wrapper.css({
  1895. marginLeft: translateX,
  1896. marginTop: translateY
  1897. });
  1898. }
  1899. if (wrapper.inverted) {
  1900. each(elem.childNodes, function(child) {
  1901. wrapper.renderer.invertChild(child, elem);
  1902. });
  1903. }
  1904. if (elem.tagName == 'SPAN') {
  1905. css(elem, {
  1906. filter: rotation ? ['progid:DXImageTransform.Microsoft.Matrix(M11=', costheta,
  1907. ', M12=', -sintheta, ', M21=', sintheta, ', M22=', costheta,
  1908. ', sizingMethod=\'auto expand\')'].join('') : NONE
  1909. });
  1910. var width = elem.offsetWidth,
  1911. height = elem.offsetHeight,
  1912. lineHeight = mathRound(pInt(elem.style.fontSize || 12) * 1.2);
  1913. x += width * mathMin(costheta, 0) + mathMin(sintheta, 0) * lineHeight;
  1914. y += height * mathMin(sintheta, 0) - mathMax(costheta, 0) * lineHeight;
  1915. if (nonLeft) {
  1916. x -= width / alignCorrection * costheta;
  1917. y -= height / alignCorrection * sintheta;
  1918. }
  1919. css(elem, {
  1920. textAlign: align,
  1921. left: x,
  1922. top: y
  1923. });
  1924. }
  1925. },
  1926. shadow: function(apply) {
  1927. var shadows = [],
  1928. i,
  1929. element = this.element,
  1930. renderer = this.renderer,
  1931. shadow,
  1932. elemStyle = element.style,
  1933. markup,
  1934. path = element.path;
  1935. if (''+ element.path === '') {
  1936. path = 'x';
  1937. }
  1938. if (apply) {
  1939. for (i = 1; i <= 3; i++) {
  1940. markup = ['<shape isShadow="true" strokeweight="', ( 7 - 2 * i ) ,
  1941. '" filled="false" path="', path,
  1942. '" coordsize="100,100" style="', element.style.cssText, '" />'];
  1943. shadow = createElement(renderer.prepVML(markup),
  1944. null, {
  1945. left: pInt(elemStyle.left) + 1,
  1946. top: pInt(elemStyle.top) + 1
  1947. }
  1948. );
  1949. markup = ['<stroke color="black" opacity="', (0.05 * i), '"/>'];
  1950. createElement(renderer.prepVML(markup), null, null, shadow);
  1951. element.parentNode.insertBefore(shadow, element);
  1952. shadows.push(shadow);
  1953. }
  1954. this.shadows = shadows;
  1955. }
  1956. return this;
  1957. }
  1958. });
  1959. VMLRenderer = function() {
  1960. this.init.apply(this, arguments);
  1961. };
  1962. VMLRenderer.prototype = merge( SVGRenderer.prototype, {
  1963. isIE8: userAgent.indexOf('MSIE 8.0') > -1,
  1964. init: function(container, width, height) {
  1965. var renderer = this,
  1966. boxWrapper;
  1967. renderer.Element = VMLElement;
  1968. renderer.alignedObjects = [];
  1969. boxWrapper = renderer.createElement(DIV);
  1970. container.appendChild(boxWrapper.element);
  1971. renderer.box = boxWrapper.element;
  1972. renderer.boxWrapper = boxWrapper;
  1973. renderer.setSize(width, height, false);
  1974. if (!doc.namespaces.hcv) {
  1975. doc.namespaces.add('hcv', 'urn:schemas-microsoft-com:vml');
  1976. doc.createStyleSheet().cssText =
  1977. 'hcv\\:fill, hcv\\:path, hcv\\:shape, hcv\\:stroke'+
  1978. '{ behavior:url(#default#VML); display: inline-block; } ';
  1979. }
  1980. },
  1981. clipRect: function (x, y, width, height) {
  1982. var clipRect = this.createElement();
  1983. return extend(clipRect, {
  1984. members: [],
  1985. left: x,
  1986. top: y,
  1987. width: width,
  1988. height: height,
  1989. getCSS: function(inverted) {
  1990. var rect = this,
  1991. top = rect.top,
  1992. left = rect.left,
  1993. right = left + rect.width,
  1994. bottom = top + rect.height,
  1995. ret = {
  1996. clip: 'rect('+
  1997. mathRound(inverted ? left : top) + 'px,'+
  1998. mathRound(inverted ? bottom : right) + 'px,'+
  1999. mathRound(inverted ? right : bottom) + 'px,'+
  2000. mathRound(inverted ? top : left) +'px)'
  2001. };
  2002. if (!inverted && docMode8) {
  2003. extend(ret, {
  2004. width: right +PX,
  2005. height: bottom +PX
  2006. });
  2007. }
  2008. return ret;
  2009. },
  2010. updateClipping: function() {
  2011. each(clipRect.members, function(member) {
  2012. member.css(clipRect.getCSS(member.inverted));
  2013. });
  2014. }
  2015. });
  2016. },
  2017. color: function(color, elem, prop) {
  2018. var colorObject,
  2019. regexRgba = /^rgba/,
  2020. markup;
  2021. if (color && color.linearGradient) {
  2022. var stopColor,
  2023. stopOpacity,
  2024. linearGradient = color.linearGradient,
  2025. angle,
  2026. color1,
  2027. opacity1,
  2028. color2,
  2029. opacity2;
  2030. each(color.stops, function(stop, i) {
  2031. if (regexRgba.test(stop[1])) {
  2032. colorObject = Color(stop[1]);
  2033. stopColor = colorObject.get('rgb');
  2034. stopOpacity = colorObject.get('a');
  2035. } else {
  2036. stopColor = stop[1];
  2037. stopOpacity = 1;
  2038. }
  2039. if (!i) {
  2040. color1 = stopColor;
  2041. opacity1 = stopOpacity;
  2042. } else {
  2043. color2 = stopColor;
  2044. opacity2 = stopOpacity;
  2045. }
  2046. });
  2047. angle = 90 - math.atan(
  2048. (linearGradient[3] - linearGradient[1]) /
  2049. (linearGradient[2] - linearGradient[0])
  2050. ) * 180 / mathPI;
  2051. markup = ['<', prop, ' colors="0% ', color1, ',100% ', color2, '" angle="', angle,
  2052. '" opacity="', opacity2, '" o:opacity2="', opacity1,
  2053. '" type="gradient" focus="100%" />'];
  2054. createElement(this.prepVML(markup), null, null, elem);
  2055. } else if (regexRgba.test(color) && elem.tagName != 'IMG') {
  2056. colorObject = Color(color);
  2057. markup = ['<', prop, ' opacity="', colorObject.get('a'), '"/>'];
  2058. createElement(this.prepVML(markup), null, null, elem);
  2059. return colorObject.get('rgb');
  2060. } else {
  2061. return color;
  2062. }
  2063. },
  2064. prepVML: function(markup) {
  2065. var vmlStyle = 'display:inline-block;behavior:url(#default#VML);',
  2066. isIE8 = this.isIE8;
  2067. markup = markup.join('');
  2068. if (isIE8) {
  2069. markup = markup.replace('/>', ' xmlns="urn:schemas-microsoft-com:vml" />');
  2070. if (markup.indexOf('style="') == -1) {
  2071. markup = markup.replace('/>', ' style="'+ vmlStyle +'" />');
  2072. } else {
  2073. markup = markup.replace('style="', 'style="'+ vmlStyle);
  2074. }
  2075. } else {
  2076. markup = markup.replace('<', '<hcv:');
  2077. }
  2078. return markup;
  2079. },
  2080. text: function(str, x, y) {
  2081. var defaultChartStyle = defaultOptions.chart.style;
  2082. return this.createElement('span')
  2083. .attr({
  2084. text: str,
  2085. x: mathRound(x),
  2086. y: mathRound(y)
  2087. })
  2088. .css({
  2089. whiteSpace: 'nowrap',
  2090. fontFamily: defaultChartStyle.fontFamily,
  2091. fontSize: defaultChartStyle.fontSize
  2092. });
  2093. },
  2094. path: function (path) {
  2095. return this.createElement('shape').attr({
  2096. coordsize: '100 100',
  2097. d: path
  2098. });
  2099. },
  2100. circle: function(x, y, r) {
  2101. return this.path(this.symbols.circle(x, y, r));
  2102. },
  2103. g: function(name) {
  2104. var wrapper,
  2105. attribs;
  2106. if (name) {
  2107. attribs = { 'className': PREFIX + name, 'class': PREFIX + name };
  2108. }
  2109. wrapper = this.createElement(DIV).attr(attribs);
  2110. return wrapper;
  2111. },
  2112. image: function(src, x, y, width, height) {
  2113. var obj = this.createElement('img')
  2114. .attr({ src: src });
  2115. if (arguments.length > 1) {
  2116. obj.css({
  2117. left: x,
  2118. top: y,
  2119. width: width,
  2120. height: height
  2121. });
  2122. }
  2123. return obj;
  2124. },
  2125. rect: function(x, y, width, height, r, strokeWidth) {
  2126. if (arguments.length > 1) {
  2127. var normalizer = (strokeWidth || 0) % 2 / 2;
  2128. x = mathRound(x || 0) + normalizer;
  2129. y = mathRound(y || 0) + normalizer;
  2130. width = mathRound((width || 0) - 2 * normalizer);
  2131. height = mathRound((height || 0) - 2 * normalizer);
  2132. }
  2133. if (isObject(x)) {
  2134. y = x.y;
  2135. width = x.width;
  2136. height = x.height;
  2137. r = x.r;
  2138. x = x.x;
  2139. }
  2140. return this.symbol('rect', x || 0, y || 0, r || 0, {
  2141. width: width || 0,
  2142. height: height || 0
  2143. });
  2144. },
  2145. invertChild: function(element, parentNode) {
  2146. var parentStyle = parentNode.style;
  2147. css(element, {
  2148. flip: 'x',
  2149. left: pInt(parentStyle.width) - 10,
  2150. top: pInt(parentStyle.height) - 10,
  2151. rotation: -90
  2152. });
  2153. },
  2154. symbols: {
  2155. arc: function (x, y, radius, options) {
  2156. var start = options.start,
  2157. end = options.end,
  2158. cosStart = mathCos(start),
  2159. sinStart = mathSin(start),
  2160. cosEnd = mathCos(end),
  2161. sinEnd = mathSin(end),
  2162. innerRadius = options.innerR;
  2163. if (end - start === 0) {
  2164. return ['x'];
  2165. } else if (end - start == 2 * mathPI) {
  2166. cosEnd = -0.07 / radius;
  2167. }
  2168. return [
  2169. 'wa',
  2170. x - radius,
  2171. y - radius,
  2172. x + radius,
  2173. y + radius,
  2174. x + radius * cosStart,
  2175. y + radius * sinStart,
  2176. x + radius * cosEnd,
  2177. y + radius * sinEnd,
  2178. 'at',
  2179. x - innerRadius,
  2180. y - innerRadius,
  2181. x + innerRadius,
  2182. y + innerRadius,
  2183. x + innerRadius * cosEnd,
  2184. y + innerRadius * sinEnd,
  2185. x + innerRadius * cosStart,
  2186. y + innerRadius * sinStart,
  2187. 'x',
  2188. 'e'
  2189. ];
  2190. },
  2191. circle: function (x, y, r) {
  2192. return [
  2193. 'wa',
  2194. x - r,
  2195. y - r,
  2196. x + r,
  2197. y + r,
  2198. x + r,
  2199. y,
  2200. x + r,
  2201. y,
  2202. 'e'
  2203. ];
  2204. },
  2205. rect: function (left, top, r, options) {
  2206. var width = options.width,
  2207. height = options.height,
  2208. right = left + width,
  2209. bottom = top + height;
  2210. r = mathMin(r, width, height);
  2211. return [
  2212. M,
  2213. left + r, top,
  2214. L,
  2215. right - r, top,
  2216. 'wa',
  2217. right - 2 * r, top,
  2218. right, top + 2 * r,
  2219. right - r, top,
  2220. right, top + r,
  2221. L,
  2222. right, bottom - r,
  2223. 'wa',
  2224. right - 2 * r, bottom - 2 * r,
  2225. right, bottom,
  2226. right, bottom - r,
  2227. right - r, bottom,
  2228. L,
  2229. left + r, bottom,
  2230. 'wa',
  2231. left, bottom - 2 * r,
  2232. left + 2 * r, bottom,
  2233. left + r, bottom,
  2234. left, bottom - r,
  2235. L,
  2236. left, top + r,
  2237. 'wa',
  2238. left, top,
  2239. left + 2 * r, top + 2 * r,
  2240. left, top + r,
  2241. left + r, top,
  2242. 'x',
  2243. 'e'
  2244. ];
  2245. }
  2246. }
  2247. });
  2248. }
  2249. var CanVGRenderer;
  2250. if (useCanVG) {
  2251. CanVGRenderer = function(container) {
  2252. var contStyle = container.style,
  2253. canvas;
  2254. this.init.apply(this, arguments);
  2255. canvas = createElement('canvas', {
  2256. width: container.offsetWidth,
  2257. height: container.offsetHeight
  2258. }, {
  2259. position: RELATIVE,
  2260. left: contStyle.left,
  2261. top: contStyle.top
  2262. }, container.parentNode);
  2263. css(container, {
  2264. position: ABSOLUTE,
  2265. visibility: HIDDEN
  2266. });
  2267. this.container = container;
  2268. this.canvas = canvas;
  2269. };
  2270. CanVGRenderer.prototype = merge( SVGRenderer.prototype, {
  2271. draw: function() {
  2272. var renderer = this;
  2273. if (win.canvg) {
  2274. canvg(renderer.canvas, renderer.container.innerHTML);
  2275. } else {
  2276. deferredCanvases.push(function() {
  2277. renderer.draw()
  2278. });
  2279. }
  2280. }
  2281. });
  2282. }
  2283. var Renderer = VMLRenderer || CanVGRenderer || SVGRenderer;
  2284. function Chart (options, callback) {
  2285. defaultXAxisOptions = merge(defaultXAxisOptions, defaultOptions.xAxis);
  2286. defaultYAxisOptions = merge(defaultYAxisOptions, defaultOptions.yAxis);
  2287. defaultOptions.xAxis = defaultOptions.yAxis = null;
  2288. options = merge(defaultOptions, options);
  2289. var optionsChart = options.chart,
  2290. optionsMargin = optionsChart.margin,
  2291. margin = isObject(optionsMargin) ?
  2292. optionsMargin :
  2293. [optionsMargin, optionsMargin, optionsMargin, optionsMargin],
  2294. optionsMarginTop = pick(optionsChart.marginTop, margin[0]),
  2295. optionsMarginRight = pick(optionsChart.marginRight, margin[1]),
  2296. optionsMarginBottom = pick(optionsChart.marginBottom, margin[2]),
  2297. optionsMarginLeft = pick(optionsChart.marginLeft, margin[3]),
  2298. spacingTop = optionsChart.spacingTop,
  2299. spacingRight = optionsChart.spacingRight,
  2300. spacingBottom = optionsChart.spacingBottom,
  2301. spacingLeft = optionsChart.spacingLeft,
  2302. spacingBox,
  2303. chartTitleOptions,
  2304. chartSubtitleOptions,
  2305. plotTop,
  2306. marginRight,
  2307. marginBottom,
  2308. plotLeft,
  2309. axisOffset,
  2310. renderTo,
  2311. renderToClone,
  2312. canvas,
  2313. container,
  2314. containerId,
  2315. containerWidth,
  2316. containerHeight,
  2317. chartWidth,
  2318. chartHeight,
  2319. oldChartWidth,
  2320. oldChartHeight,
  2321. chartBackground,
  2322. plotBackground,
  2323. plotBGImage,
  2324. plotBorder,
  2325. chart = this,
  2326. chartEvents = optionsChart.events,
  2327. runChartClick = chartEvents && !!chartEvents.click,
  2328. eventType,
  2329. isInsidePlot,
  2330. tooltip,
  2331. mouseIsDown,
  2332. loadingDiv,
  2333. loadingSpan,
  2334. loadingShown,
  2335. plotHeight,
  2336. plotWidth,
  2337. tracker,
  2338. trackerGroup,
  2339. placeTrackerGroup,
  2340. legend,
  2341. legendWidth,
  2342. legendHeight,
  2343. chartPosition,
  2344. hasCartesianSeries = optionsChart.showAxes,
  2345. isResizing = 0,
  2346. axes = [],
  2347. maxTicks,
  2348. series = [],
  2349. inverted,
  2350. renderer,
  2351. tooltipTick,
  2352. tooltipInterval,
  2353. hoverX,
  2354. drawChartBox,
  2355. getMargins,
  2356. resetMargins,
  2357. setChartSize,
  2358. resize,
  2359. zoom,
  2360. zoomOut;
  2361. function Axis (chart, options) {
  2362. var isXAxis = options.isX,
  2363. opposite = options.opposite,
  2364. horiz = inverted ? !isXAxis : isXAxis,
  2365. side = horiz ?
  2366. (opposite ? 0 : 2 ) :
  2367. (opposite ? 1 : 3 ),
  2368. stacks = {};
  2369. options = merge(
  2370. isXAxis ? defaultXAxisOptions : defaultYAxisOptions,
  2371. [defaultTopAxisOptions, defaultRightAxisOptions,
  2372. defaultBottomAxisOptions, defaultLeftAxisOptions][side],
  2373. options
  2374. );
  2375. var axis = this,
  2376. isDatetimeAxis = options.type == 'datetime',
  2377. offset = options.offset || 0,
  2378. xOrY = isXAxis ? 'x' : 'y',
  2379. axisLength,
  2380. transA,
  2381. oldTransA,
  2382. transB = horiz ? plotLeft : marginBottom,
  2383. translate,
  2384. getPlotLinePath,
  2385. axisGroup,
  2386. gridGroup,
  2387. axisLine,
  2388. dataMin,
  2389. dataMax,
  2390. associatedSeries,
  2391. userSetMin,
  2392. userSetMax,
  2393. max = null,
  2394. min = null,
  2395. oldMin,
  2396. oldMax,
  2397. minPadding = options.minPadding,
  2398. maxPadding = options.maxPadding,
  2399. isLinked = defined(options.linkedTo),
  2400. ignoreMinPadding,
  2401. ignoreMaxPadding,
  2402. usePercentage,
  2403. events = options.events,
  2404. eventType,
  2405. plotLinesAndBands = [],
  2406. tickInterval,
  2407. minorTickInterval,
  2408. magnitude,
  2409. tickPositions,
  2410. ticks = {},
  2411. minorTicks = {},
  2412. alternateBands = {},
  2413. tickAmount,
  2414. labelOffset,
  2415. axisTitleMargin,
  2416. dateTimeLabelFormat,
  2417. categories = options.categories,
  2418. labelFormatter = options.labels.formatter ||
  2419. function() {
  2420. var value = this.value,
  2421. ret;
  2422. if (dateTimeLabelFormat) {
  2423. ret = dateFormat(dateTimeLabelFormat, value);
  2424. } else if (tickInterval % 1000000 === 0) {
  2425. ret = (value / 1000000) +'M';
  2426. } else if (tickInterval % 1000 === 0) {
  2427. ret = (value / 1000) +'k';
  2428. } else if (!categories && value >= 1000) {
  2429. ret = numberFormat(value, 0);
  2430. } else {
  2431. ret = value;
  2432. }
  2433. return ret;
  2434. },
  2435. staggerLines = horiz && options.labels.staggerLines,
  2436. reversed = options.reversed,
  2437. tickmarkOffset = (categories && options.tickmarkPlacement == 'between') ? 0.5 : 0;
  2438. function Tick(pos, minor) {
  2439. var tick = this;
  2440. tick.pos = pos;
  2441. tick.minor = minor;
  2442. tick.isNew = true;
  2443. if (!minor) {
  2444. tick.addLabel();
  2445. }
  2446. }
  2447. Tick.prototype = {
  2448. addLabel: function() {
  2449. var pos = this.pos,
  2450. labelOptions = options.labels,
  2451. str,
  2452. withLabel = !((pos == min && !pick(options.showFirstLabel, 1)) ||
  2453. (pos == max && !pick(options.showLastLabel, 0))),
  2454. label = this.label;
  2455. str = labelFormatter.call({
  2456. isFirst: pos == tickPositions[0],
  2457. isLast: pos == tickPositions[tickPositions.length - 1],
  2458. dateTimeLabelFormat: dateTimeLabelFormat,
  2459. value: (categories && categories[pos] ? categories[pos] : pos)
  2460. });
  2461. if (label === UNDEFINED) {
  2462. this.label =
  2463. defined(str) && withLabel && labelOptions.enabled ?
  2464. renderer.text(
  2465. str,
  2466. 0,
  2467. 0
  2468. )
  2469. .attr({
  2470. align: labelOptions.align,
  2471. rotation: labelOptions.rotation
  2472. })
  2473. .css(labelOptions.style)
  2474. .add(axisGroup):
  2475. null;
  2476. } else if (label) {
  2477. label.attr({ text: str });
  2478. }
  2479. },
  2480. getLabelSize: function() {
  2481. var label = this.label;
  2482. return label ?
  2483. ((this.labelBBox = label.getBBox()))[horiz ? 'height' : 'width'] :
  2484. 0;
  2485. },
  2486. render: function(index, old) {
  2487. var tick = this,
  2488. major = !tick.minor,
  2489. label = tick.label,
  2490. pos = tick.pos,
  2491. labelOptions = options.labels,
  2492. gridLine = tick.gridLine,
  2493. gridLineWidth = major ? options.gridLineWidth : options.minorGridLineWidth,
  2494. gridLineColor = major ? options.gridLineColor : options.minorGridLineColor,
  2495. dashStyle = major ?
  2496. options.gridLineDashStyle :
  2497. options.minorGridLineDashStyle,
  2498. gridLinePath,
  2499. mark = tick.mark,
  2500. markPath,
  2501. tickLength = major ? options.tickLength : options.minorTickLength,
  2502. tickWidth = major ? options.tickWidth : (options.minorTickWidth || 0),
  2503. tickColor = major ? options.tickColor : options.minorTickColor,
  2504. tickPosition = major ? options.tickPosition : options.minorTickPosition,
  2505. step = labelOptions.step,
  2506. cHeight = old && oldChartHeight || chartHeight,
  2507. attribs,
  2508. x,
  2509. y;
  2510. x = horiz ?
  2511. translate(pos + tickmarkOffset, null, null, old) + transB :
  2512. plotLeft + offset + (opposite ? (old && oldChartWidth || chartWidth) - marginRight - plotLeft : 0);
  2513. y = horiz ?
  2514. cHeight - marginBottom + offset - (opposite ? plotHeight : 0) :
  2515. cHeight - translate(pos + tickmarkOffset, null, null, old) - transB;
  2516. if (gridLineWidth) {
  2517. gridLinePath = getPlotLinePath(pos + tickmarkOffset, gridLineWidth, old);
  2518. if (gridLine === UNDEFINED) {
  2519. attribs = {
  2520. stroke: gridLineColor,
  2521. 'stroke-width': gridLineWidth
  2522. };
  2523. if (dashStyle) {
  2524. attribs.dashstyle = dashStyle;
  2525. }
  2526. tick.gridLine = gridLine =
  2527. gridLineWidth ?
  2528. renderer.path(gridLinePath)
  2529. .attr(attribs).add(gridGroup) :
  2530. null;
  2531. }
  2532. if (gridLine && gridLinePath) {
  2533. gridLine.animate({
  2534. d: gridLinePath
  2535. });
  2536. }
  2537. }
  2538. if (tickWidth) {
  2539. if (tickPosition == 'inside') {
  2540. tickLength = -tickLength;
  2541. }
  2542. if (opposite) {
  2543. tickLength = -tickLength;
  2544. }
  2545. markPath = renderer.crispLine([
  2546. M,
  2547. x,
  2548. y,
  2549. L,
  2550. x + (horiz ? 0 : -tickLength),
  2551. y + (horiz ? tickLength : 0)
  2552. ], tickWidth);
  2553. if (mark) {
  2554. mark.animate({
  2555. d: markPath
  2556. });
  2557. } else {
  2558. tick.mark = renderer.path(
  2559. markPath
  2560. ).attr({
  2561. stroke: tickColor,
  2562. 'stroke-width': tickWidth
  2563. }).add(axisGroup);
  2564. }
  2565. }
  2566. if (label) {
  2567. x = x + labelOptions.x - (tickmarkOffset && horiz ?
  2568. tickmarkOffset * transA * (reversed ? -1 : 1) : 0);
  2569. y = y + labelOptions.y - (tickmarkOffset && !horiz ?
  2570. tickmarkOffset * transA * (reversed ? 1 : -1) : 0);
  2571. if (staggerLines) {
  2572. y += (index % staggerLines) * 16;
  2573. }
  2574. if (step) {
  2575. label[index % step ? 'hide' : 'show']();
  2576. }
  2577. label[tick.isNew ? 'attr' : 'animate']({
  2578. x: x,
  2579. y: y
  2580. });
  2581. }
  2582. tick.isNew = false;
  2583. },
  2584. destroy: function() {
  2585. var tick = this,
  2586. n;
  2587. for (n in tick) {
  2588. if (tick[n] && tick[n].destroy) {
  2589. tick[n].destroy();
  2590. }
  2591. }
  2592. }
  2593. };
  2594. function PlotLineOrBand(options) {
  2595. var plotLine = this;
  2596. if (options) {
  2597. plotLine.options = options;
  2598. plotLine.id = options.id;
  2599. }
  2600. return plotLine;
  2601. }
  2602. PlotLineOrBand.prototype = {
  2603. render: function () {
  2604. var plotLine = this,
  2605. options = plotLine.options,
  2606. optionsLabel = options.label,
  2607. label = plotLine.label,
  2608. width = options.width,
  2609. to = options.to,
  2610. toPath,
  2611. from = options.from,
  2612. dashStyle = options.dashStyle,
  2613. svgElem = plotLine.svgElem,
  2614. path = [],
  2615. addEvent,
  2616. eventType,
  2617. xs,
  2618. ys,
  2619. x,
  2620. y,
  2621. color = options.color,
  2622. zIndex = options.zIndex,
  2623. events = options.events,
  2624. attribs;
  2625. if (width) {
  2626. path = getPlotLinePath(options.value, width);
  2627. attribs = {
  2628. stroke: color,
  2629. 'stroke-width': width
  2630. };
  2631. if (dashStyle) {
  2632. attribs.dashstyle = dashStyle;
  2633. }
  2634. }
  2635. else if (defined(from) && defined(to)) {
  2636. from = mathMax(from, min);
  2637. to = mathMin(to, max);
  2638. toPath = getPlotLinePath(to);
  2639. path = getPlotLinePath(from);
  2640. if (path && toPath) {
  2641. path.push(
  2642. toPath[4],
  2643. toPath[5],
  2644. toPath[1],
  2645. toPath[2]
  2646. );
  2647. } else {
  2648. path = null;
  2649. }
  2650. attribs = {
  2651. fill: color
  2652. };
  2653. } else {
  2654. return;
  2655. }
  2656. if (defined(zIndex)) {
  2657. attribs.zIndex = zIndex;
  2658. }
  2659. if (svgElem) {
  2660. if (path) {
  2661. svgElem.animate({
  2662. d: path
  2663. }, null, svgElem.onGetPath);
  2664. } else {
  2665. svgElem.hide();
  2666. svgElem.onGetPath = function() {
  2667. svgElem.show();
  2668. }
  2669. }
  2670. } else if (path && path.length) {
  2671. plotLine.svgElem = svgElem = renderer.path(path)
  2672. .attr(attribs).add();
  2673. if (events) {
  2674. addEvent = function(eventType) {
  2675. svgElem.on(eventType, function(e) {
  2676. events[eventType].apply(plotLine, [e]);
  2677. });
  2678. };
  2679. for (eventType in events) {
  2680. addEvent(eventType);
  2681. }
  2682. }
  2683. }
  2684. if (optionsLabel && defined(optionsLabel.text) && path && path.length && plotWidth > 0 && plotHeight > 0) {
  2685. optionsLabel = merge({
  2686. align: horiz && toPath && 'center',
  2687. x: horiz ? !toPath && 4 : 10,
  2688. verticalAlign : !horiz && toPath && 'middle',
  2689. y: horiz ? toPath ? 16 : 10 : toPath ? 6 : -4,
  2690. rotation: horiz && !toPath && 90
  2691. }, optionsLabel);
  2692. if (!label) {
  2693. plotLine.label = label = renderer.text(
  2694. optionsLabel.text,
  2695. 0,
  2696. 0
  2697. )
  2698. .attr({
  2699. align: optionsLabel.textAlign || optionsLabel.align,
  2700. rotation: optionsLabel.rotation,
  2701. zIndex: zIndex
  2702. })
  2703. .css(optionsLabel.style)
  2704. .add();
  2705. }
  2706. xs = [path[1], path[4], path[6] || path[1]];
  2707. ys = [path[2], path[5], path[7] || path[2]];
  2708. x = mathMin.apply(math, xs);
  2709. y = mathMin.apply(math, ys);
  2710. label.align(optionsLabel, false, {
  2711. x: x,
  2712. y: y,
  2713. width: mathMax.apply(math, xs) - x,
  2714. height: mathMax.apply(math, ys) - y
  2715. });
  2716. label.show();
  2717. } else if (label) {
  2718. label.hide();
  2719. }
  2720. return plotLine;
  2721. },
  2722. destroy: function() {
  2723. var obj = this,
  2724. n;
  2725. for (n in obj) {
  2726. if (obj[n] && obj[n].destroy) {
  2727. obj[n].destroy();
  2728. }
  2729. delete obj[n];
  2730. }
  2731. erase(plotLinesAndBands, obj);
  2732. }
  2733. };
  2734. function getSeriesExtremes() {
  2735. var posStack = [],
  2736. negStack = [],
  2737. run;
  2738. dataMin = dataMax = null;
  2739. associatedSeries = [];
  2740. each(series, function(serie) {
  2741. run = false;
  2742. each(['xAxis', 'yAxis'], function(strAxis) {
  2743. if (
  2744. serie.isCartesian &&
  2745. (strAxis == 'xAxis' && isXAxis || strAxis == 'yAxis' && !isXAxis) && (
  2746. (serie.options[strAxis] == options.index) ||
  2747. (serie.options[strAxis] === UNDEFINED && options.index === 0)
  2748. )
  2749. ) {
  2750. serie[strAxis] = axis;
  2751. associatedSeries.push(serie);
  2752. run = true;
  2753. }
  2754. });
  2755. if (!serie.visible && optionsChart.ignoreHiddenSeries) {
  2756. run = false;
  2757. }
  2758. if (run) {
  2759. var stacking,
  2760. posPointStack,
  2761. negPointStack,
  2762. stackKey,
  2763. negKey;
  2764. if (!isXAxis) {
  2765. stacking = serie.options.stacking;
  2766. usePercentage = stacking == 'percent';
  2767. if (stacking) {
  2768. stackKey = serie.type + pick(serie.options.stack, '');
  2769. negKey = '-'+ stackKey;
  2770. serie.stackKey = stackKey;
  2771. posPointStack = posStack[stackKey] || [];
  2772. posStack[stackKey] = posPointStack;
  2773. negPointStack = negStack[negKey] || [];
  2774. negStack[negKey] = negPointStack;
  2775. }
  2776. if (usePercentage) {
  2777. dataMin = 0;
  2778. dataMax = 99;
  2779. }
  2780. }
  2781. if (serie.isCartesian) {
  2782. each(serie.data, function(point, i) {
  2783. var pointX = point.x,
  2784. pointY = point.y,
  2785. isNegative = pointY < 0,
  2786. pointStack = isNegative ? negPointStack : posPointStack,
  2787. key = isNegative ? negKey : stackKey,
  2788. totalPos;
  2789. if (dataMin === null) {
  2790. dataMin = dataMax = point[xOrY];
  2791. }
  2792. if (isXAxis) {
  2793. if (pointX > dataMax) {
  2794. dataMax = pointX;
  2795. } else if (pointX < dataMin) {
  2796. dataMin = pointX;
  2797. }
  2798. }
  2799. else if (defined(pointY)) {
  2800. if (stacking) {
  2801. pointStack[pointX] =
  2802. defined(pointStack[pointX]) ?
  2803. pointStack[pointX] + pointY : pointY;
  2804. }
  2805. totalPos = pointStack ? pointStack[pointX] : pointY;
  2806. if (!usePercentage) {
  2807. if (totalPos > dataMax) {
  2808. dataMax = totalPos;
  2809. } else if (totalPos < dataMin) {
  2810. dataMin = totalPos;
  2811. }
  2812. }
  2813. if (stacking) {
  2814. if (!stacks[key]) {
  2815. stacks[key] = {};
  2816. }
  2817. stacks[key][pointX] = {
  2818. total: totalPos,
  2819. cum: totalPos
  2820. };
  2821. }
  2822. }
  2823. });
  2824. if (/(area|column|bar)/.test(serie.type) && !isXAxis) {
  2825. if (dataMin >= 0) {
  2826. dataMin = 0;
  2827. ignoreMinPadding = true;
  2828. } else if (dataMax < 0) {
  2829. dataMax = 0;
  2830. ignoreMaxPadding = true;
  2831. }
  2832. }
  2833. }
  2834. }
  2835. });
  2836. }
  2837. translate = function(val, backwards, cvsCoord, old) {
  2838. var sign = 1,
  2839. cvsOffset = 0,
  2840. localA = old ? oldTransA : transA,
  2841. localMin = old ? oldMin : min,
  2842. returnValue;
  2843. if (!localA) {
  2844. localA = transA;
  2845. }
  2846. if (cvsCoord) {
  2847. sign *= -1;
  2848. cvsOffset = axisLength;
  2849. }
  2850. if (reversed) {
  2851. sign *= -1;
  2852. cvsOffset -= sign * axisLength;
  2853. }
  2854. if (backwards) {
  2855. if (reversed) {
  2856. val = axisLength - val;
  2857. }
  2858. returnValue = val / localA + localMin;
  2859. } else {
  2860. returnValue = sign * (val - localMin) * localA + cvsOffset;
  2861. }
  2862. return returnValue;
  2863. };
  2864. getPlotLinePath = function(value, lineWidth, old) {
  2865. var x1,
  2866. y1,
  2867. x2,
  2868. y2,
  2869. translatedValue = translate(value, null, null, old),
  2870. cHeight = old && oldChartHeight || chartHeight,
  2871. cWidth = old && oldChartWidth || chartWidth,
  2872. skip;
  2873. x1 = x2 = mathRound(translatedValue + transB);
  2874. y1 = y2 = mathRound(cHeight - translatedValue - transB);
  2875. if (isNaN(translatedValue)) {
  2876. skip = true;
  2877. } else if (horiz) {
  2878. y1 = plotTop;
  2879. y2 = cHeight - marginBottom;
  2880. if (x1 < plotLeft || x1 > plotLeft + plotWidth) {
  2881. skip = true;
  2882. }
  2883. } else {
  2884. x1 = plotLeft;
  2885. x2 = cWidth - marginRight;
  2886. if (y1 < plotTop || y1 > plotTop + plotHeight) {
  2887. skip = true;
  2888. }
  2889. }
  2890. return skip ?
  2891. null :
  2892. renderer.crispLine([M, x1, y1, L, x2, y2], lineWidth || 0);
  2893. };
  2894. function normalizeTickInterval(interval, multiples) {
  2895. var normalized;
  2896. magnitude = multiples ? 1 : math.pow(10, mathFloor(math.log(interval) / math.LN10));
  2897. normalized = interval / magnitude;
  2898. if (!multiples) {
  2899. multiples = [1, 2, 2.5, 5, 10];
  2900. if (options.allowDecimals === false) {
  2901. if (magnitude == 1) {
  2902. multiples = [1, 2, 5, 10];
  2903. } else if (magnitude <= 0.1) {
  2904. multiples = [1 / magnitude];
  2905. }
  2906. }
  2907. }
  2908. for (var i = 0; i < multiples.length; i++) {
  2909. interval = multiples[i];
  2910. if (normalized <= (multiples[i] + (multiples[i+1] || multiples[i])) / 2) {
  2911. break;
  2912. }
  2913. }
  2914. interval *= magnitude;
  2915. return interval;
  2916. }
  2917. function setDateTimeTickPositions() {
  2918. tickPositions = [];
  2919. var i,
  2920. useUTC = defaultOptions.global.useUTC,
  2921. oneSecond = 1000 / timeFactor,
  2922. oneMinute = 60000 / timeFactor,
  2923. oneHour = 3600000 / timeFactor,
  2924. oneDay = 24 * 3600000 / timeFactor,
  2925. oneWeek = 7 * 24 * 3600000 / timeFactor,
  2926. oneMonth = 30 * 24 * 3600000 / timeFactor,
  2927. oneYear = 31556952000 / timeFactor,
  2928. units = [[
  2929. 'second',
  2930. oneSecond,
  2931. [1, 2, 5, 10, 15, 30]
  2932. ], [
  2933. 'minute',
  2934. oneMinute,
  2935. [1, 2, 5, 10, 15, 30]
  2936. ], [
  2937. 'hour',
  2938. oneHour,
  2939. [1, 2, 3, 4, 6, 8, 12]
  2940. ], [
  2941. 'day',
  2942. oneDay,
  2943. [1, 2]
  2944. ], [
  2945. 'week',
  2946. oneWeek,
  2947. [1, 2]
  2948. ], [
  2949. 'month',
  2950. oneMonth,
  2951. [1, 2, 3, 4, 6]
  2952. ], [
  2953. 'year',
  2954. oneYear,
  2955. null
  2956. ]],
  2957. unit = units[6],
  2958. interval = unit[1],
  2959. multiples = unit[2];
  2960. for (i = 0; i < units.length; i++) {
  2961. unit = units[i];
  2962. interval = unit[1];
  2963. multiples = unit[2];
  2964. if (units[i+1]) {
  2965. var lessThan = (interval * multiples[multiples.length - 1] +
  2966. units[i + 1][1]) / 2;
  2967. if (tickInterval <= lessThan) {
  2968. break;
  2969. }
  2970. }
  2971. }
  2972. if (interval == oneYear && tickInterval < 5 * interval) {
  2973. multiples = [1, 2, 5];
  2974. }
  2975. var multitude = normalizeTickInterval(tickInterval / interval, multiples),
  2976. minYear,
  2977. minDate = new Date(min * timeFactor);
  2978. minDate.setMilliseconds(0);
  2979. if (interval >= oneSecond) {
  2980. minDate.setSeconds(interval >= oneMinute ? 0 :
  2981. multitude * mathFloor(minDate.getSeconds() / multitude));
  2982. }
  2983. if (interval >= oneMinute) {
  2984. minDate[setMinutes](interval >= oneHour ? 0 :
  2985. multitude * mathFloor(minDate[getMinutes]() / multitude));
  2986. }
  2987. if (interval >= oneHour) {
  2988. minDate[setHours](interval >= oneDay ? 0 :
  2989. multitude * mathFloor(minDate[getHours]() / multitude));
  2990. }
  2991. if (interval >= oneDay) {
  2992. minDate[setDate](interval >= oneMonth ? 1 :
  2993. multitude * mathFloor(minDate[getDate]() / multitude));
  2994. }
  2995. if (interval >= oneMonth) {
  2996. minDate[setMonth](interval >= oneYear ? 0 :
  2997. multitude * mathFloor(minDate[getMonth]() / multitude));
  2998. minYear = minDate[getFullYear]();
  2999. }
  3000. if (interval >= oneYear) {
  3001. minYear -= minYear % multitude;
  3002. minDate[setFullYear](minYear);
  3003. }
  3004. if (interval == oneWeek) {
  3005. minDate[setDate](minDate[getDate]() - minDate[getDay]() +
  3006. options.startOfWeek);
  3007. }
  3008. i = 1;
  3009. minYear = minDate[getFullYear]();
  3010. var time = minDate.getTime() / timeFactor,
  3011. minMonth = minDate[getMonth](),
  3012. minDateDate = minDate[getDate]();
  3013. while (time < max && i < plotWidth) {
  3014. tickPositions.push(time);
  3015. if (interval == oneYear) {
  3016. time = makeTime(minYear + i * multitude, 0) / timeFactor;
  3017. } else if (interval == oneMonth) {
  3018. time = makeTime(minYear, minMonth + i * multitude) / timeFactor;
  3019. } else if (!useUTC && (interval == oneDay || interval == oneWeek)) {
  3020. time = makeTime(minYear, minMonth, minDateDate +
  3021. i * multitude * (interval == oneDay ? 1 : 7));
  3022. } else {
  3023. time += interval * multitude;
  3024. }
  3025. i++;
  3026. }
  3027. tickPositions.push(time);
  3028. dateTimeLabelFormat = options.dateTimeLabelFormats[unit[0]];
  3029. }
  3030. function correctFloat(num) {
  3031. var invMag, ret = num;
  3032. if (defined(magnitude)) {
  3033. invMag = (magnitude < 1 ? mathRound(1 / magnitude) : 1) * 10;
  3034. ret = mathRound(num * invMag) / invMag;
  3035. }
  3036. return ret;
  3037. }
  3038. function setLinearTickPositions() {
  3039. var i,
  3040. roundedMin = mathFloor(min / tickInterval) * tickInterval,
  3041. roundedMax = mathCeil(max / tickInterval) * tickInterval;
  3042. tickPositions = [];
  3043. i = correctFloat(roundedMin);
  3044. while (i <= roundedMax) {
  3045. tickPositions.push(i);
  3046. i = correctFloat(i + tickInterval);
  3047. }
  3048. }
  3049. function setTickPositions(secondPass) {
  3050. var length,
  3051. catPad,
  3052. linkedParent,
  3053. linkedParentExtremes,
  3054. tickIntervalOption = options.tickInterval,
  3055. tickPixelIntervalOption = options.tickPixelInterval,
  3056. maxZoom = options.maxZoom || (
  3057. isXAxis ?
  3058. mathMin(chart.smallestInterval * 5, dataMax - dataMin) :
  3059. null
  3060. ),
  3061. zoomOffset;
  3062. axisLength = horiz ? plotWidth : plotHeight;
  3063. if (isLinked) {
  3064. linkedParent = chart[isXAxis ? 'xAxis' : 'yAxis'][options.linkedTo];
  3065. linkedParentExtremes = linkedParent.getExtremes();
  3066. min = pick(linkedParentExtremes.min, linkedParentExtremes.dataMin);
  3067. max = pick(linkedParentExtremes.max, linkedParentExtremes.dataMax);
  3068. }
  3069. else {
  3070. min = pick(userSetMin, options.min, dataMin);
  3071. max = pick(userSetMax, options.max, dataMax);
  3072. }
  3073. if (max - min < maxZoom) {
  3074. zoomOffset = (maxZoom - max + min) / 2;
  3075. min = mathMax(min - zoomOffset, pick(options.min, min - zoomOffset), dataMin);
  3076. max = mathMin(min + maxZoom, pick(options.max, min + maxZoom), dataMax);
  3077. }
  3078. if (!categories && !usePercentage && !isLinked && defined(min) && defined(max)) {
  3079. length = (max - min) || 1;
  3080. if (!defined(options.min) && !defined(userSetMin) && minPadding && (dataMin < 0 || !ignoreMinPadding)) {
  3081. min -= length * minPadding;
  3082. }
  3083. if (!defined(options.max) && !defined(userSetMax) && maxPadding && (dataMax > 0 || !ignoreMaxPadding)) {
  3084. max += length * maxPadding;
  3085. }
  3086. }
  3087. if (min == max) {
  3088. tickInterval = 1;
  3089. } else if (isLinked && !tickIntervalOption &&
  3090. tickPixelIntervalOption == linkedParent.options.tickPixelInterval) {
  3091. tickInterval = linkedParent.tickInterval;
  3092. } else {
  3093. tickInterval = pick(
  3094. tickIntervalOption,
  3095. categories ?
  3096. 1 :
  3097. (max - min) * tickPixelIntervalOption / axisLength
  3098. );
  3099. }
  3100. if (!isDatetimeAxis && !defined(options.tickInterval)) {
  3101. axis.tickInterval = tickInterval = normalizeTickInterval(tickInterval);
  3102. }
  3103. minorTickInterval = options.minorTickInterval === 'auto' && tickInterval ?
  3104. tickInterval / 5 : options.minorTickInterval;
  3105. if (isDatetimeAxis) {
  3106. setDateTimeTickPositions();
  3107. } else {
  3108. setLinearTickPositions();
  3109. }
  3110. if (!isLinked) {
  3111. if (categories || (isXAxis && chart.hasColumn)) {
  3112. catPad = (categories ? 1 : tickInterval) * 0.5;
  3113. min -= catPad;
  3114. max += catPad;
  3115. }
  3116. var roundedMin = tickPositions[0],
  3117. roundedMax = tickPositions[tickPositions.length - 1];
  3118. if (options.startOnTick) {
  3119. min = roundedMin;
  3120. } else if (min > roundedMin) {
  3121. tickPositions.shift();
  3122. }
  3123. if (options.endOnTick) {
  3124. max = roundedMax;
  3125. } else if (max < roundedMax) {
  3126. tickPositions.pop();
  3127. }
  3128. if (!maxTicks) {
  3129. maxTicks = {
  3130. x: 0,
  3131. y: 0
  3132. };
  3133. }
  3134. if (!isDatetimeAxis && tickPositions.length > maxTicks[xOrY]) {
  3135. maxTicks[xOrY] = tickPositions.length;
  3136. }
  3137. }
  3138. }
  3139. function adjustTickAmount() {
  3140. if (maxTicks && !isDatetimeAxis && !categories && !isLinked) {
  3141. var oldTickAmount = tickAmount,
  3142. calculatedTickAmount = tickPositions.length;
  3143. tickAmount = maxTicks[xOrY];
  3144. if (calculatedTickAmount < tickAmount) {
  3145. while (tickPositions.length < tickAmount) {
  3146. tickPositions.push( correctFloat(
  3147. tickPositions[tickPositions.length - 1] + tickInterval
  3148. ));
  3149. }
  3150. transA *= (calculatedTickAmount - 1) / (tickAmount - 1);
  3151. max = tickPositions[tickPositions.length - 1];
  3152. }
  3153. if (defined(oldTickAmount) && tickAmount != oldTickAmount) {
  3154. axis.isDirty = true;
  3155. }
  3156. }
  3157. }
  3158. function setScale() {
  3159. var type,
  3160. i;
  3161. oldMin = min;
  3162. oldMax = max;
  3163. getSeriesExtremes();
  3164. setTickPositions();
  3165. oldTransA = transA;
  3166. transA = axisLength / ((max - min) || 1);
  3167. if (!isXAxis) {
  3168. for (type in stacks) {
  3169. for (i in stacks[type]) {
  3170. stacks[type][i].cum = stacks[type][i].total;
  3171. }
  3172. }
  3173. }
  3174. if (!axis.isDirty) {
  3175. axis.isDirty = (min != oldMin || max != oldMax);
  3176. }
  3177. }
  3178. function setExtremes(newMin, newMax, redraw, animation) {
  3179. setAnimation(animation, chart);
  3180. redraw = pick(redraw, true);
  3181. fireEvent(axis, 'setExtremes', {
  3182. min: newMin,
  3183. max: newMax
  3184. }, function() {
  3185. userSetMin = newMin;
  3186. userSetMax = newMax;
  3187. if (redraw) {
  3188. chart.redraw();
  3189. }
  3190. });
  3191. }
  3192. function getExtremes() {
  3193. return {
  3194. min: min,
  3195. max: max,
  3196. dataMin: dataMin,
  3197. dataMax: dataMax
  3198. };
  3199. }
  3200. function getThreshold(threshold) {
  3201. if (min > threshold) {
  3202. threshold = min;
  3203. } else if (max < threshold) {
  3204. threshold = max;
  3205. }
  3206. return translate(threshold, 0, 1);
  3207. }
  3208. function addPlotBandOrLine(options) {
  3209. var obj = new PlotLineOrBand(options).render();
  3210. plotLinesAndBands.push(obj);
  3211. return obj;
  3212. }
  3213. function getOffset() {
  3214. var hasData = associatedSeries.length && defined(min) && defined(max),
  3215. titleOffset = 0,
  3216. titleMargin = 0,
  3217. axisTitleOptions = options.title,
  3218. labelOptions = options.labels,
  3219. directionFactor = [-1, 1, 1, -1][side];
  3220. if (!axisGroup) {
  3221. axisGroup = renderer.g('axis')
  3222. .attr({ zIndex: 7 })
  3223. .add();
  3224. gridGroup = renderer.g('grid')
  3225. .attr({ zIndex: 1 })
  3226. .add();
  3227. }
  3228. labelOffset = 0;
  3229. if (hasData || isLinked) {
  3230. each(tickPositions, function(pos) {
  3231. if (!ticks[pos]) {
  3232. ticks[pos] = new Tick(pos);
  3233. } else {
  3234. ticks[pos].addLabel();
  3235. }
  3236. if (side === 0 || side == 2 || { 1: 'left', 3: 'right' }[side] == labelOptions.align) {
  3237. labelOffset = mathMax(
  3238. ticks[pos].getLabelSize(),
  3239. labelOffset
  3240. );
  3241. }
  3242. });
  3243. if (staggerLines) {
  3244. labelOffset += (staggerLines - 1) * 16;
  3245. }
  3246. } else {
  3247. for (var n in ticks) {
  3248. ticks[n].destroy();
  3249. delete ticks[n];
  3250. }
  3251. }
  3252. if (axisTitleOptions && axisTitleOptions.text) {
  3253. if (!axis.axisTitle) {
  3254. axis.axisTitle = renderer.text(
  3255. axisTitleOptions.text,
  3256. 0,
  3257. 0
  3258. )
  3259. .attr({
  3260. zIndex: 7,
  3261. rotation: axisTitleOptions.rotation || 0,
  3262. align:
  3263. axisTitleOptions.textAlign ||
  3264. { low: 'left', middle: 'center', high: 'right' }[axisTitleOptions.align]
  3265. })
  3266. .css(axisTitleOptions.style)
  3267. .add();
  3268. }
  3269. titleOffset = axis.axisTitle.getBBox()[horiz ? 'height' : 'width'];
  3270. titleMargin = pick(axisTitleOptions.margin, horiz ? 5 : 10);
  3271. }
  3272. offset = directionFactor * (options.offset || axisOffset[side]);
  3273. axisTitleMargin =
  3274. labelOffset +
  3275. (side != 2 && labelOffset && directionFactor * options.labels[horiz ? 'y' : 'x']) +
  3276. titleMargin;
  3277. axisOffset[side] = mathMax(
  3278. axisOffset[side],
  3279. axisTitleMargin + titleOffset + directionFactor * offset
  3280. );
  3281. }
  3282. function render() {
  3283. var axisTitleOptions = options.title,
  3284. alternateGridColor = options.alternateGridColor,
  3285. lineWidth = options.lineWidth,
  3286. lineLeft,
  3287. lineTop,
  3288. linePath,
  3289. hasRendered = chart.hasRendered,
  3290. slideInTicks = hasRendered && defined(oldMin) && !isNaN(oldMin),
  3291. hasData = associatedSeries.length && defined(min) && defined(max);
  3292. axisLength = horiz ? plotWidth : plotHeight;
  3293. transA = axisLength / ((max - min) || 1);
  3294. transB = horiz ? plotLeft : marginBottom;
  3295. if (hasData || isLinked) {
  3296. if (minorTickInterval && !categories) {
  3297. var pos = min + (tickPositions[0] - min) % minorTickInterval;
  3298. for (pos; pos <= max; pos += minorTickInterval) {
  3299. if (!minorTicks[pos]) {
  3300. minorTicks[pos] = new Tick(pos, true);
  3301. }
  3302. if (slideInTicks && minorTicks[pos].isNew) {
  3303. minorTicks[pos].render(null, true);
  3304. }
  3305. minorTicks[pos].isActive = true;
  3306. minorTicks[pos].render();
  3307. }
  3308. }
  3309. each(tickPositions, function(pos, i) {
  3310. if (!isLinked || (pos >= min && pos <= max)) {
  3311. if (slideInTicks && ticks[pos].isNew) {
  3312. ticks[pos].render(i, true);
  3313. }
  3314. ticks[pos].isActive = true;
  3315. ticks[pos].render(i);
  3316. }
  3317. });
  3318. if (alternateGridColor) {
  3319. each(tickPositions, function(pos, i) {
  3320. if (i % 2 === 0 && pos < max) {
  3321. if (!alternateBands[pos]) {
  3322. alternateBands[pos] = new PlotLineOrBand();
  3323. }
  3324. alternateBands[pos].options = {
  3325. from: pos,
  3326. to: tickPositions[i + 1] !== UNDEFINED ? tickPositions[i + 1] : max,
  3327. color: alternateGridColor
  3328. };
  3329. alternateBands[pos].render();
  3330. alternateBands[pos].isActive = true;
  3331. }
  3332. });
  3333. }
  3334. if (!hasRendered) {
  3335. each((options.plotLines || []).concat(options.plotBands || []), function(plotLineOptions) {
  3336. plotLinesAndBands.push(new PlotLineOrBand(plotLineOptions).render());
  3337. });
  3338. }
  3339. }
  3340. each([ticks, minorTicks, alternateBands], function(coll) {
  3341. for (var pos in coll) {
  3342. if (!coll[pos].isActive) {
  3343. coll[pos].destroy();
  3344. delete coll[pos];
  3345. } else {
  3346. coll[pos].isActive = false;
  3347. }
  3348. }
  3349. });
  3350. if (lineWidth) {
  3351. lineLeft = plotLeft + (opposite ? plotWidth : 0) + offset;
  3352. lineTop = chartHeight - marginBottom - (opposite ? plotHeight : 0) + offset;
  3353. linePath = renderer.crispLine([
  3354. M,
  3355. horiz ?
  3356. plotLeft:
  3357. lineLeft,
  3358. horiz ?
  3359. lineTop:
  3360. plotTop,
  3361. L,
  3362. horiz ?
  3363. chartWidth - marginRight :
  3364. lineLeft,
  3365. horiz ?
  3366. lineTop:
  3367. chartHeight - marginBottom
  3368. ], lineWidth);
  3369. if (!axisLine) {
  3370. axisLine = renderer.path(linePath)
  3371. .attr({
  3372. stroke: options.lineColor,
  3373. 'stroke-width': lineWidth,
  3374. zIndex: 7
  3375. })
  3376. .add();
  3377. } else {
  3378. axisLine.animate({ d: linePath });
  3379. }
  3380. }
  3381. if (axis.axisTitle) {
  3382. var margin = horiz ? plotLeft : plotTop,
  3383. fontSize = pInt(axisTitleOptions.style.fontSize || 12),
  3384. alongAxis = {
  3385. low: margin + (horiz ? 0 : axisLength),
  3386. middle: margin + axisLength / 2,
  3387. high: margin + (horiz ? axisLength : 0)
  3388. }[axisTitleOptions.align],
  3389. offAxis = (horiz ? plotTop + plotHeight : plotLeft) +
  3390. (horiz ? 1 : -1) *
  3391. (opposite ? -1 : 1) *
  3392. axisTitleMargin +
  3393. (side == 2 ? fontSize : 0);
  3394. axis.axisTitle[hasRendered ? 'animate' : 'attr']({
  3395. x: horiz ?
  3396. alongAxis:
  3397. offAxis + (opposite ? plotWidth : 0) + offset +
  3398. (axisTitleOptions.x || 0),
  3399. y: horiz ?
  3400. offAxis - (opposite ? plotHeight : 0) + offset:
  3401. alongAxis + (axisTitleOptions.y || 0)
  3402. });
  3403. }
  3404. axis.isDirty = false;
  3405. }
  3406. function removePlotBandOrLine(id) {
  3407. for (var i = 0; i < plotLinesAndBands.length; i++) {
  3408. if (plotLinesAndBands[i].id == id) {
  3409. plotLinesAndBands[i].destroy();
  3410. }
  3411. }
  3412. }
  3413. function redraw() {
  3414. if (tracker.resetTracker) {
  3415. tracker.resetTracker();
  3416. }
  3417. render();
  3418. each(plotLinesAndBands, function(plotLine) {
  3419. plotLine.render();
  3420. });
  3421. each(associatedSeries, function(series) {
  3422. series.isDirty = true;
  3423. });
  3424. }
  3425. function setCategories(newCategories, doRedraw) {
  3426. axis.categories = categories = newCategories;
  3427. each(associatedSeries, function(series) {
  3428. series.translate();
  3429. series.setTooltipPoints(true);
  3430. });
  3431. axis.isDirty = true;
  3432. if (pick(doRedraw, true)) {
  3433. chart.redraw();
  3434. }
  3435. }
  3436. if (inverted && isXAxis && reversed === UNDEFINED) {
  3437. reversed = true;
  3438. }
  3439. extend(axis, {
  3440. addPlotBand: addPlotBandOrLine,
  3441. addPlotLine: addPlotBandOrLine,
  3442. adjustTickAmount: adjustTickAmount,
  3443. categories: categories,
  3444. getExtremes: getExtremes,
  3445. getPlotLinePath: getPlotLinePath,
  3446. getThreshold: getThreshold,
  3447. isXAxis: isXAxis,
  3448. options: options,
  3449. plotLinesAndBands: plotLinesAndBands,
  3450. getOffset: getOffset,
  3451. render: render,
  3452. setCategories: setCategories,
  3453. setExtremes: setExtremes,
  3454. setScale: setScale,
  3455. setTickPositions: setTickPositions,
  3456. translate: translate,
  3457. redraw: redraw,
  3458. removePlotBand: removePlotBandOrLine,
  3459. removePlotLine: removePlotBandOrLine,
  3460. reversed: reversed,
  3461. stacks: stacks
  3462. });
  3463. for (eventType in events) {
  3464. addEvent(axis, eventType, events[eventType]);
  3465. }
  3466. setScale();
  3467. }
  3468. function Toolbar(chart) {
  3469. var buttons = {};
  3470. function add(id, text, title, fn) {
  3471. if (!buttons[id]) {
  3472. var button = renderer.text(
  3473. text,
  3474. 0,
  3475. 0
  3476. )
  3477. .css(options.toolbar.itemStyle)
  3478. .align({
  3479. align: 'right',
  3480. x: - marginRight - 20,
  3481. y: plotTop + 30
  3482. })
  3483. .on('click', fn)
  3484. .attr({
  3485. align: 'right',
  3486. zIndex: 20
  3487. })
  3488. .add();
  3489. buttons[id] = button;
  3490. }
  3491. }
  3492. function remove(id) {
  3493. discardElement(buttons[id].element);
  3494. buttons[id] = null;
  3495. }
  3496. return {
  3497. add: add,
  3498. remove: remove
  3499. };
  3500. }
  3501. function Tooltip (options) {
  3502. var currentSeries,
  3503. borderWidth = options.borderWidth,
  3504. crosshairsOptions = options.crosshairs,
  3505. crosshairs = [],
  3506. style = options.style,
  3507. shared = options.shared,
  3508. padding = pInt(style.padding),
  3509. boxOffLeft = borderWidth + padding,
  3510. tooltipIsHidden = true,
  3511. boxWidth,
  3512. boxHeight,
  3513. currentX = 0,
  3514. currentY = 0;
  3515. style.padding = 0;
  3516. var group = renderer.g('tooltip')
  3517. .attr({
  3518. zIndex: 8,
  3519. translateY: -99
  3520. })
  3521. .add(),
  3522. box = renderer.rect(boxOffLeft, boxOffLeft, 0, 0, options.borderRadius, borderWidth)
  3523. .attr({
  3524. fill: options.backgroundColor,
  3525. 'stroke-width': borderWidth
  3526. })
  3527. .add(group)
  3528. .shadow(options.shadow),
  3529. label = renderer.text('', padding + boxOffLeft, pInt(style.fontSize) + padding + boxOffLeft)
  3530. .attr({ zIndex: 1 })
  3531. .css(style)
  3532. .add(group);
  3533. group.hide();
  3534. function defaultFormatter() {
  3535. var pThis = this,
  3536. points = pThis.points || splat(pThis.point),
  3537. xAxis = points[0].series.xAxis,
  3538. x = pThis.x,
  3539. isDateTime = xAxis && xAxis.options.type == 'datetime',
  3540. useHeader = isString(x) || isDateTime,
  3541. series,
  3542. s;
  3543. s = useHeader ?
  3544. ['<span style="font-size: 10px">',
  3545. (isDateTime ? dateFormat('%A, %b %e, %Y', x) : x),
  3546. '</span><br/>'] : [];
  3547. each(points, function(point) {
  3548. series = point.series;
  3549. s.push('<span style="color:'+ series.color +'">', (point.name || series.name), '</span>: ',
  3550. (!useHeader ? ('<b>x = '+ (point.name || point.x) + ',</b> ') : ''),
  3551. '<b>', (!useHeader ? 'y = ' : '' ), point.y, '</b><br/>');
  3552. });
  3553. return s.join('');
  3554. }
  3555. function move(finalX, finalY) {
  3556. currentX = tooltipIsHidden ? finalX : (2 * currentX + finalX) / 3;
  3557. currentY = tooltipIsHidden ? finalY : (currentY + finalY) / 2;
  3558. group.translate(currentX, currentY);
  3559. if (mathAbs(finalX - currentX) > 1 || mathAbs(finalY - currentY) > 1) {
  3560. tooltipTick = function() {
  3561. move(finalX, finalY);
  3562. };
  3563. } else {
  3564. tooltipTick = null;
  3565. }
  3566. }
  3567. function hide() {
  3568. if (!tooltipIsHidden) {
  3569. var hoverPoints = chart.hoverPoints;
  3570. group.hide();
  3571. each(crosshairs, function(crosshair) {
  3572. crosshair.hide();
  3573. });
  3574. if (hoverPoints) {
  3575. each (hoverPoints, function(point) {
  3576. point.setState();
  3577. });
  3578. }
  3579. chart.hoverPoints = null;
  3580. tooltipIsHidden = true;
  3581. }
  3582. }
  3583. function refresh(point) {
  3584. var x,
  3585. y,
  3586. boxX,
  3587. boxY,
  3588. show,
  3589. bBox,
  3590. plotX,
  3591. plotY = 0,
  3592. textConfig = {},
  3593. text,
  3594. pointConfig = [],
  3595. tooltipPos = point.tooltipPos,
  3596. formatter = options.formatter || defaultFormatter,
  3597. hoverPoints = chart.hoverPoints,
  3598. getConfig = function(point) {
  3599. return {
  3600. series: point.series,
  3601. point: point,
  3602. x: point.category,
  3603. y: point.y,
  3604. percentage: point.percentage,
  3605. total: point.total || point.stackTotal
  3606. };
  3607. };
  3608. if (shared) {
  3609. if (hoverPoints) {
  3610. each (hoverPoints, function(point) {
  3611. point.setState();
  3612. });
  3613. }
  3614. chart.hoverPoints = point;
  3615. each(point, function(item, i) {
  3616. item.setState(HOVER_STATE);
  3617. plotY += item.plotY;
  3618. pointConfig.push(getConfig(item));
  3619. });
  3620. plotX = point[0].plotX;
  3621. plotY = mathRound(plotY) / point.length;
  3622. textConfig = {
  3623. x: point[0].category
  3624. };
  3625. textConfig.points = pointConfig;
  3626. point = point[0];
  3627. } else {
  3628. textConfig = getConfig(point);
  3629. }
  3630. text = formatter.call(textConfig);
  3631. currentSeries = point.series;
  3632. plotX = shared ? plotX : point.plotX;
  3633. plotY = shared ? plotY : point.plotY;
  3634. x = mathRound(tooltipPos ? tooltipPos[0] : (inverted ? plotWidth - plotY : plotX));
  3635. y = mathRound(tooltipPos ? tooltipPos[1] : (inverted ? plotHeight - plotX : plotY));
  3636. show = !point.series.isCartesian || isInsidePlot(x, y);
  3637. if (text === false || !show) {
  3638. hide();
  3639. } else {
  3640. if (tooltipIsHidden) {
  3641. group.show();
  3642. tooltipIsHidden = false;
  3643. }
  3644. label.attr({
  3645. text: text
  3646. });
  3647. bBox = label.getBBox();
  3648. boxWidth = bBox.width;
  3649. boxHeight = bBox.height;
  3650. box.attr({
  3651. width: boxWidth + 2 * padding,
  3652. height: boxHeight + 2 * padding,
  3653. stroke: options.borderColor || point.color || currentSeries.color || '#606060'
  3654. });
  3655. boxX = x - boxWidth + plotLeft - 25;
  3656. boxY = y - boxHeight + plotTop + 10;
  3657. if (boxX < 7) {
  3658. boxX = 7;
  3659. boxY -= 30;
  3660. }
  3661. if (boxY < 5) {
  3662. boxY = 5;
  3663. } else if (boxY + boxHeight > chartHeight) {
  3664. boxY = chartHeight - boxHeight - 5;
  3665. }
  3666. move(mathRound(boxX - boxOffLeft), mathRound(boxY - boxOffLeft));
  3667. }
  3668. if (crosshairsOptions) {
  3669. crosshairsOptions = splat(crosshairsOptions);
  3670. var path,
  3671. i = crosshairsOptions.length,
  3672. attribs,
  3673. axis;
  3674. while (i--) {
  3675. if (crosshairsOptions[i] && (axis = point.series[i ? 'yAxis' : 'xAxis'])) {
  3676. path = axis
  3677. .getPlotLinePath(point[i ? 'y' : 'x'], 1);
  3678. if (crosshairs[i]) {
  3679. crosshairs[i].attr({ d: path, visibility: VISIBLE });
  3680. } else {
  3681. attribs = {
  3682. 'stroke-width': crosshairsOptions[i].width || 1,
  3683. stroke: crosshairsOptions[i].color || '#C0C0C0',
  3684. zIndex: 2
  3685. };
  3686. if (crosshairsOptions[i].dashStyle) {
  3687. attribs.dashstyle = crosshairsOptions[i].dashStyle;
  3688. }
  3689. crosshairs[i] = renderer.path(path)
  3690. .attr(attribs)
  3691. .add();
  3692. }
  3693. }
  3694. }
  3695. }
  3696. }
  3697. return {
  3698. shared: shared,
  3699. refresh: refresh,
  3700. hide: hide
  3701. };
  3702. }
  3703. function MouseTracker (chart, options) {
  3704. var mouseDownX,
  3705. mouseDownY,
  3706. hasDragged,
  3707. selectionMarker,
  3708. zoomType = optionsChart.zoomType,
  3709. zoomX = /x/.test(zoomType),
  3710. zoomY = /y/.test(zoomType),
  3711. zoomHor = zoomX && !inverted || zoomY && inverted,
  3712. zoomVert = zoomY && !inverted || zoomX && inverted;
  3713. function normalizeMouseEvent(e) {
  3714. var ePos;
  3715. e = e || win.event;
  3716. if (!e.target) {
  3717. e.target = e.srcElement;
  3718. }
  3719. ePos = e.touches ? e.touches.item(0) : e;
  3720. if (e.type != 'mousemove' || win.opera) {
  3721. chartPosition = getPosition(container);
  3722. }
  3723. if (isIE) {
  3724. e.chartX = e.x;
  3725. e.chartY = e.y;
  3726. } else {
  3727. if (ePos.layerX === UNDEFINED) {
  3728. e.chartX = ePos.pageX - chartPosition.left;
  3729. e.chartY = ePos.pageY - chartPosition.top;
  3730. } else {
  3731. e.chartX = e.layerX;
  3732. e.chartY = e.layerY;
  3733. }
  3734. }
  3735. return e;
  3736. }
  3737. function getMouseCoordinates(e) {
  3738. var coordinates = {
  3739. xAxis: [],
  3740. yAxis: []
  3741. };
  3742. each(axes, function(axis, i) {
  3743. var translate = axis.translate,
  3744. isXAxis = axis.isXAxis,
  3745. isHorizontal = inverted ? !isXAxis : isXAxis;
  3746. coordinates[isXAxis ? 'xAxis' : 'yAxis'].push({
  3747. axis: axis,
  3748. value: translate(
  3749. isHorizontal ?
  3750. e.chartX - plotLeft :
  3751. plotHeight - e.chartY + plotTop,
  3752. true
  3753. )
  3754. });
  3755. });
  3756. return coordinates;
  3757. }
  3758. function onmousemove (e) {
  3759. var point,
  3760. points,
  3761. hoverPoint = chart.hoverPoint,
  3762. hoverSeries = chart.hoverSeries,
  3763. i,
  3764. j,
  3765. distance = chartWidth,
  3766. index = inverted ? e.chartY : e.chartX - plotLeft;
  3767. if (tooltip && options.shared) {
  3768. points = [];
  3769. i = series.length;
  3770. for (j = 0; j < i; j++) {
  3771. if (series[j].visible && series[j].tooltipPoints.length) {
  3772. point = series[j].tooltipPoints[index];
  3773. point._dist = mathAbs(index - point.plotX);
  3774. distance = mathMin(distance, point._dist);
  3775. points.push(point);
  3776. }
  3777. }
  3778. i = points.length;
  3779. while (i--) {
  3780. if (points[i]._dist > distance) {
  3781. points.splice(i, 1);
  3782. }
  3783. }
  3784. if (points.length && (points[0].plotX != hoverX)) {
  3785. tooltip.refresh(points);
  3786. hoverX = points[0].plotX;
  3787. }
  3788. }
  3789. if (hoverSeries && hoverSeries.tracker) {
  3790. point = hoverSeries.tooltipPoints[index];
  3791. if (point && point != hoverPoint) {
  3792. point.onMouseOver();
  3793. }
  3794. }
  3795. }
  3796. function resetTracker() {
  3797. var hoverSeries = chart.hoverSeries,
  3798. hoverPoint = chart.hoverPoint;
  3799. if (hoverPoint) {
  3800. hoverPoint.onMouseOut();
  3801. }
  3802. if (hoverSeries) {
  3803. hoverSeries.onMouseOut();
  3804. }
  3805. if (tooltip) {
  3806. tooltip.hide();
  3807. }
  3808. hoverX = null;
  3809. }
  3810. function drop() {
  3811. if (selectionMarker) {
  3812. var selectionData = {
  3813. xAxis: [],
  3814. yAxis: []
  3815. },
  3816. selectionBox = selectionMarker.getBBox(),
  3817. selectionLeft = selectionBox.x - plotLeft,
  3818. selectionTop = selectionBox.y - plotTop;
  3819. if (hasDragged) {
  3820. each(axes, function(axis, i) {
  3821. var translate = axis.translate,
  3822. isXAxis = axis.isXAxis,
  3823. isHorizontal = inverted ? !isXAxis : isXAxis,
  3824. selectionMin = translate(
  3825. isHorizontal ?
  3826. selectionLeft :
  3827. plotHeight - selectionTop - selectionBox.height,
  3828. true
  3829. ),
  3830. selectionMax = translate(
  3831. isHorizontal ?
  3832. selectionLeft + selectionBox.width :
  3833. plotHeight - selectionTop,
  3834. true
  3835. );
  3836. selectionData[isXAxis ? 'xAxis' : 'yAxis'].push({
  3837. axis: axis,
  3838. min: mathMin(selectionMin, selectionMax),
  3839. max: mathMax(selectionMin, selectionMax)
  3840. });
  3841. });
  3842. fireEvent(chart, 'selection', selectionData, zoom);
  3843. }
  3844. selectionMarker = selectionMarker.destroy();
  3845. }
  3846. chart.mouseIsDown = mouseIsDown = hasDragged = false;
  3847. removeEvent(doc, hasTouch ? 'touchend' : 'mouseup', drop);
  3848. }
  3849. function setDOMEvents () {
  3850. var lastWasOutsidePlot = true;
  3851. container.onmousedown = function(e) {
  3852. e = normalizeMouseEvent(e);
  3853. chart.mouseIsDown = mouseIsDown = true;
  3854. mouseDownX = e.chartX;
  3855. mouseDownY = e.chartY;
  3856. addEvent(doc, hasTouch ? 'touchend' : 'mouseup', drop);
  3857. };
  3858. var mouseMove = function(e) {
  3859. if (e && e.touches && e.touches.length > 1) {
  3860. return;
  3861. }
  3862. e = normalizeMouseEvent(e);
  3863. if (!hasTouch) {
  3864. e.returnValue = false;
  3865. }
  3866. var chartX = e.chartX,
  3867. chartY = e.chartY,
  3868. isOutsidePlot = !isInsidePlot(chartX - plotLeft, chartY - plotTop);
  3869. if (hasTouch && e.type == 'touchstart') {
  3870. if (attr(e.target, 'isTracker')) {
  3871. if (!chart.runTrackerClick) {
  3872. e.preventDefault();
  3873. }
  3874. } else if (!runChartClick && !isOutsidePlot) {
  3875. e.preventDefault();
  3876. }
  3877. }
  3878. if (isOutsidePlot) {
  3879. if (!lastWasOutsidePlot) {
  3880. resetTracker();
  3881. }
  3882. if (chartX < plotLeft) {
  3883. chartX = plotLeft;
  3884. } else if (chartX > plotLeft + plotWidth) {
  3885. chartX = plotLeft + plotWidth;
  3886. }
  3887. if (chartY < plotTop) {
  3888. chartY = plotTop;
  3889. } else if (chartY > plotTop + plotHeight) {
  3890. chartY = plotTop + plotHeight;
  3891. }
  3892. }
  3893. if (mouseIsDown && e.type != 'touchstart') {
  3894. if ((hasDragged = Math.sqrt(
  3895. Math.pow(mouseDownX - chartX, 2) +
  3896. Math.pow(mouseDownY - chartY, 2)
  3897. ) > 10)) {
  3898. if (hasCartesianSeries && (zoomX || zoomY) &&
  3899. isInsidePlot(mouseDownX - plotLeft, mouseDownY - plotTop)) {
  3900. if (!selectionMarker) {
  3901. selectionMarker = renderer.rect(
  3902. plotLeft,
  3903. plotTop,
  3904. zoomHor ? 1 : plotWidth,
  3905. zoomVert ? 1 : plotHeight,
  3906. 0
  3907. )
  3908. .attr({
  3909. fill: 'rgba(69,114,167,0.25)',
  3910. zIndex: 7
  3911. })
  3912. .add();
  3913. }
  3914. }
  3915. if (selectionMarker && zoomHor) {
  3916. var xSize = chartX - mouseDownX;
  3917. selectionMarker.attr({
  3918. width: mathAbs(xSize),
  3919. x: (xSize > 0 ? 0 : xSize) + mouseDownX
  3920. });
  3921. }
  3922. if (selectionMarker && zoomVert) {
  3923. var ySize = chartY - mouseDownY;
  3924. selectionMarker.attr({
  3925. height: mathAbs(ySize),
  3926. y: (ySize > 0 ? 0 : ySize) + mouseDownY
  3927. });
  3928. }
  3929. }
  3930. } else if (!isOutsidePlot) {
  3931. onmousemove(e);
  3932. }
  3933. lastWasOutsidePlot = isOutsidePlot;
  3934. return isOutsidePlot || !hasCartesianSeries;
  3935. };
  3936. container.onmousemove = mouseMove;
  3937. addEvent(container, 'mouseleave', resetTracker);
  3938. container.ontouchstart = function(e) {
  3939. if (zoomX || zoomY) {
  3940. container.onmousedown(e);
  3941. }
  3942. mouseMove(e);
  3943. };
  3944. container.ontouchmove = mouseMove;
  3945. container.ontouchend = function() {
  3946. if (hasDragged) {
  3947. resetTracker();
  3948. }
  3949. };
  3950. container.onclick = function(e) {
  3951. var hoverPoint = chart.hoverPoint;
  3952. e = normalizeMouseEvent(e);
  3953. e.cancelBubble = true;
  3954. if (!hasDragged) {
  3955. if (hoverPoint && attr(e.target, 'isTracker')) {
  3956. var plotX = hoverPoint.plotX,
  3957. plotY = hoverPoint.plotY;
  3958. extend(hoverPoint, {
  3959. pageX: chartPosition.left + plotLeft +
  3960. (inverted ? plotWidth - plotY : plotX),
  3961. pageY: chartPosition.top + plotTop +
  3962. (inverted ? plotHeight - plotX : plotY)
  3963. });
  3964. fireEvent(hoverPoint.series, 'click', extend(e, {
  3965. point: hoverPoint
  3966. }));
  3967. hoverPoint.firePointEvent('click', e);
  3968. } else {
  3969. extend(e, getMouseCoordinates(e));
  3970. if (isInsidePlot(e.chartX - plotLeft, e.chartY - plotTop)) {
  3971. fireEvent(chart, 'click', e);
  3972. }
  3973. }
  3974. }
  3975. hasDragged = false;
  3976. };
  3977. }
  3978. placeTrackerGroup = function() {
  3979. if (!trackerGroup) {
  3980. chart.trackerGroup = trackerGroup = renderer.g('tracker')
  3981. .attr({ zIndex: 9 })
  3982. .add();
  3983. } else {
  3984. trackerGroup.translate(plotLeft, plotTop);
  3985. if (inverted) {
  3986. trackerGroup.attr({
  3987. width: chart.plotWidth,
  3988. height: chart.plotHeight
  3989. }).invert();
  3990. }
  3991. }
  3992. };
  3993. placeTrackerGroup();
  3994. if (options.enabled) {
  3995. chart.tooltip = tooltip = Tooltip(options);
  3996. }
  3997. setDOMEvents();
  3998. tooltipInterval = setInterval(function() {
  3999. if (tooltipTick) {
  4000. tooltipTick();
  4001. }
  4002. }, 32);
  4003. extend(this, {
  4004. zoomX: zoomX,
  4005. zoomY: zoomY,
  4006. resetTracker: resetTracker
  4007. });
  4008. }
  4009. var Legend = function(chart) {
  4010. var options = chart.options.legend;
  4011. if (!options.enabled) {
  4012. return;
  4013. }
  4014. var horizontal = options.layout == 'horizontal',
  4015. symbolWidth = options.symbolWidth,
  4016. symbolPadding = options.symbolPadding,
  4017. allItems,
  4018. style = options.style,
  4019. itemStyle = options.itemStyle,
  4020. itemHoverStyle = options.itemHoverStyle,
  4021. itemHiddenStyle = options.itemHiddenStyle,
  4022. padding = pInt(style.padding),
  4023. rightPadding = 20,
  4024. y = 18,
  4025. initialItemX = 4 + padding + symbolWidth + symbolPadding,
  4026. itemX,
  4027. itemY,
  4028. lastItemY,
  4029. lastItemHeight = 0,
  4030. box,
  4031. legendBorderWidth = options.borderWidth,
  4032. legendBackgroundColor = options.backgroundColor,
  4033. legendGroup,
  4034. offsetWidth,
  4035. widthOption = options.width,
  4036. series = chart.series,
  4037. reversedLegend = options.reversed;
  4038. function colorizeItem(item, visible) {
  4039. var legendItem = item.legendItem,
  4040. legendLine = item.legendLine,
  4041. legendSymbol = item.legendSymbol,
  4042. hiddenColor = itemHiddenStyle.color,
  4043. textColor = visible ? options.itemStyle.color : hiddenColor,
  4044. symbolColor = visible ? item.color : hiddenColor;
  4045. if (legendItem) {
  4046. legendItem.css({ fill: textColor });
  4047. }
  4048. if (legendLine) {
  4049. legendLine.attr({ stroke: symbolColor });
  4050. }
  4051. if (legendSymbol) {
  4052. legendSymbol.attr({
  4053. stroke: symbolColor,
  4054. fill: symbolColor
  4055. });
  4056. }
  4057. }
  4058. function positionItem(item, itemX, itemY) {
  4059. var legendItem = item.legendItem,
  4060. legendLine = item.legendLine,
  4061. legendSymbol = item.legendSymbol,
  4062. checkbox = item.checkbox;
  4063. if (legendItem) {
  4064. legendItem.attr({
  4065. x: itemX,
  4066. y: itemY
  4067. });
  4068. }
  4069. if (legendLine) {
  4070. legendLine.translate(itemX, itemY - 4);
  4071. }
  4072. if (legendSymbol) {
  4073. legendSymbol.attr({
  4074. x: itemX + legendSymbol.xOff,
  4075. y: itemY + legendSymbol.yOff
  4076. });
  4077. }
  4078. if (checkbox) {
  4079. checkbox.x = itemX;
  4080. checkbox.y = itemY;
  4081. }
  4082. }
  4083. function destroyItem(item) {
  4084. var checkbox = item.checkbox;
  4085. each(['legendItem', 'legendLine', 'legendSymbol'], function(key) {
  4086. if (item[key]) {
  4087. item[key].destroy();
  4088. }
  4089. });
  4090. if (checkbox) {
  4091. discardElement(item.checkbox);
  4092. }
  4093. }
  4094. function positionCheckboxes() {
  4095. each(allItems, function(item) {
  4096. var checkbox = item.checkbox;
  4097. if (checkbox) {
  4098. css(checkbox, {
  4099. left: (legendGroup.attr('translateX') + item.legendItemWidth + checkbox.x - 40) +PX,
  4100. top: (legendGroup.attr('translateY') + checkbox.y - 11) + PX
  4101. });
  4102. }
  4103. });
  4104. }
  4105. function renderItem(item) {
  4106. var bBox,
  4107. itemWidth,
  4108. legendSymbol,
  4109. symbolX,
  4110. symbolY,
  4111. attribs,
  4112. simpleSymbol,
  4113. li = item.legendItem,
  4114. series = item.series || item;
  4115. if (!li) {
  4116. simpleSymbol = /^(bar|pie|area|column)$/.test(series.type);
  4117. item.legendItem = li = renderer.text(
  4118. options.labelFormatter.call(item),
  4119. 0,
  4120. 0
  4121. )
  4122. .css(item.visible ? itemStyle : itemHiddenStyle)
  4123. .on('mouseover', function() {
  4124. item.setState(HOVER_STATE);
  4125. li.css(itemHoverStyle);
  4126. })
  4127. .on('mouseout', function() {
  4128. li.css(item.visible ? itemStyle : itemHiddenStyle);
  4129. item.setState();
  4130. })
  4131. .on('click', function(event) {
  4132. var strLegendItemClick = 'legendItemClick',
  4133. fnLegendItemClick = function() {
  4134. item.setVisible();
  4135. };
  4136. if (item.firePointEvent) {
  4137. item.firePointEvent(strLegendItemClick, null, fnLegendItemClick);
  4138. } else {
  4139. fireEvent(item, strLegendItemClick, null, fnLegendItemClick);
  4140. }
  4141. })
  4142. .attr({ zIndex: 2 })
  4143. .add(legendGroup);
  4144. if (!simpleSymbol && item.options && item.options.lineWidth) {
  4145. var itemOptions = item.options;
  4146. attribs = {
  4147. 'stroke-width': itemOptions.lineWidth,
  4148. zIndex: 2
  4149. };
  4150. if (itemOptions.dashStyle) {
  4151. attribs.dashstyle = itemOptions.dashStyle;
  4152. }
  4153. item.legendLine = renderer.path([
  4154. M,
  4155. -symbolWidth - symbolPadding,
  4156. 0,
  4157. L,
  4158. -symbolPadding,
  4159. 0
  4160. ])
  4161. .attr(attribs)
  4162. .add(legendGroup);
  4163. }
  4164. if (simpleSymbol) {
  4165. legendSymbol = renderer.rect(
  4166. (symbolX = -symbolWidth - symbolPadding),
  4167. (symbolY = -11),
  4168. symbolWidth,
  4169. 12,
  4170. 2
  4171. ).attr({
  4172. 'stroke-width': 0,
  4173. zIndex: 3
  4174. }).add(legendGroup);
  4175. }
  4176. else if (item.options && item.options.marker && item.options.marker.enabled) {
  4177. legendSymbol = renderer.symbol(
  4178. item.symbol,
  4179. (symbolX = -symbolWidth / 2 - symbolPadding),
  4180. (symbolY = -4),
  4181. item.options.marker.radius
  4182. )
  4183. .attr(item.pointAttr[NORMAL_STATE])
  4184. .attr({ zIndex: 3 })
  4185. .add(legendGroup);
  4186. }
  4187. if (legendSymbol) {
  4188. legendSymbol.xOff = symbolX;
  4189. legendSymbol.yOff = symbolY;
  4190. }
  4191. item.legendSymbol = legendSymbol;
  4192. colorizeItem(item, item.visible);
  4193. if (item.options && item.options.showCheckbox) {
  4194. item.checkbox = createElement('input', {
  4195. type: 'checkbox',
  4196. checked: item.selected,
  4197. defaultChecked: item.selected
  4198. }, options.itemCheckboxStyle, container);
  4199. addEvent(item.checkbox, 'click', function(event) {
  4200. var target = event.target;
  4201. fireEvent(item, 'checkboxClick', {
  4202. checked: target.checked
  4203. },
  4204. function() {
  4205. item.select();
  4206. }
  4207. );
  4208. });
  4209. }
  4210. }
  4211. positionItem(item, itemX, itemY);
  4212. bBox = li.getBBox();
  4213. lastItemY = itemY;
  4214. lastItemHeight = bBox.height;
  4215. item.legendItemWidth = itemWidth =
  4216. options.itemWidth || symbolWidth + symbolPadding + bBox.width + rightPadding;
  4217. if (horizontal) {
  4218. itemX += itemWidth;
  4219. offsetWidth = widthOption || mathMax(itemX - initialItemX, offsetWidth);
  4220. if (itemX - initialItemX + itemWidth >
  4221. (widthOption || (chartWidth - 2 * padding - initialItemX))) {
  4222. itemX = initialItemX;
  4223. itemY += lastItemHeight;
  4224. }
  4225. } else {
  4226. itemY += lastItemHeight;
  4227. offsetWidth = widthOption || mathMax(itemWidth, offsetWidth);
  4228. }
  4229. allItems.push(item);
  4230. }
  4231. function renderLegend() {
  4232. itemX = initialItemX;
  4233. itemY = y;
  4234. offsetWidth = 0;
  4235. lastItemY = 0;
  4236. allItems = [];
  4237. if (!legendGroup) {
  4238. legendGroup = renderer.g('legend')
  4239. .attr({ zIndex: 7 })
  4240. .add();
  4241. }
  4242. if (reversedLegend) {
  4243. series.reverse();
  4244. }
  4245. each(series, function(serie) {
  4246. if (!serie.options.showInLegend) {
  4247. return;
  4248. }
  4249. var items = (serie.options.legendType == 'point') ?
  4250. serie.data : [serie];
  4251. each(items, renderItem);
  4252. });
  4253. if (reversedLegend) {
  4254. series.reverse();
  4255. }
  4256. legendWidth = widthOption || offsetWidth;
  4257. legendHeight = lastItemY - y + lastItemHeight;
  4258. if (legendBorderWidth || legendBackgroundColor) {
  4259. legendWidth += 2 * padding;
  4260. legendHeight += 2 * padding;
  4261. if (!box) {
  4262. box = renderer.rect(
  4263. 0,
  4264. 0,
  4265. legendWidth,
  4266. legendHeight,
  4267. options.borderRadius,
  4268. legendBorderWidth || 0
  4269. ).attr({
  4270. stroke: options.borderColor,
  4271. 'stroke-width': legendBorderWidth || 0,
  4272. fill: legendBackgroundColor || NONE
  4273. })
  4274. .add(legendGroup)
  4275. .shadow(options.shadow);
  4276. } else if (legendWidth > 0 && legendHeight > 0) {
  4277. box.animate({
  4278. width: legendWidth,
  4279. height: legendHeight
  4280. });
  4281. }
  4282. box[allItems.length ? 'show' : 'hide']();
  4283. }
  4284. var props = ['left', 'right', 'top', 'bottom'],
  4285. prop,
  4286. i = 4;
  4287. while(i--) {
  4288. prop = props[i];
  4289. if (style[prop] && style[prop] != 'auto') {
  4290. options[i < 2 ? 'align' : 'verticalAlign'] = prop;
  4291. options[i < 2 ? 'x' : 'y'] = pInt(style[prop]) * (i % 2 ? -1 : 1);
  4292. }
  4293. }
  4294. legendGroup.align(extend(options, {
  4295. width: legendWidth,
  4296. height: legendHeight
  4297. }), true, spacingBox);
  4298. if (!isResizing) {
  4299. positionCheckboxes();
  4300. }
  4301. }
  4302. renderLegend();
  4303. addEvent(chart, 'endResize', positionCheckboxes);
  4304. return {
  4305. colorizeItem: colorizeItem,
  4306. destroyItem: destroyItem,
  4307. renderLegend: renderLegend
  4308. };
  4309. };
  4310. function initSeries(options) {
  4311. var type = options.type || optionsChart.type || optionsChart.defaultSeriesType,
  4312. typeClass = seriesTypes[type],
  4313. serie,
  4314. hasRendered = chart.hasRendered;
  4315. if (hasRendered) {
  4316. if (inverted && type == 'column') {
  4317. typeClass = seriesTypes.bar;
  4318. } else if (!inverted && type == 'bar') {
  4319. typeClass = seriesTypes.column;
  4320. }
  4321. }
  4322. serie = new typeClass();
  4323. serie.init(chart, options);
  4324. if (!hasRendered && serie.inverted) {
  4325. inverted = true;
  4326. }
  4327. if (serie.isCartesian) {
  4328. hasCartesianSeries = serie.isCartesian;
  4329. }
  4330. series.push(serie);
  4331. return serie;
  4332. }
  4333. function addSeries(options, redraw, animation) {
  4334. var series;
  4335. if (options) {
  4336. setAnimation(animation, chart);
  4337. redraw = pick(redraw, true);
  4338. fireEvent(chart, 'addSeries', { options: options }, function() {
  4339. series = initSeries(options);
  4340. series.isDirty = true;
  4341. chart.isDirtyLegend = true;
  4342. if (redraw) {
  4343. chart.redraw();
  4344. }
  4345. });
  4346. }
  4347. return series;
  4348. }
  4349. isInsidePlot = function(x, y) {
  4350. return x >= 0 &&
  4351. x <= plotWidth &&
  4352. y >= 0 &&
  4353. y <= plotHeight;
  4354. };
  4355. function adjustTickAmounts() {
  4356. if (optionsChart.alignTicks !== false) {
  4357. each(axes, function(axis) {
  4358. axis.adjustTickAmount();
  4359. });
  4360. }
  4361. maxTicks = null;
  4362. }
  4363. function redraw(animation) {
  4364. var redrawLegend = chart.isDirtyLegend,
  4365. hasStackedSeries,
  4366. isDirtyBox = chart.isDirtyBox,
  4367. seriesLength = series.length,
  4368. i = seriesLength,
  4369. clipRect = chart.clipRect,
  4370. serie;
  4371. setAnimation(animation, chart);
  4372. while (i--) {
  4373. serie = series[i];
  4374. if (serie.isDirty && serie.options.stacking) {
  4375. hasStackedSeries = true;
  4376. break;
  4377. }
  4378. }
  4379. if (hasStackedSeries) {
  4380. i = seriesLength;
  4381. while (i--) {
  4382. serie = series[i];
  4383. if (serie.options.stacking) {
  4384. serie.isDirty = true;
  4385. }
  4386. }
  4387. }
  4388. each(series, function(serie) {
  4389. if (serie.isDirty) {
  4390. serie.cleanData();
  4391. serie.getSegments();
  4392. if (serie.options.legendType == 'point') {
  4393. redrawLegend = true;
  4394. }
  4395. }
  4396. });
  4397. if (redrawLegend && legend.renderLegend) {
  4398. legend.renderLegend();
  4399. chart.isDirtyLegend = false;
  4400. }
  4401. if (hasCartesianSeries) {
  4402. if (!isResizing) {
  4403. maxTicks = null;
  4404. each(axes, function(axis) {
  4405. axis.setScale();
  4406. });
  4407. }
  4408. adjustTickAmounts();
  4409. getMargins();
  4410. each(axes, function(axis) {
  4411. if (axis.isDirty || isDirtyBox) {
  4412. axis.redraw();
  4413. isDirtyBox = true;
  4414. }
  4415. });
  4416. }
  4417. if (isDirtyBox) {
  4418. drawChartBox();
  4419. placeTrackerGroup();
  4420. if (clipRect) {
  4421. stop(clipRect);
  4422. clipRect.animate({
  4423. width: chart.plotSizeX,
  4424. height: chart.plotSizeY
  4425. });
  4426. }
  4427. }
  4428. each(series, function(serie) {
  4429. if (serie.isDirty && serie.visible) {
  4430. serie.redraw();
  4431. }
  4432. });
  4433. if (tracker && tracker.resetTracker) {
  4434. tracker.resetTracker();
  4435. }
  4436. renderer.draw();
  4437. fireEvent(chart, 'redraw');
  4438. }
  4439. function showLoading(str) {
  4440. var loadingOptions = options.loading;
  4441. if (!loadingDiv) {
  4442. loadingDiv = createElement(DIV, {
  4443. className: 'highcharts-loading'
  4444. }, extend(loadingOptions.style, {
  4445. left: plotLeft + PX,
  4446. top: plotTop + PX,
  4447. width: plotWidth + PX,
  4448. height: plotHeight + PX,
  4449. zIndex: 10,
  4450. display: NONE
  4451. }), container);
  4452. loadingSpan = createElement(
  4453. 'span',
  4454. null,
  4455. loadingOptions.labelStyle,
  4456. loadingDiv
  4457. );
  4458. }
  4459. loadingSpan.innerHTML = str || options.lang.loading;
  4460. if (!loadingShown) {
  4461. css(loadingDiv, { opacity: 0, display: '' });
  4462. animate(loadingDiv, {
  4463. opacity: loadingOptions.style.opacity
  4464. }, {
  4465. duration: loadingOptions.showDuration
  4466. });
  4467. loadingShown = true;
  4468. }
  4469. }
  4470. function hideLoading() {
  4471. animate(loadingDiv, {
  4472. opacity: 0
  4473. }, {
  4474. duration: options.loading.hideDuration,
  4475. complete: function() {
  4476. css(loadingDiv, { display: NONE });
  4477. }
  4478. });
  4479. loadingShown = false;
  4480. }
  4481. function get(id) {
  4482. var i,
  4483. j,
  4484. data;
  4485. for (i = 0; i < axes.length; i++) {
  4486. if (axes[i].options.id == id) {
  4487. return axes[i];
  4488. }
  4489. }
  4490. for (i = 0; i < series.length; i++) {
  4491. if (series[i].options.id == id) {
  4492. return series[i];
  4493. }
  4494. }
  4495. for (i = 0; i < series.length; i++) {
  4496. data = series[i].data;
  4497. for (j = 0; j < data.length; j++) {
  4498. if (data[j].id == id) {
  4499. return data[j];
  4500. }
  4501. }
  4502. }
  4503. return null;
  4504. }
  4505. function getAxes() {
  4506. var xAxisOptions = options.xAxis || {},
  4507. yAxisOptions = options.yAxis || {},
  4508. axis;
  4509. xAxisOptions = splat(xAxisOptions);
  4510. each(xAxisOptions, function(axis, i) {
  4511. axis.index = i;
  4512. axis.isX = true;
  4513. });
  4514. yAxisOptions = splat(yAxisOptions);
  4515. each(yAxisOptions, function(axis, i) {
  4516. axis.index = i;
  4517. });
  4518. axes = xAxisOptions.concat(yAxisOptions);
  4519. chart.xAxis = [];
  4520. chart.yAxis = [];
  4521. axes = map(axes, function(axisOptions) {
  4522. axis = new Axis(chart, axisOptions);
  4523. chart[axis.isXAxis ? 'xAxis' : 'yAxis'].push(axis);
  4524. return axis;
  4525. });
  4526. adjustTickAmounts();
  4527. }
  4528. function getSelectedPoints() {
  4529. var points = [];
  4530. each(series, function(serie) {
  4531. points = points.concat( grep( serie.data, function(point) {
  4532. return point.selected;
  4533. }));
  4534. });
  4535. return points;
  4536. }
  4537. function getSelectedSeries() {
  4538. return grep(series, function (serie) {
  4539. return serie.selected;
  4540. });
  4541. }
  4542. zoomOut = function () {
  4543. fireEvent(chart, 'selection', { resetSelection: true }, zoom);
  4544. chart.toolbar.remove('zoom');
  4545. };
  4546. zoom = function (event) {
  4547. var lang = defaultOptions.lang,
  4548. animate = chart.pointCount < 100;
  4549. chart.toolbar.add('zoom', lang.resetZoom, lang.resetZoomTitle, zoomOut);
  4550. if (!event || event.resetSelection) {
  4551. each(axes, function(axis) {
  4552. axis.setExtremes(null, null, false, animate);
  4553. });
  4554. }
  4555. else {
  4556. each(event.xAxis.concat(event.yAxis), function(axisData) {
  4557. var axis = axisData.axis;
  4558. if (chart.tracker[axis.isXAxis ? 'zoomX' : 'zoomY']) {
  4559. axis.setExtremes(axisData.min, axisData.max, false, animate);
  4560. }
  4561. });
  4562. }
  4563. redraw();
  4564. };
  4565. function setTitle (titleOptions, subtitleOptions) {
  4566. chartTitleOptions = merge(options.title, titleOptions);
  4567. chartSubtitleOptions = merge(options.subtitle, subtitleOptions);
  4568. each([
  4569. ['title', titleOptions, chartTitleOptions],
  4570. ['subtitle', subtitleOptions, chartSubtitleOptions]
  4571. ], function(arr) {
  4572. var name = arr[0],
  4573. title = chart[name],
  4574. titleOptions = arr[1],
  4575. chartTitleOptions = arr[2];
  4576. if (title && titleOptions) {
  4577. title.destroy();
  4578. title = null;
  4579. }
  4580. if (chartTitleOptions && chartTitleOptions.text && !title) {
  4581. chart[name] = renderer.text(
  4582. chartTitleOptions.text,
  4583. 0,
  4584. 0
  4585. )
  4586. .attr({
  4587. align: chartTitleOptions.align,
  4588. 'class': 'highcharts-'+ name,
  4589. zIndex: 1
  4590. })
  4591. .css(chartTitleOptions.style)
  4592. .add()
  4593. .align(chartTitleOptions, false, spacingBox);
  4594. }
  4595. });
  4596. }
  4597. function getChartSize() {
  4598. containerWidth = (renderToClone || renderTo).offsetWidth;
  4599. containerHeight = (renderToClone || renderTo).offsetHeight;
  4600. chart.chartWidth = chartWidth = optionsChart.width || containerWidth || 600;
  4601. chart.chartHeight = chartHeight = optionsChart.height ||
  4602. (containerHeight > 19 ? containerHeight : 400);
  4603. }
  4604. function getContainer() {
  4605. renderTo = optionsChart.renderTo;
  4606. containerId = PREFIX + idCounter++;
  4607. if (isString(renderTo)) {
  4608. renderTo = doc.getElementById(renderTo);
  4609. }
  4610. renderTo.innerHTML = '';
  4611. if (!renderTo.offsetWidth) {
  4612. renderToClone = renderTo.cloneNode(0);
  4613. css(renderToClone, {
  4614. position: ABSOLUTE,
  4615. top: '-9999px',
  4616. display: ''
  4617. });
  4618. doc.body.appendChild(renderToClone);
  4619. }
  4620. getChartSize();
  4621. chart.container = container = createElement(DIV, {
  4622. className: 'highcharts-container' +
  4623. (optionsChart.className ? ' '+ optionsChart.className : ''),
  4624. id: containerId
  4625. }, extend({
  4626. position: RELATIVE,
  4627. overflow: HIDDEN,
  4628. width: chartWidth + PX,
  4629. height: chartHeight + PX,
  4630. textAlign: 'left'
  4631. }, optionsChart.style),
  4632. renderToClone || renderTo
  4633. );
  4634. chart.renderer = renderer =
  4635. optionsChart.renderer == 'SVG' ?
  4636. new SVGRenderer(container, chartWidth, chartHeight) :
  4637. new Renderer(container, chartWidth, chartHeight);
  4638. var subPixelFix;
  4639. if (/Gecko/.test(userAgent)) {
  4640. subPixelFix = function() {
  4641. css(container, { left: 0, top: 0 });
  4642. var rect = container.getBoundingClientRect();
  4643. css(container, {
  4644. left: (-rect.left % 1) + PX,
  4645. top: (-rect.top % 1) + PX
  4646. });
  4647. };
  4648. subPixelFix();
  4649. addEvent(win, 'resize', subPixelFix);
  4650. addEvent(chart, 'destroy', function() {
  4651. removeEvent(win, 'resize', subPixelFix);
  4652. });
  4653. }
  4654. }
  4655. getMargins = function() {
  4656. var legendOptions = options.legend,
  4657. legendMargin = pick(legendOptions.margin, 10),
  4658. legendX = legendOptions.x,
  4659. legendY = legendOptions.y,
  4660. align = legendOptions.align,
  4661. verticalAlign = legendOptions.verticalAlign,
  4662. titleOffset;
  4663. resetMargins();
  4664. if ((chart.title || chart.subtitle) && !defined(optionsMarginTop)) {
  4665. titleOffset = mathMax(
  4666. chart.title && !chartTitleOptions.floating && !chartTitleOptions.verticalAlign && chartTitleOptions.y || 0,
  4667. chart.subtitle && !chartSubtitleOptions.floating && !chartSubtitleOptions.verticalAlign && chartSubtitleOptions.y || 0
  4668. );
  4669. if (titleOffset) {
  4670. plotTop = mathMax(plotTop, titleOffset + pick(chartTitleOptions.margin, 15) + spacingTop);
  4671. }
  4672. }
  4673. if (legendOptions.enabled && !legendOptions.floating) {
  4674. if (align == 'right') {
  4675. if (!defined(optionsMarginRight)) {
  4676. marginRight = mathMax(
  4677. marginRight,
  4678. legendWidth - legendX + legendMargin + spacingRight
  4679. );
  4680. }
  4681. } else if (align == 'left') {
  4682. if (!defined(optionsMarginLeft)) {
  4683. plotLeft = mathMax(
  4684. plotLeft,
  4685. legendWidth + legendX + legendMargin + spacingLeft
  4686. );
  4687. }
  4688. } else if (verticalAlign == 'top') {
  4689. if (!defined(optionsMarginTop)) {
  4690. plotTop = mathMax(
  4691. plotTop,
  4692. legendHeight + legendY + legendMargin + spacingTop
  4693. );
  4694. }
  4695. } else if (verticalAlign == 'bottom') {
  4696. if (!defined(optionsMarginBottom)) {
  4697. marginBottom = mathMax(
  4698. marginBottom,
  4699. legendHeight - legendY + legendMargin + spacingBottom
  4700. );
  4701. }
  4702. }
  4703. }
  4704. if (hasCartesianSeries) {
  4705. each(axes, function(axis) {
  4706. axis.getOffset();
  4707. });
  4708. }
  4709. if (!defined(optionsMarginLeft)) {
  4710. plotLeft += axisOffset[3];
  4711. }
  4712. if (!defined(optionsMarginTop)) {
  4713. plotTop += axisOffset[0];
  4714. }
  4715. if (!defined(optionsMarginBottom)) {
  4716. marginBottom += axisOffset[2];
  4717. }
  4718. if (!defined(optionsMarginRight)) {
  4719. marginRight += axisOffset[1];
  4720. }
  4721. setChartSize();
  4722. };
  4723. function initReflow() {
  4724. var reflowTimeout;
  4725. function reflow() {
  4726. var width = optionsChart.width || renderTo.offsetWidth,
  4727. height = optionsChart.height || renderTo.offsetHeight;
  4728. if (width && height) {
  4729. if (width != containerWidth || height != containerHeight) {
  4730. clearTimeout(reflowTimeout);
  4731. reflowTimeout = setTimeout(function() {
  4732. resize(width, height, false);
  4733. }, 100);
  4734. }
  4735. containerWidth = width;
  4736. containerHeight = height;
  4737. }
  4738. }
  4739. addEvent(window, 'resize', reflow);
  4740. addEvent(chart, 'destroy', function() {
  4741. removeEvent(window, 'resize', reflow);
  4742. });
  4743. }
  4744. resize = function(width, height, animation) {
  4745. var chartTitle = chart.title,
  4746. chartSubtitle = chart.subtitle;
  4747. isResizing += 1;
  4748. setAnimation(animation, chart);
  4749. oldChartHeight = chartHeight;
  4750. oldChartWidth = chartWidth;
  4751. chartWidth = mathRound(width);
  4752. chartHeight = mathRound(height);
  4753. css(container, {
  4754. width: chartWidth + PX,
  4755. height: chartHeight + PX
  4756. });
  4757. renderer.setSize(chartWidth, chartHeight);
  4758. plotWidth = chartWidth - plotLeft - marginRight;
  4759. plotHeight = chartHeight - plotTop - marginBottom;
  4760. maxTicks = null;
  4761. each(axes, function(axis) {
  4762. axis.isDirty = true;
  4763. axis.setScale();
  4764. });
  4765. each(series, function(serie) {
  4766. serie.isDirty = true;
  4767. });
  4768. chart.isDirtyLegend = true;
  4769. chart.isDirtyBox = true;
  4770. getMargins();
  4771. if (chartTitle) {
  4772. chartTitle.align(null, null, spacingBox);
  4773. }
  4774. if (chartSubtitle) {
  4775. chartSubtitle.align(null, null, spacingBox);
  4776. }
  4777. redraw();
  4778. oldChartHeight = null;
  4779. fireEvent(chart, 'resize');
  4780. setTimeout(function() {
  4781. fireEvent(chart, 'endResize', null, function() {
  4782. isResizing -= 1;
  4783. });
  4784. }, globalAnimation && globalAnimation.duration || 500);
  4785. };
  4786. setChartSize = function() {
  4787. chart.plotLeft = plotLeft = mathRound(plotLeft);
  4788. chart.plotTop = plotTop = mathRound(plotTop);
  4789. chart.plotWidth = plotWidth = mathRound(chartWidth - plotLeft - marginRight);
  4790. chart.plotHeight = plotHeight = mathRound(chartHeight - plotTop - marginBottom);
  4791. chart.plotSizeX = inverted ? plotHeight : plotWidth;
  4792. chart.plotSizeY = inverted ? plotWidth : plotHeight;
  4793. spacingBox = {
  4794. x: spacingLeft,
  4795. y: spacingTop,
  4796. width: chartWidth - spacingLeft - spacingRight,
  4797. height: chartHeight - spacingTop - spacingBottom
  4798. };
  4799. };
  4800. resetMargins = function() {
  4801. plotTop = pick(optionsMarginTop, spacingTop);
  4802. marginRight = pick(optionsMarginRight, spacingRight);
  4803. marginBottom = pick(optionsMarginBottom, spacingBottom);
  4804. plotLeft = pick(optionsMarginLeft, spacingLeft);
  4805. axisOffset = [0, 0, 0, 0];
  4806. };
  4807. drawChartBox = function() {
  4808. var chartBorderWidth = optionsChart.borderWidth || 0,
  4809. chartBackgroundColor = optionsChart.backgroundColor,
  4810. plotBackgroundColor = optionsChart.plotBackgroundColor,
  4811. plotBackgroundImage = optionsChart.plotBackgroundImage,
  4812. mgn,
  4813. plotSize = {
  4814. x: plotLeft,
  4815. y: plotTop,
  4816. width: plotWidth,
  4817. height: plotHeight
  4818. };
  4819. mgn = 2 * chartBorderWidth + (optionsChart.shadow ? 8 : 0);
  4820. if (chartBorderWidth || chartBackgroundColor) {
  4821. if (!chartBackground) {
  4822. chartBackground = renderer.rect(mgn / 2, mgn / 2, chartWidth - mgn, chartHeight - mgn,
  4823. optionsChart.borderRadius, chartBorderWidth)
  4824. .attr({
  4825. stroke: optionsChart.borderColor,
  4826. 'stroke-width': chartBorderWidth,
  4827. fill: chartBackgroundColor || NONE
  4828. })
  4829. .add()
  4830. .shadow(optionsChart.shadow);
  4831. } else {
  4832. chartBackground.animate({
  4833. width: chartWidth - mgn,
  4834. height:chartHeight - mgn
  4835. });
  4836. }
  4837. }
  4838. if (plotBackgroundColor) {
  4839. if (!plotBackground) {
  4840. plotBackground = renderer.rect(plotLeft, plotTop, plotWidth, plotHeight, 0)
  4841. .attr({
  4842. fill: plotBackgroundColor
  4843. })
  4844. .add()
  4845. .shadow(optionsChart.plotShadow);
  4846. } else {
  4847. plotBackground.animate(plotSize);
  4848. }
  4849. }
  4850. if (plotBackgroundImage) {
  4851. if (!plotBGImage) {
  4852. plotBGImage = renderer.image(plotBackgroundImage, plotLeft, plotTop, plotWidth, plotHeight)
  4853. .add();
  4854. } else {
  4855. plotBGImage.animate(plotSize);
  4856. }
  4857. }
  4858. if (optionsChart.plotBorderWidth) {
  4859. if (!plotBorder) {
  4860. plotBorder = renderer.rect(plotLeft, plotTop, plotWidth, plotHeight, 0, optionsChart.plotBorderWidth)
  4861. .attr({
  4862. stroke: optionsChart.plotBorderColor,
  4863. 'stroke-width': optionsChart.plotBorderWidth,
  4864. zIndex: 4
  4865. })
  4866. .add();
  4867. } else {
  4868. plotBorder.animate(plotSize);
  4869. }
  4870. }
  4871. chart.isDirtyBox = false;
  4872. };
  4873. function render () {
  4874. var labels = options.labels,
  4875. credits = options.credits,
  4876. creditsHref;
  4877. setTitle();
  4878. legend = chart.legend = new Legend(chart);
  4879. getMargins();
  4880. each(axes, function(axis) {
  4881. axis.setTickPositions(true);
  4882. });
  4883. adjustTickAmounts();
  4884. getMargins();
  4885. drawChartBox();
  4886. if (hasCartesianSeries) {
  4887. each(axes, function(axis) {
  4888. axis.render();
  4889. });
  4890. }
  4891. if (!chart.seriesGroup) {
  4892. chart.seriesGroup = renderer.g('series-group')
  4893. .attr({ zIndex: 3 })
  4894. .add();
  4895. }
  4896. each(series, function(serie) {
  4897. serie.translate();
  4898. serie.setTooltipPoints();
  4899. serie.render();
  4900. });
  4901. if (labels.items) {
  4902. each(labels.items, function() {
  4903. var style = extend(labels.style, this.style),
  4904. x = pInt(style.left) + plotLeft,
  4905. y = pInt(style.top) + plotTop + 12;
  4906. delete style.left;
  4907. delete style.top;
  4908. renderer.text(
  4909. this.html,
  4910. x,
  4911. y
  4912. )
  4913. .attr({ zIndex: 2 })
  4914. .css(style)
  4915. .add();
  4916. });
  4917. }
  4918. if (!chart.toolbar) {
  4919. chart.toolbar = Toolbar(chart);
  4920. }
  4921. if (credits.enabled && !chart.credits) {
  4922. creditsHref = credits.href;
  4923. renderer.text(
  4924. credits.text,
  4925. 0,
  4926. 0
  4927. )
  4928. .on('click', function() {
  4929. if (creditsHref) {
  4930. location.href = creditsHref;
  4931. }
  4932. })
  4933. .attr({
  4934. align: credits.position.align,
  4935. zIndex: 8
  4936. })
  4937. .css(credits.style)
  4938. .add()
  4939. .align(credits.position);
  4940. }
  4941. placeTrackerGroup();
  4942. chart.hasRendered = true;
  4943. if (renderToClone) {
  4944. renderTo.appendChild(container);
  4945. discardElement(renderToClone);
  4946. }
  4947. }
  4948. function destroy() {
  4949. var i = series.length,
  4950. parentNode = container.parentNode;
  4951. fireEvent(chart, 'destroy');
  4952. removeEvent(win, 'unload', destroy);
  4953. removeEvent(chart);
  4954. each(axes, function(axis) {
  4955. removeEvent(axis);
  4956. });
  4957. while (i--) {
  4958. series[i].destroy();
  4959. }
  4960. container.innerHTML = '';
  4961. removeEvent(container);
  4962. if (parentNode) {
  4963. parentNode.removeChild(container);
  4964. }
  4965. container = null;
  4966. renderer.alignedObjects = null;
  4967. clearInterval(tooltipInterval);
  4968. for (i in chart) {
  4969. delete chart[i];
  4970. }
  4971. }
  4972. function firstRender() {
  4973. var onreadystatechange = 'onreadystatechange';
  4974. if (!hasSVG && !useCanVG && doc.readyState != 'complete') {
  4975. doc.attachEvent(onreadystatechange, function() {
  4976. doc.detachEvent(onreadystatechange, firstRender);
  4977. firstRender();
  4978. });
  4979. return;
  4980. }
  4981. getContainer();
  4982. resetMargins();
  4983. setChartSize();
  4984. each(options.series || [], function(serieOptions) {
  4985. initSeries(serieOptions);
  4986. });
  4987. chart.inverted = inverted = pick(inverted, options.chart.inverted);
  4988. getAxes();
  4989. chart.render = render;
  4990. chart.tracker = tracker = new MouseTracker(chart, options.tooltip);
  4991. render();
  4992. renderer.draw();
  4993. fireEvent(chart, 'load');
  4994. if (callback) {
  4995. callback.apply(chart, [chart]);
  4996. }
  4997. each(chart.callbacks, function(fn) {
  4998. fn.apply(chart, [chart]);
  4999. });
  5000. }
  5001. colorCounter = 0;
  5002. symbolCounter = 0;
  5003. addEvent(win, 'unload', destroy);
  5004. if (optionsChart.reflow !== false) {
  5005. addEvent(chart, 'load', initReflow);
  5006. }
  5007. if (chartEvents) {
  5008. for (eventType in chartEvents) {
  5009. addEvent(chart, eventType, chartEvents[eventType]);
  5010. }
  5011. }
  5012. chart.options = options;
  5013. chart.series = series;
  5014. chart.addSeries = addSeries;
  5015. chart.animation = useCanVG ? false : pick(optionsChart.animation, true);
  5016. chart.destroy = destroy;
  5017. chart.get = get;
  5018. chart.getSelectedPoints = getSelectedPoints;
  5019. chart.getSelectedSeries = getSelectedSeries;
  5020. chart.hideLoading = hideLoading;
  5021. chart.isInsidePlot = isInsidePlot;
  5022. chart.redraw = redraw;
  5023. chart.setSize = resize;
  5024. chart.setTitle = setTitle;
  5025. chart.showLoading = showLoading;
  5026. chart.pointCount = 0;
  5027. firstRender();
  5028. }
  5029. Chart.prototype.callbacks = [];
  5030. var Point = function() {};
  5031. Point.prototype = {
  5032. init: function(series, options) {
  5033. var point = this,
  5034. defaultColors;
  5035. point.series = series;
  5036. point.applyOptions(options);
  5037. point.pointAttr = {};
  5038. if (series.options.colorByPoint) {
  5039. defaultColors = series.chart.options.colors;
  5040. if (!point.options) {
  5041. point.options = {};
  5042. }
  5043. point.color = point.options.color = point.color || defaultColors[colorCounter++];
  5044. if (colorCounter >= defaultColors.length) {
  5045. colorCounter = 0;
  5046. }
  5047. }
  5048. series.chart.pointCount++;
  5049. return point;
  5050. },
  5051. applyOptions: function(options) {
  5052. var point = this,
  5053. series = point.series;
  5054. point.config = options;
  5055. if (isNumber(options) || options === null) {
  5056. point.y = options;
  5057. }
  5058. else if (isObject(options) && !isNumber(options.length)) {
  5059. extend(point, options);
  5060. point.options = options;
  5061. }
  5062. else if (isString(options[0])) {
  5063. point.name = options[0];
  5064. point.y = options[1];
  5065. }
  5066. else if (isNumber(options[0])) {
  5067. point.x = options[0];
  5068. point.y = options[1];
  5069. }
  5070. if (point.x === UNDEFINED) {
  5071. point.x = series.autoIncrement();
  5072. }
  5073. },
  5074. destroy: function() {
  5075. var point = this,
  5076. series = point.series,
  5077. prop;
  5078. series.chart.pointCount--;
  5079. if (point == series.chart.hoverPoint) {
  5080. point.onMouseOut();
  5081. }
  5082. series.chart.hoverPoints = null;
  5083. removeEvent(point);
  5084. each(['graphic', 'tracker', 'group', 'dataLabel', 'connector'], function(prop) {
  5085. if (point[prop]) {
  5086. point[prop].destroy();
  5087. }
  5088. });
  5089. if (point.legendItem) {
  5090. point.series.chart.legend.destroyItem(point);
  5091. }
  5092. for (prop in point) {
  5093. point[prop] = null;
  5094. }
  5095. },
  5096. select: function(selected, accumulate) {
  5097. var point = this,
  5098. series = point.series,
  5099. chart = series.chart;
  5100. point.selected = selected = pick(selected, !point.selected);
  5101. point.firePointEvent(selected ? 'select' : 'unselect');
  5102. point.setState(selected && SELECT_STATE);
  5103. if (!accumulate) {
  5104. each(chart.getSelectedPoints(), function (loopPoint) {
  5105. if (loopPoint.selected && loopPoint != point) {
  5106. loopPoint.selected = false;
  5107. loopPoint.setState(NORMAL_STATE);
  5108. loopPoint.firePointEvent('unselect');
  5109. }
  5110. });
  5111. }
  5112. },
  5113. onMouseOver: function() {
  5114. var point = this,
  5115. chart = point.series.chart,
  5116. tooltip = chart.tooltip,
  5117. hoverPoint = chart.hoverPoint;
  5118. if (hoverPoint && hoverPoint != point) {
  5119. hoverPoint.onMouseOut();
  5120. }
  5121. point.firePointEvent('mouseOver');
  5122. if (tooltip && !tooltip.shared) {
  5123. tooltip.refresh(point);
  5124. }
  5125. point.setState(HOVER_STATE);
  5126. chart.hoverPoint = point;
  5127. },
  5128. onMouseOut: function() {
  5129. var point = this;
  5130. point.firePointEvent('mouseOut');
  5131. point.setState();
  5132. point.series.chart.hoverPoint = null;
  5133. },
  5134. update: function(options, redraw, animation) {
  5135. var point = this,
  5136. series = point.series,
  5137. chart = series.chart;
  5138. setAnimation(animation, chart);
  5139. redraw = pick(redraw, true);
  5140. point.firePointEvent('update', { options: options }, function() {
  5141. point.applyOptions(options);
  5142. series.isDirty = true;
  5143. if (redraw) {
  5144. chart.redraw();
  5145. }
  5146. });
  5147. },
  5148. remove: function(redraw, animation) {
  5149. var point = this,
  5150. series = point.series,
  5151. chart = series.chart,
  5152. data = series.data;
  5153. setAnimation(animation, chart);
  5154. redraw = pick(redraw, true);
  5155. point.firePointEvent('remove', null, function() {
  5156. erase(data, point);
  5157. point.destroy();
  5158. series.isDirty = true;
  5159. if (redraw) {
  5160. chart.redraw();
  5161. }
  5162. });
  5163. },
  5164. firePointEvent: function(eventType, eventArgs, defaultFunction) {
  5165. var point = this,
  5166. series = this.series,
  5167. seriesOptions = series.options;
  5168. if (seriesOptions.point.events[eventType] || (
  5169. point.options && point.options.events && point.options.events[eventType])) {
  5170. this.importEvents();
  5171. }
  5172. if (eventType == 'click' && seriesOptions.allowPointSelect) {
  5173. defaultFunction = function (event) {
  5174. point.select(null, event.ctrlKey || event.metaKey || event.shiftKey);
  5175. };
  5176. }
  5177. fireEvent(this, eventType, eventArgs, defaultFunction);
  5178. },
  5179. importEvents: function() {
  5180. if (!this.hasImportedEvents) {
  5181. var point = this,
  5182. options = merge(point.series.options.point, point.options),
  5183. events = options.events,
  5184. eventType;
  5185. point.events = events;
  5186. for (eventType in events) {
  5187. addEvent(point, eventType, events[eventType]);
  5188. }
  5189. this.hasImportedEvents = true;
  5190. }
  5191. },
  5192. setState: function(state) {
  5193. var point = this,
  5194. series = point.series,
  5195. stateOptions = series.options.states,
  5196. markerOptions = defaultPlotOptions[series.type].marker && series.options.marker,
  5197. normalDisabled = markerOptions && !markerOptions.enabled,
  5198. markerStateOptions = markerOptions && markerOptions.states[state],
  5199. stateDisabled = markerStateOptions && markerStateOptions.enabled === false,
  5200. stateMarkerGraphic = series.stateMarkerGraphic,
  5201. chart = series.chart,
  5202. pointAttr = point.pointAttr;
  5203. if (!state) {
  5204. state = NORMAL_STATE;
  5205. }
  5206. if (
  5207. state == point.state ||
  5208. (point.selected && state != SELECT_STATE) ||
  5209. (stateOptions[state] && stateOptions[state].enabled === false) ||
  5210. (state && (stateDisabled || normalDisabled && !markerStateOptions.enabled))
  5211. ) {
  5212. return;
  5213. }
  5214. if (point.graphic) {
  5215. point.graphic.attr(pointAttr[state]);
  5216. }
  5217. else {
  5218. if (state) {
  5219. if (!stateMarkerGraphic) {
  5220. series.stateMarkerGraphic = stateMarkerGraphic = chart.renderer.circle(
  5221. 0, 0, pointAttr[state].r
  5222. )
  5223. .attr(pointAttr[state])
  5224. .add(series.group);
  5225. }
  5226. stateMarkerGraphic.translate(
  5227. point.plotX,
  5228. point.plotY
  5229. );
  5230. }
  5231. if (stateMarkerGraphic) {
  5232. stateMarkerGraphic[state ? 'show' : 'hide']();
  5233. }
  5234. }
  5235. point.state = state;
  5236. }
  5237. };
  5238. var Series = function() {};
  5239. Series.prototype = {
  5240. isCartesian: true,
  5241. type: 'line',
  5242. pointClass: Point,
  5243. pointAttrToOptions: {
  5244. stroke: 'lineColor',
  5245. 'stroke-width': 'lineWidth',
  5246. fill: 'fillColor',
  5247. r: 'radius'
  5248. },
  5249. init: function(chart, options) {
  5250. var series = this,
  5251. eventType,
  5252. events,
  5253. index = chart.series.length;
  5254. series.chart = chart;
  5255. options = series.setOptions(options);
  5256. extend(series, {
  5257. index: index,
  5258. options: options,
  5259. name: options.name || 'Series '+ (index + 1),
  5260. state: NORMAL_STATE,
  5261. pointAttr: {},
  5262. visible: options.visible !== false,
  5263. selected: options.selected === true
  5264. });
  5265. if (useCanVG) {
  5266. options.animation = false;
  5267. }
  5268. events = options.events;
  5269. for (eventType in events) {
  5270. addEvent(series, eventType, events[eventType]);
  5271. }
  5272. if (
  5273. (events && events.click) ||
  5274. (options.point && options.point.events && options.point.events.click) ||
  5275. options.allowPointSelect
  5276. ) {
  5277. chart.runTrackerClick = true;
  5278. }
  5279. series.getColor();
  5280. series.getSymbol();
  5281. series.setData(options.data, false);
  5282. },
  5283. autoIncrement: function() {
  5284. var series = this,
  5285. options = series.options,
  5286. xIncrement = series.xIncrement;
  5287. xIncrement = pick(xIncrement, options.pointStart, 0);
  5288. series.pointInterval = pick(series.pointInterval, options.pointInterval, 1);
  5289. series.xIncrement = xIncrement + series.pointInterval;
  5290. return xIncrement;
  5291. },
  5292. cleanData: function() {
  5293. var series = this,
  5294. chart = series.chart,
  5295. data = series.data,
  5296. closestPoints,
  5297. smallestInterval,
  5298. chartSmallestInterval = chart.smallestInterval,
  5299. interval,
  5300. i;
  5301. data.sort(function(a, b){
  5302. return (a.x - b.x);
  5303. });
  5304. for (i = data.length - 1; i >= 0; i--) {
  5305. if (data[i - 1]) {
  5306. if (data[i - 1].x == data[i].x) {
  5307. data.splice(i - 1, 1);
  5308. }
  5309. }
  5310. }
  5311. for (i = data.length - 1; i >= 0; i--) {
  5312. if (data[i - 1]) {
  5313. interval = data[i].x - data[i - 1].x;
  5314. if (smallestInterval === UNDEFINED || interval < smallestInterval) {
  5315. smallestInterval = interval;
  5316. closestPoints = i;
  5317. }
  5318. }
  5319. }
  5320. if (chartSmallestInterval === UNDEFINED || smallestInterval < chartSmallestInterval) {
  5321. chart.smallestInterval = smallestInterval;
  5322. }
  5323. series.closestPoints = closestPoints;
  5324. },
  5325. getSegments: function() {
  5326. var lastNull = -1,
  5327. segments = [],
  5328. data = this.data;
  5329. each(data, function(point, i) {
  5330. if (point.y === null) {
  5331. if (i > lastNull + 1) {
  5332. segments.push(data.slice(lastNull + 1, i));
  5333. }
  5334. lastNull = i;
  5335. } else if (i == data.length - 1) {
  5336. segments.push(data.slice(lastNull + 1, i + 1));
  5337. }
  5338. });
  5339. this.segments = segments;
  5340. },
  5341. setOptions: function(itemOptions) {
  5342. var plotOptions = this.chart.options.plotOptions,
  5343. options = merge(
  5344. plotOptions[this.type],
  5345. plotOptions.series,
  5346. itemOptions
  5347. );
  5348. return options;
  5349. },
  5350. getColor: function(){
  5351. var defaultColors = this.chart.options.colors;
  5352. this.color = this.options.color || defaultColors[colorCounter++] || '#0000ff';
  5353. if (colorCounter >= defaultColors.length) {
  5354. colorCounter = 0;
  5355. }
  5356. },
  5357. getSymbol: function(){
  5358. var defaultSymbols = this.chart.options.symbols,
  5359. symbol = this.options.marker.symbol || defaultSymbols[symbolCounter++];
  5360. this.symbol = symbol;
  5361. if (symbolCounter >= defaultSymbols.length) {
  5362. symbolCounter = 0;
  5363. }
  5364. },
  5365. addPoint: function(options, redraw, shift, animation) {
  5366. var series = this,
  5367. data = series.data,
  5368. graph = series.graph,
  5369. area = series.area,
  5370. chart = series.chart,
  5371. point = (new series.pointClass()).init(series, options);
  5372. setAnimation(animation, chart);
  5373. if (graph && shift) {
  5374. graph.shift = shift;
  5375. }
  5376. if (area) {
  5377. area.shift = shift;
  5378. area.isArea = true;
  5379. }
  5380. redraw = pick(redraw, true);
  5381. data.push(point);
  5382. if (shift) {
  5383. data[0].remove(false);
  5384. }
  5385. series.isDirty = true;
  5386. if (redraw) {
  5387. chart.redraw();
  5388. }
  5389. },
  5390. setData: function(data, redraw) {
  5391. var series = this,
  5392. oldData = series.data,
  5393. initialColor = series.initialColor,
  5394. chart = series.chart,
  5395. i = oldData && oldData.length || 0;
  5396. series.xIncrement = null;
  5397. if (defined(initialColor)) {
  5398. colorCounter = initialColor;
  5399. }
  5400. data = map(splat(data || []), function(pointOptions) {
  5401. return (new series.pointClass()).init(series, pointOptions);
  5402. });
  5403. while (i--) {
  5404. oldData[i].destroy();
  5405. }
  5406. series.data = data;
  5407. series.cleanData();
  5408. series.getSegments();
  5409. series.isDirty = true;
  5410. chart.isDirtyBox = true;
  5411. if (pick(redraw, true)) {
  5412. chart.redraw(false);
  5413. }
  5414. },
  5415. remove: function(redraw, animation) {
  5416. var series = this,
  5417. chart = series.chart;
  5418. redraw = pick(redraw, true);
  5419. if (!series.isRemoving) {
  5420. series.isRemoving = true;
  5421. fireEvent(series, 'remove', null, function() {
  5422. series.destroy();
  5423. chart.isDirtyLegend = chart.isDirtyBox = true;
  5424. if (redraw) {
  5425. chart.redraw(animation);
  5426. }
  5427. });
  5428. }
  5429. series.isRemoving = false;
  5430. },
  5431. translate: function() {
  5432. var series = this,
  5433. chart = series.chart,
  5434. stacking = series.options.stacking,
  5435. categories = series.xAxis.categories,
  5436. yAxis = series.yAxis,
  5437. data = series.data,
  5438. i = data.length;
  5439. while (i--) {
  5440. var point = data[i],
  5441. xValue = point.x,
  5442. yValue = point.y,
  5443. yBottom,
  5444. stack = yAxis.stacks[(yValue < 0 ? '-' : '') + series.stackKey],
  5445. pointStack,
  5446. pointStackTotal;
  5447. point.plotX = series.xAxis.translate(xValue);
  5448. if (stacking && series.visible && stack[xValue]) {
  5449. pointStack = stack[xValue];
  5450. pointStackTotal = pointStack.total;
  5451. pointStack.cum = yBottom = pointStack.cum - yValue;
  5452. yValue = yBottom + yValue;
  5453. if (stacking == 'percent') {
  5454. yBottom = pointStackTotal ? yBottom * 100 / pointStackTotal : 0;
  5455. yValue = pointStackTotal ? yValue * 100 / pointStackTotal : 0;
  5456. }
  5457. point.percentage = pointStackTotal ? point.y * 100 / pointStackTotal : 0;
  5458. point.stackTotal = pointStackTotal;
  5459. point.yBottom = yAxis.translate(yBottom, 0, 1);
  5460. }
  5461. if (yValue !== null) {
  5462. point.plotY = yAxis.translate(yValue, 0, 1);
  5463. }
  5464. point.clientX = chart.inverted ?
  5465. chart.plotHeight - point.plotX :
  5466. point.plotX;
  5467. point.category = categories && categories[point.x] !== UNDEFINED ?
  5468. categories[point.x] : point.x;
  5469. }
  5470. },
  5471. setTooltipPoints: function (renew) {
  5472. var series = this,
  5473. chart = series.chart,
  5474. inverted = chart.inverted,
  5475. data = [],
  5476. plotSize = mathRound((inverted ? chart.plotTop : chart.plotLeft) + chart.plotSizeX),
  5477. low,
  5478. high,
  5479. tooltipPoints = [];
  5480. if (renew) {
  5481. series.tooltipPoints = null;
  5482. }
  5483. each(series.segments, function(segment){
  5484. data = data.concat(segment);
  5485. });
  5486. if (series.xAxis && series.xAxis.reversed) {
  5487. data = data.reverse();
  5488. }
  5489. each(data, function(point, i) {
  5490. low = data[i - 1] ? data[i - 1].high + 1 : 0;
  5491. high = point.high = data[i + 1] ? (
  5492. mathFloor((point.plotX + (data[i + 1] ?
  5493. data[i + 1].plotX : plotSize)) / 2)) :
  5494. plotSize;
  5495. while (low <= high) {
  5496. tooltipPoints[inverted ? plotSize - low++ : low++] = point;
  5497. }
  5498. });
  5499. series.tooltipPoints = tooltipPoints;
  5500. },
  5501. onMouseOver: function() {
  5502. var series = this,
  5503. chart = series.chart,
  5504. hoverSeries = chart.hoverSeries;
  5505. if (!hasTouch && chart.mouseIsDown) {
  5506. return;
  5507. }
  5508. if (hoverSeries && hoverSeries != series) {
  5509. hoverSeries.onMouseOut();
  5510. }
  5511. if (series.options.events.mouseOver) {
  5512. fireEvent(series, 'mouseOver');
  5513. }
  5514. if (series.tracker) {
  5515. series.tracker.toFront();
  5516. }
  5517. series.setState(HOVER_STATE);
  5518. chart.hoverSeries = series;
  5519. },
  5520. onMouseOut: function() {
  5521. var series = this,
  5522. options = series.options,
  5523. chart = series.chart,
  5524. tooltip = chart.tooltip,
  5525. hoverPoint = chart.hoverPoint;
  5526. if (hoverPoint) {
  5527. hoverPoint.onMouseOut();
  5528. }
  5529. if (series && options.events.mouseOut) {
  5530. fireEvent(series, 'mouseOut');
  5531. }
  5532. if (tooltip && !options.stickyTracking) {
  5533. tooltip.hide();
  5534. }
  5535. series.setState();
  5536. chart.hoverSeries = null;
  5537. },
  5538. animate: function(init) {
  5539. var series = this,
  5540. chart = series.chart,
  5541. clipRect = series.clipRect,
  5542. animation = series.options.animation;
  5543. if (animation && !isObject(animation)) {
  5544. animation = {};
  5545. }
  5546. if (init) {
  5547. if (!clipRect.isAnimating) {
  5548. clipRect.attr( 'width', 0 );
  5549. clipRect.isAnimating = true;
  5550. }
  5551. } else {
  5552. clipRect.animate({
  5553. width: chart.plotSizeX
  5554. }, animation && extend(animation, {
  5555. complete: function() {
  5556. clipRect.isAnimating = false;
  5557. if (clipRect != chart.clipRect) {
  5558. series.group.clip((series.clipRect = chart.clipRect));
  5559. clipRect.destroy();
  5560. }
  5561. }
  5562. }));
  5563. this.animate = null;
  5564. }
  5565. },
  5566. drawPoints: function(){
  5567. var series = this,
  5568. pointAttr,
  5569. data = series.data,
  5570. chart = series.chart,
  5571. plotX,
  5572. plotY,
  5573. i,
  5574. point,
  5575. radius,
  5576. graphic;
  5577. if (series.options.marker.enabled) {
  5578. i = data.length;
  5579. while (i--) {
  5580. point = data[i];
  5581. plotX = point.plotX;
  5582. plotY = point.plotY;
  5583. graphic = point.graphic;
  5584. if (plotY !== UNDEFINED && !isNaN(plotY)) {
  5585. pointAttr = point.pointAttr[point.selected ? SELECT_STATE : NORMAL_STATE];
  5586. radius = pointAttr.r;
  5587. if (graphic) {
  5588. graphic.animate({
  5589. x: plotX,
  5590. y: plotY,
  5591. r: radius
  5592. });
  5593. } else {
  5594. point.graphic = chart.renderer.symbol(
  5595. pick(point.marker && point.marker.symbol, series.symbol),
  5596. plotX,
  5597. plotY,
  5598. radius
  5599. )
  5600. .attr(pointAttr)
  5601. .add(series.group);
  5602. }
  5603. }
  5604. }
  5605. }
  5606. },
  5607. convertAttribs: function(options, base1, base2, base3) {
  5608. var conversion = this.pointAttrToOptions,
  5609. attr,
  5610. option,
  5611. obj = {};
  5612. options = options || {};
  5613. base1 = base1 || {};
  5614. base2 = base2 || {};
  5615. base3 = base3 || {};
  5616. for (attr in conversion) {
  5617. option = conversion[attr];
  5618. obj[attr] = pick(options[option], base1[attr], base2[attr], base3[attr]);
  5619. }
  5620. return obj;
  5621. },
  5622. getAttribs: function() {
  5623. var series = this,
  5624. normalOptions = defaultPlotOptions[series.type].marker ? series.options.marker : series.options,
  5625. stateOptions = normalOptions.states,
  5626. stateOptionsHover = stateOptions[HOVER_STATE],
  5627. pointStateOptionsHover,
  5628. normalDefaults = {},
  5629. seriesColor = series.color,
  5630. data = series.data,
  5631. i,
  5632. point,
  5633. seriesPointAttr = [],
  5634. pointAttr,
  5635. pointAttrToOptions = series.pointAttrToOptions,
  5636. hasPointSpecificOptions;
  5637. if (series.options.marker) {
  5638. normalDefaults = {
  5639. stroke: seriesColor,
  5640. fill: seriesColor
  5641. };
  5642. stateOptionsHover.radius = stateOptionsHover.radius || normalOptions.radius + 2;
  5643. stateOptionsHover.lineWidth = stateOptionsHover.lineWidth || normalOptions.lineWidth + 1;
  5644. } else {
  5645. normalDefaults = {
  5646. fill: seriesColor
  5647. };
  5648. stateOptionsHover.color = stateOptionsHover.color ||
  5649. Color(stateOptionsHover.color || seriesColor)
  5650. .brighten(stateOptionsHover.brightness).get();
  5651. }
  5652. seriesPointAttr[NORMAL_STATE] = series.convertAttribs(normalOptions, normalDefaults);
  5653. each([HOVER_STATE, SELECT_STATE], function(state) {
  5654. seriesPointAttr[state] =
  5655. series.convertAttribs(stateOptions[state], seriesPointAttr[NORMAL_STATE]);
  5656. });
  5657. series.pointAttr = seriesPointAttr;
  5658. i = data.length;
  5659. while (i--) {
  5660. point = data[i];
  5661. normalOptions = (point.options && point.options.marker) || point.options;
  5662. if (normalOptions && normalOptions.enabled === false) {
  5663. normalOptions.radius = 0;
  5664. }
  5665. hasPointSpecificOptions = false;
  5666. if (point.options) {
  5667. for (var key in pointAttrToOptions) {
  5668. if (defined(normalOptions[pointAttrToOptions[key]])) {
  5669. hasPointSpecificOptions = true;
  5670. }
  5671. }
  5672. }
  5673. if (hasPointSpecificOptions) {
  5674. pointAttr = [];
  5675. stateOptions = normalOptions.states || {};
  5676. pointStateOptionsHover = stateOptions[HOVER_STATE] = stateOptions[HOVER_STATE] || {};
  5677. if (!series.options.marker) {
  5678. pointStateOptionsHover.color =
  5679. Color(pointStateOptionsHover.color || point.options.color)
  5680. .brighten(pointStateOptionsHover.brightness ||
  5681. stateOptionsHover.brightness).get();
  5682. }
  5683. pointAttr[NORMAL_STATE] = series.convertAttribs(normalOptions, seriesPointAttr[NORMAL_STATE]);
  5684. pointAttr[HOVER_STATE] = series.convertAttribs(
  5685. stateOptions[HOVER_STATE],
  5686. seriesPointAttr[HOVER_STATE],
  5687. pointAttr[NORMAL_STATE]
  5688. );
  5689. pointAttr[SELECT_STATE] = series.convertAttribs(
  5690. stateOptions[SELECT_STATE],
  5691. seriesPointAttr[SELECT_STATE],
  5692. pointAttr[NORMAL_STATE]
  5693. );
  5694. } else {
  5695. pointAttr = seriesPointAttr;
  5696. }
  5697. point.pointAttr = pointAttr;
  5698. }
  5699. },
  5700. destroy: function() {
  5701. var series = this,
  5702. chart = series.chart,
  5703. clipRect = series.clipRect,
  5704. issue134 = /\/5[0-9\.]+ Safari\
  5705. destroy,
  5706. prop;
  5707. removeEvent(series);
  5708. if (series.legendItem) {
  5709. series.chart.legend.destroyItem(series);
  5710. }
  5711. each(series.data, function(point) {
  5712. point.destroy();
  5713. });
  5714. each(['area', 'graph', 'dataLabelsGroup', 'group', 'tracker'], function(prop) {
  5715. if (series[prop]) {
  5716. destroy = issue134 && prop == 'group' ?
  5717. 'hide' :
  5718. 'destroy';
  5719. series[prop][destroy]();
  5720. }
  5721. });
  5722. if (chart.hoverSeries == series) {
  5723. chart.hoverSeries = null;
  5724. }
  5725. erase(chart.series, series);
  5726. for (prop in series) {
  5727. delete series[prop];
  5728. }
  5729. },
  5730. drawDataLabels: function() {
  5731. if (this.options.dataLabels.enabled) {
  5732. var series = this,
  5733. x,
  5734. y,
  5735. data = series.data,
  5736. options = series.options.dataLabels,
  5737. str,
  5738. dataLabelsGroup = series.dataLabelsGroup,
  5739. chart = series.chart,
  5740. inverted = chart.inverted,
  5741. seriesType = series.type,
  5742. color;
  5743. if (!dataLabelsGroup) {
  5744. dataLabelsGroup = series.dataLabelsGroup =
  5745. chart.renderer.g(PREFIX +'data-labels')
  5746. .attr({
  5747. visibility: series.visible ? VISIBLE : HIDDEN,
  5748. zIndex: 5
  5749. })
  5750. .translate(chart.plotLeft, chart.plotTop)
  5751. .add();
  5752. }
  5753. color = options.color;
  5754. if (color == 'auto') {
  5755. color = null;
  5756. }
  5757. options.style.color = pick(color, series.color);
  5758. each(data, function(point, i){
  5759. var plotX = pick(point.barX, point.plotX, -999),
  5760. plotY = pick(point.plotY, -999),
  5761. dataLabel = point.dataLabel,
  5762. align = options.align;
  5763. str = options.formatter.call({
  5764. x: point.x,
  5765. y: point.y,
  5766. series: series,
  5767. point: point,
  5768. percentage: point.percentage,
  5769. total: point.total || point.stackTotal
  5770. });
  5771. x = (inverted ? chart.plotWidth - plotY : plotX) + options.x;
  5772. y = (inverted ? chart.plotHeight - plotX : plotY) + options.y;
  5773. if (seriesType == 'column') {
  5774. x += {
  5775. center: point.barW / 2,
  5776. right: point.barW
  5777. }[align] || 0;
  5778. }
  5779. if (dataLabel) {
  5780. dataLabel.animate({
  5781. x: x,
  5782. y: y
  5783. });
  5784. } else if (str) {
  5785. point.dataLabel = chart.renderer.text(
  5786. str,
  5787. x,
  5788. y
  5789. )
  5790. .attr({
  5791. align: align,
  5792. rotation: options.rotation,
  5793. zIndex: 1
  5794. })
  5795. .css(options.style)
  5796. .add(dataLabelsGroup);
  5797. }
  5798. });
  5799. }
  5800. },
  5801. drawGraph: function(state) {
  5802. var series = this,
  5803. options = series.options,
  5804. chart = series.chart,
  5805. graph = series.graph,
  5806. graphPath = [],
  5807. fillColor,
  5808. area = series.area,
  5809. group = series.group,
  5810. color = options.lineColor || series.color,
  5811. lineWidth = options.lineWidth,
  5812. dashStyle = options.dashStyle,
  5813. segmentPath,
  5814. renderer = chart.renderer,
  5815. translatedThreshold = series.yAxis.getThreshold(options.threshold || 0),
  5816. useArea = /^area/.test(series.type),
  5817. singlePoints = [],
  5818. areaPath = [],
  5819. attribs;
  5820. each(series.segments, function(segment) {
  5821. segmentPath = [];
  5822. each(segment, function(point, i) {
  5823. if (series.getPointSpline) {
  5824. segmentPath.push.apply(segmentPath, series.getPointSpline(segment, point, i));
  5825. } else {
  5826. segmentPath.push(i ? L : M);
  5827. if (i && options.step) {
  5828. var lastPoint = segment[i - 1];
  5829. segmentPath.push(
  5830. point.plotX,
  5831. lastPoint.plotY
  5832. );
  5833. }
  5834. segmentPath.push(
  5835. point.plotX,
  5836. point.plotY
  5837. );
  5838. }
  5839. });
  5840. if (segment.length > 1) {
  5841. graphPath = graphPath.concat(segmentPath);
  5842. } else {
  5843. singlePoints.push(segment[0]);
  5844. }
  5845. if (useArea) {
  5846. var areaSegmentPath = [],
  5847. i,
  5848. segLength = segmentPath.length;
  5849. for (i = 0; i < segLength; i++) {
  5850. areaSegmentPath.push(segmentPath[i]);
  5851. }
  5852. if (segLength == 3) {
  5853. areaSegmentPath.push(L, segmentPath[1], segmentPath[2]);
  5854. }
  5855. if (options.stacking && series.type != 'areaspline') {
  5856. for (i = segment.length - 1; i >= 0; i--) {
  5857. areaSegmentPath.push(segment[i].plotX, segment[i].yBottom);
  5858. }
  5859. } else {
  5860. areaSegmentPath.push(
  5861. L,
  5862. segment[segment.length - 1].plotX,
  5863. translatedThreshold,
  5864. L,
  5865. segment[0].plotX,
  5866. translatedThreshold
  5867. );
  5868. }
  5869. areaPath = areaPath.concat(areaSegmentPath);
  5870. }
  5871. });
  5872. series.graphPath = graphPath;
  5873. series.singlePoints = singlePoints;
  5874. if (useArea) {
  5875. fillColor = pick(
  5876. options.fillColor,
  5877. Color(series.color).setOpacity(options.fillOpacity || 0.75).get()
  5878. );
  5879. if (area) {
  5880. area.animate({ d: areaPath });
  5881. } else {
  5882. series.area = series.chart.renderer.path(areaPath)
  5883. .attr({
  5884. fill: fillColor
  5885. }).add(group);
  5886. }
  5887. }
  5888. if (graph) {
  5889. graph.animate({ d: graphPath });
  5890. } else {
  5891. if (lineWidth) {
  5892. attribs = {
  5893. 'stroke': color,
  5894. 'stroke-width': lineWidth
  5895. };
  5896. if (dashStyle) {
  5897. attribs.dashstyle = dashStyle;
  5898. }
  5899. series.graph = renderer.path(graphPath)
  5900. .attr(attribs).add(group).shadow(options.shadow);
  5901. }
  5902. }
  5903. },
  5904. render: function() {
  5905. var series = this,
  5906. chart = series.chart,
  5907. group,
  5908. setInvert,
  5909. options = series.options,
  5910. doAnimation = options.animation && series.animate,
  5911. renderer = chart.renderer;
  5912. if (!series.clipRect) {
  5913. series.clipRect = !chart.hasRendered && chart.clipRect ?
  5914. chart.clipRect :
  5915. renderer.clipRect(0, 0, chart.plotSizeX, chart.plotSizeY);
  5916. if (!chart.clipRect) {
  5917. chart.clipRect = series.clipRect;
  5918. }
  5919. }
  5920. if (!series.group) {
  5921. group = series.group = renderer.g('series');
  5922. if (chart.inverted) {
  5923. setInvert = function() {
  5924. group.attr({
  5925. width: chart.plotWidth,
  5926. height: chart.plotHeight
  5927. }).invert();
  5928. };
  5929. setInvert();
  5930. addEvent(chart, 'resize', setInvert);
  5931. }
  5932. group.clip(series.clipRect)
  5933. .attr({
  5934. visibility: series.visible ? VISIBLE : HIDDEN,
  5935. zIndex: options.zIndex
  5936. })
  5937. .translate(chart.plotLeft, chart.plotTop)
  5938. .add(chart.seriesGroup);
  5939. }
  5940. series.drawDataLabels();
  5941. if (doAnimation) {
  5942. series.animate(true);
  5943. }
  5944. series.getAttribs();
  5945. if (series.drawGraph) {
  5946. series.drawGraph();
  5947. }
  5948. series.drawPoints();
  5949. if (series.options.enableMouseTracking !== false) {
  5950. series.drawTracker();
  5951. }
  5952. if (doAnimation) {
  5953. series.animate();
  5954. }
  5955. series.isDirty = false;
  5956. },
  5957. redraw: function() {
  5958. var series = this,
  5959. chart = series.chart,
  5960. clipRect = series.clipRect,
  5961. group = series.group;
  5962. if (group) {
  5963. if (chart.inverted) {
  5964. group.attr({
  5965. width: chart.plotWidth,
  5966. height: chart.plotHeight
  5967. });
  5968. }
  5969. group.animate({
  5970. translateX: chart.plotLeft,
  5971. translateY: chart.plotTop
  5972. });
  5973. }
  5974. series.translate();
  5975. series.setTooltipPoints(true);
  5976. series.render();
  5977. },
  5978. setState: function(state) {
  5979. var series = this,
  5980. options = series.options,
  5981. graph = series.graph,
  5982. stateOptions = options.states,
  5983. lineWidth = options.lineWidth;
  5984. state = state || NORMAL_STATE;
  5985. if (series.state != state) {
  5986. series.state = state;
  5987. if (stateOptions[state] && stateOptions[state].enabled === false) {
  5988. return;
  5989. }
  5990. if (state) {
  5991. lineWidth = stateOptions[state].lineWidth || lineWidth + 1;
  5992. }
  5993. if (graph && !graph.dashstyle) {
  5994. graph.attr({
  5995. 'stroke-width': lineWidth
  5996. }, state ? 0 : 500);
  5997. }
  5998. }
  5999. },
  6000. setVisible: function(vis, redraw) {
  6001. var series = this,
  6002. chart = series.chart,
  6003. legendItem = series.legendItem,
  6004. seriesGroup = series.group,
  6005. seriesTracker = series.tracker,
  6006. dataLabelsGroup = series.dataLabelsGroup,
  6007. showOrHide,
  6008. i,
  6009. data = series.data,
  6010. point,
  6011. ignoreHiddenSeries = chart.options.chart.ignoreHiddenSeries,
  6012. oldVisibility = series.visible;
  6013. series.visible = vis = vis === UNDEFINED ? !oldVisibility : vis;
  6014. showOrHide = vis ? 'show' : 'hide';
  6015. if (seriesGroup) {
  6016. seriesGroup[showOrHide]();
  6017. }
  6018. if (seriesTracker) {
  6019. seriesTracker[showOrHide]();
  6020. } else {
  6021. i = data.length;
  6022. while (i--) {
  6023. point = data[i];
  6024. if (point.tracker) {
  6025. point.tracker[showOrHide]();
  6026. }
  6027. }
  6028. }
  6029. if (dataLabelsGroup) {
  6030. dataLabelsGroup[showOrHide]();
  6031. }
  6032. if (legendItem) {
  6033. chart.legend.colorizeItem(series, vis);
  6034. }
  6035. series.isDirty = true;
  6036. if (series.options.stacking) {
  6037. each(chart.series, function(otherSeries) {
  6038. if (otherSeries.options.stacking && otherSeries.visible) {
  6039. otherSeries.isDirty = true;
  6040. }
  6041. });
  6042. }
  6043. if (ignoreHiddenSeries) {
  6044. chart.isDirtyBox = true;
  6045. }
  6046. if (redraw !== false) {
  6047. chart.redraw();
  6048. }
  6049. fireEvent(series, showOrHide);
  6050. },
  6051. show: function() {
  6052. this.setVisible(true);
  6053. },
  6054. hide: function() {
  6055. this.setVisible(false);
  6056. },
  6057. select: function(selected) {
  6058. var series = this;
  6059. series.selected = selected = (selected === UNDEFINED) ? !series.selected : selected;
  6060. if (series.checkbox) {
  6061. series.checkbox.checked = selected;
  6062. }
  6063. fireEvent(series, selected ? 'select' : 'unselect');
  6064. },
  6065. drawTracker: function() {
  6066. var series = this,
  6067. options = series.options,
  6068. trackerPath = [].concat(series.graphPath),
  6069. trackerPathLength = trackerPath.length,
  6070. chart = series.chart,
  6071. snap = chart.options.tooltip.snap,
  6072. tracker = series.tracker,
  6073. cursor = options.cursor,
  6074. css = cursor && { cursor: cursor },
  6075. singlePoints = series.singlePoints,
  6076. singlePoint,
  6077. i;
  6078. if (trackerPathLength) {
  6079. i = trackerPathLength + 1;
  6080. while (i--) {
  6081. if (trackerPath[i] == M) {
  6082. trackerPath.splice(i + 1, 0, trackerPath[i + 1] - snap, trackerPath[i + 2], L);
  6083. }
  6084. if ((i && trackerPath[i] == M) || i == trackerPathLength) {
  6085. trackerPath.splice(i, 0, L, trackerPath[i - 2] + snap, trackerPath[i - 1]);
  6086. }
  6087. }
  6088. }
  6089. for (i = 0; i < singlePoints.length; i++) {
  6090. singlePoint = singlePoints[i];
  6091. trackerPath.push(M, singlePoint.plotX - snap, singlePoint.plotY,
  6092. L, singlePoint.plotX + snap, singlePoint.plotY);
  6093. }
  6094. if (tracker) {
  6095. tracker.attr({ d: trackerPath });
  6096. } else {
  6097. series.tracker = chart.renderer.path(trackerPath)
  6098. .attr({
  6099. isTracker: true,
  6100. stroke: TRACKER_FILL,
  6101. fill: NONE,
  6102. 'stroke-width' : options.lineWidth + 2 * snap,
  6103. visibility: series.visible ? VISIBLE : HIDDEN,
  6104. zIndex: 1
  6105. })
  6106. .on(hasTouch ? 'touchstart' : 'mouseover', function() {
  6107. if (chart.hoverSeries != series) {
  6108. series.onMouseOver();
  6109. }
  6110. })
  6111. .on('mouseout', function() {
  6112. if (!options.stickyTracking) {
  6113. series.onMouseOut();
  6114. }
  6115. })
  6116. .css(css)
  6117. .add(chart.trackerGroup);
  6118. }
  6119. }
  6120. };
  6121. var LineSeries = extendClass(Series);
  6122. seriesTypes.line = LineSeries;
  6123. var AreaSeries = extendClass(Series, {
  6124. type: 'area'
  6125. });
  6126. seriesTypes.area = AreaSeries;
  6127. var SplineSeries = extendClass( Series, {
  6128. type: 'spline',
  6129. getPointSpline: function(segment, point, i) {
  6130. var smoothing = 1.5,
  6131. denom = smoothing + 1,
  6132. plotX = point.plotX,
  6133. plotY = point.plotY,
  6134. lastPoint = segment[i - 1],
  6135. nextPoint = segment[i + 1],
  6136. leftContX,
  6137. leftContY,
  6138. rightContX,
  6139. rightContY,
  6140. ret;
  6141. if (i && i < segment.length - 1) {
  6142. var lastX = lastPoint.plotX,
  6143. lastY = lastPoint.plotY,
  6144. nextX = nextPoint.plotX,
  6145. nextY = nextPoint.plotY,
  6146. correction;
  6147. leftContX = (smoothing * plotX + lastX) / denom;
  6148. leftContY = (smoothing * plotY + lastY) / denom;
  6149. rightContX = (smoothing * plotX + nextX) / denom;
  6150. rightContY = (smoothing * plotY + nextY) / denom;
  6151. correction = ((rightContY - leftContY) * (rightContX - plotX)) /
  6152. (rightContX - leftContX) + plotY - rightContY;
  6153. leftContY += correction;
  6154. rightContY += correction;
  6155. if (leftContY > lastY && leftContY > plotY) {
  6156. leftContY = mathMax(lastY, plotY);
  6157. rightContY = 2 * plotY - leftContY;
  6158. } else if (leftContY < lastY && leftContY < plotY) {
  6159. leftContY = mathMin(lastY, plotY);
  6160. rightContY = 2 * plotY - leftContY;
  6161. }
  6162. if (rightContY > nextY && rightContY > plotY) {
  6163. rightContY = mathMax(nextY, plotY);
  6164. leftContY = 2 * plotY - rightContY;
  6165. } else if (rightContY < nextY && rightContY < plotY) {
  6166. rightContY = mathMin(nextY, plotY);
  6167. leftContY = 2 * plotY - rightContY;
  6168. }
  6169. point.rightContX = rightContX;
  6170. point.rightContY = rightContY;
  6171. }
  6172. if (!i) {
  6173. ret = [M, plotX, plotY];
  6174. }
  6175. else {
  6176. ret = [
  6177. 'C',
  6178. lastPoint.rightContX || lastPoint.plotX,
  6179. lastPoint.rightContY || lastPoint.plotY,
  6180. leftContX || plotX,
  6181. leftContY || plotY,
  6182. plotX,
  6183. plotY
  6184. ];
  6185. lastPoint.rightContX = lastPoint.rightContY = null;
  6186. }
  6187. return ret;
  6188. }
  6189. });
  6190. seriesTypes.spline = SplineSeries;
  6191. var AreaSplineSeries = extendClass(SplineSeries, {
  6192. type: 'areaspline'
  6193. });
  6194. seriesTypes.areaspline = AreaSplineSeries;
  6195. var ColumnSeries = extendClass(Series, {
  6196. type: 'column',
  6197. pointAttrToOptions: {
  6198. stroke: 'borderColor',
  6199. 'stroke-width': 'borderWidth',
  6200. fill: 'color',
  6201. r: 'borderRadius'
  6202. },
  6203. init: function() {
  6204. Series.prototype.init.apply(this, arguments);
  6205. var series = this,
  6206. chart = series.chart;
  6207. chart.hasColumn = true;
  6208. if (chart.hasRendered) {
  6209. each(chart.series, function(otherSeries) {
  6210. if (otherSeries.type == series.type) {
  6211. otherSeries.isDirty = true;
  6212. }
  6213. });
  6214. }
  6215. },
  6216. translate: function() {
  6217. var series = this,
  6218. chart = series.chart,
  6219. columnCount = 0,
  6220. reversedXAxis = series.xAxis.reversed,
  6221. categories = series.xAxis.categories,
  6222. stackGroups = {},
  6223. stackKey,
  6224. columnIndex;
  6225. Series.prototype.translate.apply(series);
  6226. each(chart.series, function(otherSeries) {
  6227. if (otherSeries.type == series.type) {
  6228. if (otherSeries.options.stacking) {
  6229. stackKey = otherSeries.stackKey;
  6230. if (stackGroups[stackKey] === UNDEFINED) {
  6231. stackGroups[stackKey] = columnCount++;
  6232. }
  6233. columnIndex = stackGroups[stackKey];
  6234. } else {
  6235. columnIndex = columnCount++;
  6236. }
  6237. otherSeries.columnIndex = columnIndex;
  6238. }
  6239. });
  6240. var options = series.options,
  6241. data = series.data,
  6242. closestPoints = series.closestPoints,
  6243. categoryWidth = mathAbs(
  6244. data[1] ? data[closestPoints].plotX - data[closestPoints - 1].plotX :
  6245. chart.plotSizeX / (categories ? categories.length : 1)
  6246. ),
  6247. groupPadding = categoryWidth * options.groupPadding,
  6248. groupWidth = categoryWidth - 2 * groupPadding,
  6249. pointOffsetWidth = groupWidth / columnCount,
  6250. optionPointWidth = options.pointWidth,
  6251. pointPadding = defined(optionPointWidth) ? (pointOffsetWidth - optionPointWidth) / 2 :
  6252. pointOffsetWidth * options.pointPadding,
  6253. pointWidth = pick(optionPointWidth, pointOffsetWidth - 2 * pointPadding),
  6254. colIndex = (reversedXAxis ? columnCount -
  6255. series.columnIndex : series.columnIndex) || 0,
  6256. pointXOffset = pointPadding + (groupPadding + colIndex *
  6257. pointOffsetWidth -(categoryWidth / 2)) *
  6258. (reversedXAxis ? -1 : 1),
  6259. threshold = options.threshold || 0,
  6260. translatedThreshold = series.yAxis.getThreshold(threshold),
  6261. minPointLength = pick(options.minPointLength, 5);
  6262. each(data, function(point) {
  6263. var plotY = point.plotY,
  6264. yBottom = point.yBottom || translatedThreshold,
  6265. barX = point.plotX + pointXOffset,
  6266. barY = mathCeil(mathMin(plotY, yBottom)),
  6267. barW = pointWidth,
  6268. barH = mathCeil(mathMax(plotY, yBottom) - barY),
  6269. trackerY;
  6270. if (mathAbs(barH) < minPointLength) {
  6271. if (minPointLength) {
  6272. barH = minPointLength;
  6273. barY =
  6274. mathAbs(barY - translatedThreshold) > minPointLength ?
  6275. yBottom - minPointLength :
  6276. translatedThreshold - (plotY <= translatedThreshold ? minPointLength : 0);
  6277. }
  6278. trackerY = barY - 3;
  6279. }
  6280. extend(point, {
  6281. barX: barX,
  6282. barY: barY,
  6283. barW: barW,
  6284. barH: barH
  6285. });
  6286. point.shapeType = 'rect';
  6287. point.shapeArgs = {
  6288. x: barX,
  6289. y: barY,
  6290. width: barW,
  6291. height: barH,
  6292. r: options.borderRadius
  6293. };
  6294. point.trackerArgs = defined(trackerY) && merge(point.shapeArgs, {
  6295. height: mathMax(6, barH + 3),
  6296. y: trackerY
  6297. });
  6298. });
  6299. },
  6300. getSymbol: function(){
  6301. },
  6302. drawGraph: function() {},
  6303. drawPoints: function() {
  6304. var series = this,
  6305. options = series.options,
  6306. renderer = series.chart.renderer,
  6307. graphic,
  6308. shapeArgs;
  6309. each(series.data, function(point) {
  6310. var plotY = point.plotY;
  6311. if (plotY !== UNDEFINED && !isNaN(plotY)) {
  6312. graphic = point.graphic;
  6313. shapeArgs = point.shapeArgs;
  6314. if (graphic) {
  6315. stop(graphic);
  6316. graphic.animate(shapeArgs);
  6317. } else {
  6318. point.graphic = renderer[point.shapeType](shapeArgs)
  6319. .attr(point.pointAttr[point.selected ? SELECT_STATE : NORMAL_STATE])
  6320. .add(series.group)
  6321. .shadow(options.shadow);
  6322. }
  6323. }
  6324. });
  6325. },
  6326. drawTracker: function() {
  6327. var series = this,
  6328. chart = series.chart,
  6329. renderer = chart.renderer,
  6330. shapeArgs,
  6331. tracker,
  6332. trackerLabel = +new Date(),
  6333. cursor = series.options.cursor,
  6334. css = cursor && { cursor: cursor },
  6335. rel;
  6336. each(series.data, function(point) {
  6337. tracker = point.tracker;
  6338. shapeArgs = point.trackerArgs || point.shapeArgs;
  6339. if (point.y !== null) {
  6340. if (tracker) {
  6341. tracker.attr(shapeArgs);
  6342. } else {
  6343. point.tracker =
  6344. renderer[point.shapeType](shapeArgs)
  6345. .attr({
  6346. isTracker: trackerLabel,
  6347. fill: TRACKER_FILL,
  6348. visibility: series.visible ? VISIBLE : HIDDEN,
  6349. zIndex: 1
  6350. })
  6351. .on(hasTouch ? 'touchstart' : 'mouseover', function(event) {
  6352. rel = event.relatedTarget || event.fromElement;
  6353. if (chart.hoverSeries != series && attr(rel, 'isTracker') != trackerLabel) {
  6354. series.onMouseOver();
  6355. }
  6356. point.onMouseOver();
  6357. })
  6358. .on('mouseout', function(event) {
  6359. if (!series.options.stickyTracking) {
  6360. rel = event.relatedTarget || event.toElement;
  6361. if (attr(rel, 'isTracker') != trackerLabel) {
  6362. series.onMouseOut();
  6363. }
  6364. }
  6365. })
  6366. .css(css)
  6367. .add(chart.trackerGroup);
  6368. }
  6369. }
  6370. });
  6371. },
  6372. animate: function(init) {
  6373. var series = this,
  6374. data = series.data;
  6375. if (!init) {
  6376. each(data, function(point) {
  6377. var graphic = point.graphic;
  6378. if (graphic) {
  6379. graphic.attr({
  6380. height: 0,
  6381. y: series.yAxis.translate(0, 0, 1)
  6382. });
  6383. graphic.animate({
  6384. height: point.barH,
  6385. y: point.barY
  6386. }, series.options.animation);
  6387. }
  6388. });
  6389. series.animate = null;
  6390. }
  6391. },
  6392. remove: function() {
  6393. var series = this,
  6394. chart = series.chart;
  6395. if (chart.hasRendered) {
  6396. each(chart.series, function(otherSeries) {
  6397. if (otherSeries.type == series.type) {
  6398. otherSeries.isDirty = true;
  6399. }
  6400. });
  6401. }
  6402. Series.prototype.remove.apply(series, arguments);
  6403. }
  6404. });
  6405. seriesTypes.column = ColumnSeries;
  6406. var BarSeries = extendClass(ColumnSeries, {
  6407. type: 'bar',
  6408. init: function(chart) {
  6409. chart.inverted = this.inverted = true;
  6410. ColumnSeries.prototype.init.apply(this, arguments);
  6411. }
  6412. });
  6413. seriesTypes.bar = BarSeries;
  6414. var ScatterSeries = extendClass(Series, {
  6415. type: 'scatter',
  6416. translate: function() {
  6417. var series = this;
  6418. Series.prototype.translate.apply(series);
  6419. each(series.data, function(point) {
  6420. point.shapeType = 'circle';
  6421. point.shapeArgs = {
  6422. x: point.plotX,
  6423. y: point.plotY,
  6424. r: series.chart.options.tooltip.snap
  6425. };
  6426. });
  6427. },
  6428. drawTracker: function() {
  6429. var series = this,
  6430. cursor = series.options.cursor,
  6431. css = cursor && { cursor: cursor },
  6432. graphic;
  6433. each(series.data, function(point) {
  6434. graphic = point.graphic;
  6435. if (graphic) {
  6436. graphic
  6437. .attr({ isTracker: true })
  6438. .on('mouseover', function(event) {
  6439. series.onMouseOver();
  6440. point.onMouseOver();
  6441. })
  6442. .on('mouseout', function(event) {
  6443. if (!series.options.stickyTracking) {
  6444. series.onMouseOut();
  6445. }
  6446. })
  6447. .css(css);
  6448. }
  6449. });
  6450. },
  6451. cleanData: function() {}
  6452. });
  6453. seriesTypes.scatter = ScatterSeries;
  6454. var PiePoint = extendClass(Point, {
  6455. init: function () {
  6456. Point.prototype.init.apply(this, arguments);
  6457. var point = this,
  6458. toggleSlice;
  6459. extend(point, {
  6460. visible: point.visible !== false,
  6461. name: pick(point.name, 'Slice')
  6462. });
  6463. toggleSlice = function() {
  6464. point.slice();
  6465. };
  6466. addEvent(point, 'select', toggleSlice);
  6467. addEvent(point, 'unselect', toggleSlice);
  6468. return point;
  6469. },
  6470. setVisible: function(vis) {
  6471. var point = this,
  6472. chart = point.series.chart,
  6473. tracker = point.tracker,
  6474. dataLabel = point.dataLabel,
  6475. connector = point.connector,
  6476. method;
  6477. point.visible = vis = vis === UNDEFINED ? !point.visible : vis;
  6478. method = vis ? 'show' : 'hide';
  6479. point.group[method]();
  6480. if (tracker) {
  6481. tracker[method]();
  6482. }
  6483. if (dataLabel) {
  6484. dataLabel[method]();
  6485. }
  6486. if (connector) {
  6487. connector[method]();
  6488. }
  6489. if (point.legendItem) {
  6490. chart.legend.colorizeItem(point, vis);
  6491. }
  6492. },
  6493. slice: function(sliced, redraw, animation) {
  6494. var point = this,
  6495. series = point.series,
  6496. chart = series.chart,
  6497. slicedTranslation = point.slicedTranslation;
  6498. setAnimation(animation, chart);
  6499. redraw = pick(redraw, true);
  6500. sliced = point.sliced = defined(sliced) ? sliced : !point.sliced;
  6501. point.group.animate({
  6502. translateX: (sliced ? slicedTranslation[0] : chart.plotLeft),
  6503. translateY: (sliced ? slicedTranslation[1] : chart.plotTop)
  6504. });
  6505. }
  6506. });
  6507. var PieSeries = extendClass(Series, {
  6508. type: 'pie',
  6509. isCartesian: false,
  6510. pointClass: PiePoint,
  6511. pointAttrToOptions: {
  6512. stroke: 'borderColor',
  6513. 'stroke-width': 'borderWidth',
  6514. fill: 'color'
  6515. },
  6516. getColor: function() {
  6517. this.initialColor = colorCounter;
  6518. },
  6519. animate: function(init) {
  6520. var series = this,
  6521. data = series.data;
  6522. each(data, function(point) {
  6523. var graphic = point.graphic,
  6524. args = point.shapeArgs,
  6525. up = -mathPI / 2;
  6526. if (graphic) {
  6527. graphic.attr({
  6528. r: 0,
  6529. start: up,
  6530. end: up
  6531. });
  6532. graphic.animate({
  6533. r: args.r,
  6534. start: args.start,
  6535. end: args.end
  6536. }, series.options.animation);
  6537. }
  6538. });
  6539. series.animate = null;
  6540. },
  6541. translate: function() {
  6542. var total = 0,
  6543. series = this,
  6544. cumulative = -0.25,
  6545. options = series.options,
  6546. slicedOffset = options.slicedOffset,
  6547. connectorOffset = slicedOffset + options.borderWidth,
  6548. positions = options.center,
  6549. chart = series.chart,
  6550. plotWidth = chart.plotWidth,
  6551. plotHeight = chart.plotHeight,
  6552. start,
  6553. end,
  6554. angle,
  6555. data = series.data,
  6556. circ = 2 * mathPI,
  6557. fraction,
  6558. smallestSize = mathMin(plotWidth, plotHeight),
  6559. isPercent,
  6560. radiusX,
  6561. radiusY,
  6562. labelDistance = options.dataLabels.distance;
  6563. positions.push(options.size, options.innerSize || 0);
  6564. positions = map(positions, function(length, i) {
  6565. isPercent = /%$/.test(length);
  6566. return isPercent ?
  6567. [plotWidth, plotHeight, smallestSize, smallestSize][i] *
  6568. pInt(length) / 100:
  6569. length;
  6570. });
  6571. series.getX = function(y, left) {
  6572. angle = math.asin((y - positions[1]) / (positions[2] / 2 + labelDistance));
  6573. return positions[0] +
  6574. (left ? -1 : 1) *
  6575. (mathCos(angle) * (positions[2] / 2 + labelDistance));
  6576. };
  6577. series.center = positions;
  6578. each(data, function(point) {
  6579. total += point.y;
  6580. });
  6581. each(data, function(point) {
  6582. fraction = total ? point.y / total : 0;
  6583. start = cumulative * circ;
  6584. cumulative += fraction;
  6585. end = cumulative * circ;
  6586. point.shapeType = 'arc';
  6587. point.shapeArgs = {
  6588. x: positions[0],
  6589. y: positions[1],
  6590. r: positions[2] / 2,
  6591. innerR: positions[3] / 2,
  6592. start: start,
  6593. end: end
  6594. };
  6595. angle = (end + start) / 2;
  6596. point.slicedTranslation = map([
  6597. mathCos(angle) * slicedOffset + chart.plotLeft,
  6598. mathSin(angle) * slicedOffset + chart.plotTop
  6599. ], mathRound);
  6600. radiusX = mathCos(angle) * positions[2] / 2;
  6601. radiusY = mathSin(angle) * positions[2] / 2;
  6602. point.tooltipPos = [
  6603. positions[0] + radiusX * 0.7,
  6604. positions[1] + radiusY * 0.7
  6605. ];
  6606. point.labelPos = [
  6607. positions[0] + radiusX + mathCos(angle) * labelDistance,
  6608. positions[1] + radiusY + mathSin(angle) * labelDistance,
  6609. positions[0] + radiusX + mathCos(angle) * connectorOffset,
  6610. positions[1] + radiusY + mathSin(angle) * connectorOffset,
  6611. positions[0] + radiusX,
  6612. positions[1] + radiusY,
  6613. labelDistance < 0 ?
  6614. 'center' :
  6615. angle < circ / 4 ? 'left' : 'right',
  6616. angle
  6617. ];
  6618. point.percentage = fraction * 100;
  6619. point.total = total;
  6620. });
  6621. this.setTooltipPoints();
  6622. },
  6623. render: function() {
  6624. var series = this;
  6625. series.getAttribs();
  6626. this.drawPoints();
  6627. if (series.options.enableMouseTracking !== false) {
  6628. series.drawTracker();
  6629. }
  6630. this.drawDataLabels();
  6631. if (series.options.animation && series.animate) {
  6632. series.animate();
  6633. }
  6634. series.isDirty = false;
  6635. },
  6636. drawPoints: function() {
  6637. var series = this,
  6638. chart = series.chart,
  6639. renderer = chart.renderer,
  6640. groupTranslation,
  6641. graphic,
  6642. shapeArgs;
  6643. each(series.data, function(point) {
  6644. graphic = point.graphic;
  6645. shapeArgs = point.shapeArgs;
  6646. if (!point.group) {
  6647. groupTranslation = point.sliced ? point.slicedTranslation : [chart.plotLeft, chart.plotTop];
  6648. point.group = renderer.g('point')
  6649. .attr({ zIndex: 5 })
  6650. .add()
  6651. .translate(groupTranslation[0], groupTranslation[1]);
  6652. }
  6653. if (graphic) {
  6654. graphic.animate(shapeArgs);
  6655. } else {
  6656. point.graphic =
  6657. renderer.arc(shapeArgs)
  6658. .attr(point.pointAttr[NORMAL_STATE])
  6659. .add(point.group);
  6660. }
  6661. if (point.visible === false) {
  6662. point.setVisible(false);
  6663. }
  6664. });
  6665. },
  6666. drawDataLabels: function() {
  6667. var series = this,
  6668. data = series.data,
  6669. point,
  6670. chart = series.chart,
  6671. options = series.options.dataLabels,
  6672. connectorPadding = pick(options.connectorPadding, 10),
  6673. connectorWidth = pick(options.connectorWidth, 1),
  6674. connector,
  6675. connectorPath,
  6676. outside = options.distance > 0,
  6677. dataLabel,
  6678. labelPos,
  6679. labelHeight,
  6680. lastY,
  6681. centerY = series.center[1],
  6682. quarters = [
  6683. [],
  6684. [],
  6685. [],
  6686. []
  6687. ],
  6688. x,
  6689. y,
  6690. visibility,
  6691. overlapping,
  6692. rankArr,
  6693. secondPass,
  6694. sign,
  6695. lowerHalf,
  6696. sort,
  6697. i = 4,
  6698. j;
  6699. Series.prototype.drawDataLabels.apply(series);
  6700. each(data, function(point) {
  6701. var angle = point.labelPos[7],
  6702. quarter;
  6703. if (angle < 0) {
  6704. quarter = 0;
  6705. } else if (angle < mathPI / 2) {
  6706. quarter = 1;
  6707. } else if (angle < mathPI) {
  6708. quarter = 2;
  6709. } else {
  6710. quarter = 3;
  6711. }
  6712. quarters[quarter].push(point);
  6713. });
  6714. quarters[1].reverse();
  6715. quarters[3].reverse();
  6716. sort = function(a,b) {
  6717. return a.y > b.y;
  6718. };
  6719. while (i--) {
  6720. overlapping = 0;
  6721. rankArr = [].concat(quarters[i]);
  6722. rankArr.sort(sort);
  6723. j = rankArr.length;
  6724. while (j--) {
  6725. rankArr[j].rank = j;
  6726. }
  6727. for (secondPass = 0; secondPass < 2; secondPass++) {
  6728. lowerHalf = i % 3;
  6729. lastY = lowerHalf ? 9999 : -9999;
  6730. sign = lowerHalf ? -1 : 1;
  6731. for (j = 0; j < quarters[i].length; j++) {
  6732. point = quarters[i][j];
  6733. if ((dataLabel = point.dataLabel)) {
  6734. labelPos = point.labelPos;
  6735. visibility = VISIBLE;
  6736. x = labelPos[0];
  6737. y = labelPos[1];
  6738. if (!labelHeight) {
  6739. labelHeight = dataLabel && dataLabel.getBBox().height;
  6740. }
  6741. if (outside) {
  6742. if (secondPass && point.rank < overlapping) {
  6743. visibility = HIDDEN;
  6744. } else if ((!lowerHalf && y < lastY + labelHeight) ||
  6745. (lowerHalf && y > lastY - labelHeight)) {
  6746. y = lastY + sign * labelHeight;
  6747. x = series.getX(y, i > 1);
  6748. if ((!lowerHalf && y + labelHeight > centerY) ||
  6749. (lowerHalf && y -labelHeight < centerY)) {
  6750. if (secondPass) {
  6751. visibility = HIDDEN;
  6752. } else {
  6753. overlapping++;
  6754. }
  6755. }
  6756. }
  6757. }
  6758. if (point.visible === false) {
  6759. visibility = HIDDEN;
  6760. }
  6761. if (visibility == VISIBLE) {
  6762. lastY = y;
  6763. }
  6764. if (secondPass) {
  6765. dataLabel
  6766. .attr({
  6767. visibility: visibility,
  6768. align: labelPos[6]
  6769. })
  6770. [dataLabel.moved ? 'animate' : 'attr']({
  6771. x: x + options.x +
  6772. ({ left: connectorPadding, right: -connectorPadding }[labelPos[6]] || 0),
  6773. y: y + options.y
  6774. });
  6775. dataLabel.moved = true;
  6776. if (outside && connectorWidth) {
  6777. connector = point.connector;
  6778. connectorPath = [
  6779. M,
  6780. x + (labelPos[6] == 'left' ? 5 : -5), y,
  6781. L,
  6782. x, y,
  6783. L,
  6784. labelPos[2], labelPos[3],
  6785. L,
  6786. labelPos[4], labelPos[5]
  6787. ];
  6788. if (connector) {
  6789. connector.animate({ d: connectorPath });
  6790. connector.attr('visibility', visibility);
  6791. } else {
  6792. point.connector = connector = series.chart.renderer.path(connectorPath).attr({
  6793. 'stroke-width': connectorWidth,
  6794. stroke: options.connectorColor || '#606060',
  6795. visibility: visibility,
  6796. zIndex: 3
  6797. })
  6798. .translate(chart.plotLeft, chart.plotTop)
  6799. .add();
  6800. }
  6801. }
  6802. }
  6803. }
  6804. }
  6805. }
  6806. }
  6807. },
  6808. drawTracker: ColumnSeries.prototype.drawTracker,
  6809. getSymbol: function() {}
  6810. });
  6811. seriesTypes.pie = PieSeries;
  6812. if (useCanVG) {
  6813. var head = doc.getElementsByTagName('head')[0];
  6814. createElement('script', {
  6815. type: 'text/javascript',
  6816. src: 'http://highcharts.com/js/canvg.js',
  6817. onload: function() {
  6818. drawDeferredCanvases();
  6819. }
  6820. }, null, head);
  6821. }
  6822. win.Highcharts = {
  6823. Chart: Chart,
  6824. dateFormat: dateFormat,
  6825. pathAnim: pathAnim,
  6826. getOptions: getOptions,
  6827. numberFormat: numberFormat,
  6828. Point: Point,
  6829. Renderer: Renderer,
  6830. seriesTypes: seriesTypes,
  6831. setOptions: setOptions,
  6832. Series: Series,
  6833. addEvent: addEvent,
  6834. createElement: createElement,
  6835. discardElement: discardElement,
  6836. css: css,
  6837. each: each,
  6838. extend: extend,
  6839. map: map,
  6840. merge: merge,
  6841. pick: pick,
  6842. extendClass: extendClass,
  6843. version: '2.1.1'
  6844. };
  6845. })();