c3.js 359 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202
  1. (function (window) {
  2. 'use strict';
  3. /*global define, module, exports, require */
  4. var c3 = { version: "0.4.11" };
  5. var c3_chart_fn,
  6. c3_chart_internal_fn,
  7. c3_chart_internal_axis_fn;
  8. function API(owner) {
  9. this.owner = owner;
  10. }
  11. function inherit(base, derived) {
  12. if (Object.create) {
  13. derived.prototype = Object.create(base.prototype);
  14. } else {
  15. var f = function f() {};
  16. f.prototype = base.prototype;
  17. derived.prototype = new f();
  18. }
  19. derived.prototype.constructor = derived;
  20. return derived;
  21. }
  22. function Chart(config) {
  23. var $$ = this.internal = new ChartInternal(this);
  24. $$.loadConfig(config);
  25. $$.beforeInit(config);
  26. $$.init();
  27. $$.afterInit(config);
  28. // bind "this" to nested API
  29. (function bindThis(fn, target, argThis) {
  30. Object.keys(fn).forEach(function (key) {
  31. target[key] = fn[key].bind(argThis);
  32. if (Object.keys(fn[key]).length > 0) {
  33. bindThis(fn[key], target[key], argThis);
  34. }
  35. });
  36. })(c3_chart_fn, this, this);
  37. }
  38. function ChartInternal(api) {
  39. var $$ = this;
  40. $$.d3 = window.d3 ? window.d3 : typeof require !== 'undefined' ? require("d3") : undefined;
  41. $$.api = api;
  42. $$.config = $$.getDefaultConfig();
  43. $$.data = {};
  44. $$.cache = {};
  45. $$.axes = {};
  46. }
  47. c3.generate = function (config) {
  48. return new Chart(config);
  49. };
  50. c3.chart = {
  51. fn: Chart.prototype,
  52. internal: {
  53. fn: ChartInternal.prototype,
  54. axis: {
  55. fn: Axis.prototype
  56. }
  57. }
  58. };
  59. c3_chart_fn = c3.chart.fn;
  60. c3_chart_internal_fn = c3.chart.internal.fn;
  61. c3_chart_internal_axis_fn = c3.chart.internal.axis.fn;
  62. c3_chart_internal_fn.beforeInit = function () {
  63. // can do something
  64. };
  65. c3_chart_internal_fn.afterInit = function () {
  66. // can do something
  67. };
  68. c3_chart_internal_fn.init = function () {
  69. var $$ = this, config = $$.config;
  70. $$.initParams();
  71. if (config.data_url) {
  72. $$.convertUrlToData(config.data_url, config.data_mimeType, config.data_headers, config.data_keys, $$.initWithData);
  73. }
  74. else if (config.data_json) {
  75. $$.initWithData($$.convertJsonToData(config.data_json, config.data_keys));
  76. }
  77. else if (config.data_rows) {
  78. $$.initWithData($$.convertRowsToData(config.data_rows));
  79. }
  80. else if (config.data_columns) {
  81. $$.initWithData($$.convertColumnsToData(config.data_columns));
  82. }
  83. else {
  84. throw Error('url or json or rows or columns is required.');
  85. }
  86. };
  87. c3_chart_internal_fn.initParams = function () {
  88. var $$ = this, d3 = $$.d3, config = $$.config;
  89. // MEMO: clipId needs to be unique because it conflicts when multiple charts exist
  90. $$.clipId = "c3-" + (+new Date()) + '-clip',
  91. $$.clipIdForXAxis = $$.clipId + '-xaxis',
  92. $$.clipIdForYAxis = $$.clipId + '-yaxis',
  93. $$.clipIdForGrid = $$.clipId + '-grid',
  94. $$.clipIdForSubchart = $$.clipId + '-subchart',
  95. $$.clipPath = $$.getClipPath($$.clipId),
  96. $$.clipPathForXAxis = $$.getClipPath($$.clipIdForXAxis),
  97. $$.clipPathForYAxis = $$.getClipPath($$.clipIdForYAxis);
  98. $$.clipPathForGrid = $$.getClipPath($$.clipIdForGrid),
  99. $$.clipPathForSubchart = $$.getClipPath($$.clipIdForSubchart),
  100. $$.dragStart = null;
  101. $$.dragging = false;
  102. $$.flowing = false;
  103. $$.cancelClick = false;
  104. $$.mouseover = false;
  105. $$.transiting = false;
  106. $$.color = $$.generateColor();
  107. $$.levelColor = $$.generateLevelColor();
  108. $$.dataTimeFormat = config.data_xLocaltime ? d3.time.format : d3.time.format.utc;
  109. $$.axisTimeFormat = config.axis_x_localtime ? d3.time.format : d3.time.format.utc;
  110. $$.defaultAxisTimeFormat = $$.axisTimeFormat.multi([
  111. [".%L", function (d) { return d.getMilliseconds(); }],
  112. [":%S", function (d) { return d.getSeconds(); }],
  113. ["%I:%M", function (d) { return d.getMinutes(); }],
  114. ["%I %p", function (d) { return d.getHours(); }],
  115. ["%-m/%-d", function (d) { return d.getDay() && d.getDate() !== 1; }],
  116. ["%-m/%-d", function (d) { return d.getDate() !== 1; }],
  117. ["%-m/%-d", function (d) { return d.getMonth(); }],
  118. ["%Y/%-m/%-d", function () { return true; }]
  119. ]);
  120. $$.hiddenTargetIds = [];
  121. $$.hiddenLegendIds = [];
  122. $$.focusedTargetIds = [];
  123. $$.defocusedTargetIds = [];
  124. $$.xOrient = config.axis_rotated ? "left" : "bottom";
  125. $$.yOrient = config.axis_rotated ? (config.axis_y_inner ? "top" : "bottom") : (config.axis_y_inner ? "right" : "left");
  126. $$.y2Orient = config.axis_rotated ? (config.axis_y2_inner ? "bottom" : "top") : (config.axis_y2_inner ? "left" : "right");
  127. $$.subXOrient = config.axis_rotated ? "left" : "bottom";
  128. $$.isLegendRight = config.legend_position === 'right';
  129. $$.isLegendInset = config.legend_position === 'inset';
  130. $$.isLegendTop = config.legend_inset_anchor === 'top-left' || config.legend_inset_anchor === 'top-right';
  131. $$.isLegendLeft = config.legend_inset_anchor === 'top-left' || config.legend_inset_anchor === 'bottom-left';
  132. $$.legendStep = 0;
  133. $$.legendItemWidth = 0;
  134. $$.legendItemHeight = 0;
  135. $$.currentMaxTickWidths = {
  136. x: 0,
  137. y: 0,
  138. y2: 0
  139. };
  140. $$.rotated_padding_left = 30;
  141. $$.rotated_padding_right = config.axis_rotated && !config.axis_x_show ? 0 : 30;
  142. $$.rotated_padding_top = 5;
  143. $$.withoutFadeIn = {};
  144. $$.intervalForObserveInserted = undefined;
  145. $$.axes.subx = d3.selectAll([]); // needs when excluding subchart.js
  146. };
  147. c3_chart_internal_fn.initChartElements = function () {
  148. if (this.initBar) { this.initBar(); }
  149. if (this.initLine) { this.initLine(); }
  150. if (this.initArc) { this.initArc(); }
  151. if (this.initGauge) { this.initGauge(); }
  152. if (this.initText) { this.initText(); }
  153. };
  154. c3_chart_internal_fn.initWithData = function (data) {
  155. var $$ = this, d3 = $$.d3, config = $$.config;
  156. var defs, main, binding = true;
  157. $$.axis = new Axis($$);
  158. if ($$.initPie) { $$.initPie(); }
  159. if ($$.initBrush) { $$.initBrush(); }
  160. if ($$.initZoom) { $$.initZoom(); }
  161. if (!config.bindto) {
  162. $$.selectChart = d3.selectAll([]);
  163. }
  164. else if (typeof config.bindto.node === 'function') {
  165. $$.selectChart = config.bindto;
  166. }
  167. else {
  168. $$.selectChart = d3.select(config.bindto);
  169. }
  170. if ($$.selectChart.empty()) {
  171. $$.selectChart = d3.select(document.createElement('div')).style('opacity', 0);
  172. $$.observeInserted($$.selectChart);
  173. binding = false;
  174. }
  175. $$.selectChart.html("").classed("c3", true);
  176. // Init data as targets
  177. $$.data.xs = {};
  178. $$.data.targets = $$.convertDataToTargets(data);
  179. if (config.data_filter) {
  180. $$.data.targets = $$.data.targets.filter(config.data_filter);
  181. }
  182. // Set targets to hide if needed
  183. if (config.data_hide) {
  184. $$.addHiddenTargetIds(config.data_hide === true ? $$.mapToIds($$.data.targets) : config.data_hide);
  185. }
  186. if (config.legend_hide) {
  187. $$.addHiddenLegendIds(config.legend_hide === true ? $$.mapToIds($$.data.targets) : config.legend_hide);
  188. }
  189. // when gauge, hide legend // TODO: fix
  190. if ($$.hasType('gauge')) {
  191. config.legend_show = false;
  192. }
  193. // Init sizes and scales
  194. $$.updateSizes();
  195. $$.updateScales();
  196. // Set domains for each scale
  197. $$.x.domain(d3.extent($$.getXDomain($$.data.targets)));
  198. $$.y.domain($$.getYDomain($$.data.targets, 'y'));
  199. $$.y2.domain($$.getYDomain($$.data.targets, 'y2'));
  200. $$.subX.domain($$.x.domain());
  201. $$.subY.domain($$.y.domain());
  202. $$.subY2.domain($$.y2.domain());
  203. // Save original x domain for zoom update
  204. $$.orgXDomain = $$.x.domain();
  205. // Set initialized scales to brush and zoom
  206. if ($$.brush) { $$.brush.scale($$.subX); }
  207. if (config.zoom_enabled) { $$.zoom.scale($$.x); }
  208. /*-- Basic Elements --*/
  209. // Define svgs
  210. $$.svg = $$.selectChart.append("svg")
  211. .style("overflow", "hidden")
  212. .on('mouseenter', function () { return config.onmouseover.call($$); })
  213. .on('mouseleave', function () { return config.onmouseout.call($$); });
  214. if ($$.config.svg_classname) {
  215. $$.svg.attr('class', $$.config.svg_classname);
  216. }
  217. // Define defs
  218. defs = $$.svg.append("defs");
  219. $$.clipChart = $$.appendClip(defs, $$.clipId);
  220. $$.clipXAxis = $$.appendClip(defs, $$.clipIdForXAxis);
  221. $$.clipYAxis = $$.appendClip(defs, $$.clipIdForYAxis);
  222. $$.clipGrid = $$.appendClip(defs, $$.clipIdForGrid);
  223. $$.clipSubchart = $$.appendClip(defs, $$.clipIdForSubchart);
  224. $$.updateSvgSize();
  225. // Define regions
  226. main = $$.main = $$.svg.append("g").attr("transform", $$.getTranslate('main'));
  227. if ($$.initSubchart) { $$.initSubchart(); }
  228. if ($$.initTooltip) { $$.initTooltip(); }
  229. if ($$.initLegend) { $$.initLegend(); }
  230. if ($$.initTitle) { $$.initTitle(); }
  231. /*-- Main Region --*/
  232. // text when empty
  233. main.append("text")
  234. .attr("class", CLASS.text + ' ' + CLASS.empty)
  235. .attr("text-anchor", "middle") // horizontal centering of text at x position in all browsers.
  236. .attr("dominant-baseline", "middle"); // vertical centering of text at y position in all browsers, except IE.
  237. // Regions
  238. $$.initRegion();
  239. // Grids
  240. $$.initGrid();
  241. // Define g for chart area
  242. main.append('g')
  243. .attr("clip-path", $$.clipPath)
  244. .attr('class', CLASS.chart);
  245. // Grid lines
  246. if (config.grid_lines_front) { $$.initGridLines(); }
  247. // Cover whole with rects for events
  248. $$.initEventRect();
  249. // Define g for chart
  250. $$.initChartElements();
  251. // if zoom privileged, insert rect to forefront
  252. // TODO: is this needed?
  253. main.insert('rect', config.zoom_privileged ? null : 'g.' + CLASS.regions)
  254. .attr('class', CLASS.zoomRect)
  255. .attr('width', $$.width)
  256. .attr('height', $$.height)
  257. .style('opacity', 0)
  258. .on("dblclick.zoom", null);
  259. // Set default extent if defined
  260. if (config.axis_x_extent) { $$.brush.extent($$.getDefaultExtent()); }
  261. // Add Axis
  262. $$.axis.init();
  263. // Set targets
  264. $$.updateTargets($$.data.targets);
  265. // Draw with targets
  266. if (binding) {
  267. $$.updateDimension();
  268. $$.config.oninit.call($$);
  269. $$.redraw({
  270. withTransition: false,
  271. withTransform: true,
  272. withUpdateXDomain: true,
  273. withUpdateOrgXDomain: true,
  274. withTransitionForAxis: false
  275. });
  276. }
  277. // Bind resize event
  278. $$.bindResize();
  279. // export element of the chart
  280. $$.api.element = $$.selectChart.node();
  281. };
  282. c3_chart_internal_fn.smoothLines = function (el, type) {
  283. var $$ = this;
  284. if (type === 'grid') {
  285. el.each(function () {
  286. var g = $$.d3.select(this),
  287. x1 = g.attr('x1'),
  288. x2 = g.attr('x2'),
  289. y1 = g.attr('y1'),
  290. y2 = g.attr('y2');
  291. g.attr({
  292. 'x1': Math.ceil(x1),
  293. 'x2': Math.ceil(x2),
  294. 'y1': Math.ceil(y1),
  295. 'y2': Math.ceil(y2)
  296. });
  297. });
  298. }
  299. };
  300. c3_chart_internal_fn.updateSizes = function () {
  301. var $$ = this, config = $$.config;
  302. var legendHeight = $$.legend ? $$.getLegendHeight() : 0,
  303. legendWidth = $$.legend ? $$.getLegendWidth() : 0,
  304. legendHeightForBottom = $$.isLegendRight || $$.isLegendInset ? 0 : legendHeight,
  305. hasArc = $$.hasArcType(),
  306. xAxisHeight = config.axis_rotated || hasArc ? 0 : $$.getHorizontalAxisHeight('x'),
  307. subchartHeight = config.subchart_show && !hasArc ? (config.subchart_size_height + xAxisHeight) : 0;
  308. $$.currentWidth = $$.getCurrentWidth();
  309. $$.currentHeight = $$.getCurrentHeight();
  310. // for main
  311. $$.margin = config.axis_rotated ? {
  312. top: $$.getHorizontalAxisHeight('y2') + $$.getCurrentPaddingTop(),
  313. right: hasArc ? 0 : $$.getCurrentPaddingRight(),
  314. bottom: $$.getHorizontalAxisHeight('y') + legendHeightForBottom + $$.getCurrentPaddingBottom(),
  315. left: subchartHeight + (hasArc ? 0 : $$.getCurrentPaddingLeft())
  316. } : {
  317. top: 4 + $$.getCurrentPaddingTop(), // for top tick text
  318. right: hasArc ? 0 : $$.getCurrentPaddingRight(),
  319. bottom: xAxisHeight + subchartHeight + legendHeightForBottom + $$.getCurrentPaddingBottom(),
  320. left: hasArc ? 0 : $$.getCurrentPaddingLeft()
  321. };
  322. // for subchart
  323. $$.margin2 = config.axis_rotated ? {
  324. top: $$.margin.top,
  325. right: NaN,
  326. bottom: 20 + legendHeightForBottom,
  327. left: $$.rotated_padding_left
  328. } : {
  329. top: $$.currentHeight - subchartHeight - legendHeightForBottom,
  330. right: NaN,
  331. bottom: xAxisHeight + legendHeightForBottom,
  332. left: $$.margin.left
  333. };
  334. // for legend
  335. $$.margin3 = {
  336. top: 0,
  337. right: NaN,
  338. bottom: 0,
  339. left: 0
  340. };
  341. if ($$.updateSizeForLegend) { $$.updateSizeForLegend(legendHeight, legendWidth); }
  342. $$.width = $$.currentWidth - $$.margin.left - $$.margin.right;
  343. $$.height = $$.currentHeight - $$.margin.top - $$.margin.bottom;
  344. if ($$.width < 0) { $$.width = 0; }
  345. if ($$.height < 0) { $$.height = 0; }
  346. $$.width2 = config.axis_rotated ? $$.margin.left - $$.rotated_padding_left - $$.rotated_padding_right : $$.width;
  347. $$.height2 = config.axis_rotated ? $$.height : $$.currentHeight - $$.margin2.top - $$.margin2.bottom;
  348. if ($$.width2 < 0) { $$.width2 = 0; }
  349. if ($$.height2 < 0) { $$.height2 = 0; }
  350. // for arc
  351. $$.arcWidth = $$.width - ($$.isLegendRight ? legendWidth + 10 : 0);
  352. $$.arcHeight = $$.height - ($$.isLegendRight ? 0 : 10);
  353. if ($$.hasType('gauge') && !config.gauge_fullCircle) {
  354. $$.arcHeight += $$.height - $$.getGaugeLabelHeight();
  355. }
  356. if ($$.updateRadius) { $$.updateRadius(); }
  357. if ($$.isLegendRight && hasArc) {
  358. $$.margin3.left = $$.arcWidth / 2 + $$.radiusExpanded * 1.1;
  359. }
  360. };
  361. c3_chart_internal_fn.updateTargets = function (targets) {
  362. var $$ = this;
  363. /*-- Main --*/
  364. //-- Text --//
  365. $$.updateTargetsForText(targets);
  366. //-- Bar --//
  367. $$.updateTargetsForBar(targets);
  368. //-- Line --//
  369. $$.updateTargetsForLine(targets);
  370. //-- Arc --//
  371. if ($$.hasArcType() && $$.updateTargetsForArc) { $$.updateTargetsForArc(targets); }
  372. /*-- Sub --*/
  373. if ($$.updateTargetsForSubchart) { $$.updateTargetsForSubchart(targets); }
  374. // Fade-in each chart
  375. $$.showTargets();
  376. };
  377. c3_chart_internal_fn.showTargets = function () {
  378. var $$ = this;
  379. $$.svg.selectAll('.' + CLASS.target).filter(function (d) { return $$.isTargetToShow(d.id); })
  380. .transition().duration($$.config.transition_duration)
  381. .style("opacity", 1);
  382. };
  383. c3_chart_internal_fn.redraw = function (options, transitions) {
  384. var $$ = this, main = $$.main, d3 = $$.d3, config = $$.config;
  385. var areaIndices = $$.getShapeIndices($$.isAreaType), barIndices = $$.getShapeIndices($$.isBarType), lineIndices = $$.getShapeIndices($$.isLineType);
  386. var withY, withSubchart, withTransition, withTransitionForExit, withTransitionForAxis,
  387. withTransform, withUpdateXDomain, withUpdateOrgXDomain, withTrimXDomain, withLegend,
  388. withEventRect, withDimension, withUpdateXAxis;
  389. var hideAxis = $$.hasArcType();
  390. var drawArea, drawBar, drawLine, xForText, yForText;
  391. var duration, durationForExit, durationForAxis;
  392. var waitForDraw, flow;
  393. var targetsToShow = $$.filterTargetsToShow($$.data.targets), tickValues, i, intervalForCulling, xDomainForZoom;
  394. var xv = $$.xv.bind($$), cx, cy;
  395. options = options || {};
  396. withY = getOption(options, "withY", true);
  397. withSubchart = getOption(options, "withSubchart", true);
  398. withTransition = getOption(options, "withTransition", true);
  399. withTransform = getOption(options, "withTransform", false);
  400. withUpdateXDomain = getOption(options, "withUpdateXDomain", false);
  401. withUpdateOrgXDomain = getOption(options, "withUpdateOrgXDomain", false);
  402. withTrimXDomain = getOption(options, "withTrimXDomain", true);
  403. withUpdateXAxis = getOption(options, "withUpdateXAxis", withUpdateXDomain);
  404. withLegend = getOption(options, "withLegend", false);
  405. withEventRect = getOption(options, "withEventRect", true);
  406. withDimension = getOption(options, "withDimension", true);
  407. withTransitionForExit = getOption(options, "withTransitionForExit", withTransition);
  408. withTransitionForAxis = getOption(options, "withTransitionForAxis", withTransition);
  409. duration = withTransition ? config.transition_duration : 0;
  410. durationForExit = withTransitionForExit ? duration : 0;
  411. durationForAxis = withTransitionForAxis ? duration : 0;
  412. transitions = transitions || $$.axis.generateTransitions(durationForAxis);
  413. // update legend and transform each g
  414. if (withLegend && config.legend_show) {
  415. $$.updateLegend($$.mapToIds($$.data.targets), options, transitions);
  416. } else if (withDimension) {
  417. // need to update dimension (e.g. axis.y.tick.values) because y tick values should change
  418. // no need to update axis in it because they will be updated in redraw()
  419. $$.updateDimension(true);
  420. }
  421. // MEMO: needed for grids calculation
  422. if ($$.isCategorized() && targetsToShow.length === 0) {
  423. $$.x.domain([0, $$.axes.x.selectAll('.tick').size()]);
  424. }
  425. if (targetsToShow.length) {
  426. $$.updateXDomain(targetsToShow, withUpdateXDomain, withUpdateOrgXDomain, withTrimXDomain);
  427. if (!config.axis_x_tick_values) {
  428. tickValues = $$.axis.updateXAxisTickValues(targetsToShow);
  429. }
  430. } else {
  431. $$.xAxis.tickValues([]);
  432. $$.subXAxis.tickValues([]);
  433. }
  434. if (config.zoom_rescale && !options.flow) {
  435. xDomainForZoom = $$.x.orgDomain();
  436. }
  437. $$.y.domain($$.getYDomain(targetsToShow, 'y', xDomainForZoom));
  438. $$.y2.domain($$.getYDomain(targetsToShow, 'y2', xDomainForZoom));
  439. if (!config.axis_y_tick_values && config.axis_y_tick_count) {
  440. $$.yAxis.tickValues($$.axis.generateTickValues($$.y.domain(), config.axis_y_tick_count));
  441. }
  442. if (!config.axis_y2_tick_values && config.axis_y2_tick_count) {
  443. $$.y2Axis.tickValues($$.axis.generateTickValues($$.y2.domain(), config.axis_y2_tick_count));
  444. }
  445. // axes
  446. $$.axis.redraw(transitions, hideAxis);
  447. // Update axis label
  448. $$.axis.updateLabels(withTransition);
  449. // show/hide if manual culling needed
  450. if ((withUpdateXDomain || withUpdateXAxis) && targetsToShow.length) {
  451. if (config.axis_x_tick_culling && tickValues) {
  452. for (i = 1; i < tickValues.length; i++) {
  453. if (tickValues.length / i < config.axis_x_tick_culling_max) {
  454. intervalForCulling = i;
  455. break;
  456. }
  457. }
  458. $$.svg.selectAll('.' + CLASS.axisX + ' .tick text').each(function (e) {
  459. var index = tickValues.indexOf(e);
  460. if (index >= 0) {
  461. d3.select(this).style('display', index % intervalForCulling ? 'none' : 'block');
  462. }
  463. });
  464. } else {
  465. $$.svg.selectAll('.' + CLASS.axisX + ' .tick text').style('display', 'block');
  466. }
  467. }
  468. // setup drawer - MEMO: these must be called after axis updated
  469. drawArea = $$.generateDrawArea ? $$.generateDrawArea(areaIndices, false) : undefined;
  470. drawBar = $$.generateDrawBar ? $$.generateDrawBar(barIndices) : undefined;
  471. drawLine = $$.generateDrawLine ? $$.generateDrawLine(lineIndices, false) : undefined;
  472. xForText = $$.generateXYForText(areaIndices, barIndices, lineIndices, true);
  473. yForText = $$.generateXYForText(areaIndices, barIndices, lineIndices, false);
  474. // Update sub domain
  475. if (withY) {
  476. $$.subY.domain($$.getYDomain(targetsToShow, 'y'));
  477. $$.subY2.domain($$.getYDomain(targetsToShow, 'y2'));
  478. }
  479. // xgrid focus
  480. $$.updateXgridFocus();
  481. // Data empty label positioning and text.
  482. main.select("text." + CLASS.text + '.' + CLASS.empty)
  483. .attr("x", $$.width / 2)
  484. .attr("y", $$.height / 2)
  485. .text(config.data_empty_label_text)
  486. .transition()
  487. .style('opacity', targetsToShow.length ? 0 : 1);
  488. // grid
  489. $$.updateGrid(duration);
  490. // rect for regions
  491. $$.updateRegion(duration);
  492. // bars
  493. $$.updateBar(durationForExit);
  494. // lines, areas and cricles
  495. $$.updateLine(durationForExit);
  496. $$.updateArea(durationForExit);
  497. $$.updateCircle();
  498. // text
  499. if ($$.hasDataLabel()) {
  500. $$.updateText(durationForExit);
  501. }
  502. // title
  503. if ($$.redrawTitle) { $$.redrawTitle(); }
  504. // arc
  505. if ($$.redrawArc) { $$.redrawArc(duration, durationForExit, withTransform); }
  506. // subchart
  507. if ($$.redrawSubchart) {
  508. $$.redrawSubchart(withSubchart, transitions, duration, durationForExit, areaIndices, barIndices, lineIndices);
  509. }
  510. // circles for select
  511. main.selectAll('.' + CLASS.selectedCircles)
  512. .filter($$.isBarType.bind($$))
  513. .selectAll('circle')
  514. .remove();
  515. // event rects will redrawn when flow called
  516. if (config.interaction_enabled && !options.flow && withEventRect) {
  517. $$.redrawEventRect();
  518. if ($$.updateZoom) { $$.updateZoom(); }
  519. }
  520. // update circleY based on updated parameters
  521. $$.updateCircleY();
  522. // generate circle x/y functions depending on updated params
  523. cx = ($$.config.axis_rotated ? $$.circleY : $$.circleX).bind($$);
  524. cy = ($$.config.axis_rotated ? $$.circleX : $$.circleY).bind($$);
  525. if (options.flow) {
  526. flow = $$.generateFlow({
  527. targets: targetsToShow,
  528. flow: options.flow,
  529. duration: options.flow.duration,
  530. drawBar: drawBar,
  531. drawLine: drawLine,
  532. drawArea: drawArea,
  533. cx: cx,
  534. cy: cy,
  535. xv: xv,
  536. xForText: xForText,
  537. yForText: yForText
  538. });
  539. }
  540. if ((duration || flow) && $$.isTabVisible()) { // Only use transition if tab visible. See #938.
  541. // transition should be derived from one transition
  542. d3.transition().duration(duration).each(function () {
  543. var transitionsToWait = [];
  544. // redraw and gather transitions
  545. [
  546. $$.redrawBar(drawBar, true),
  547. $$.redrawLine(drawLine, true),
  548. $$.redrawArea(drawArea, true),
  549. $$.redrawCircle(cx, cy, true),
  550. $$.redrawText(xForText, yForText, options.flow, true),
  551. $$.redrawRegion(true),
  552. $$.redrawGrid(true),
  553. ].forEach(function (transitions) {
  554. transitions.forEach(function (transition) {
  555. transitionsToWait.push(transition);
  556. });
  557. });
  558. // Wait for end of transitions to call flow and onrendered callback
  559. waitForDraw = $$.generateWait();
  560. transitionsToWait.forEach(function (t) {
  561. waitForDraw.add(t);
  562. });
  563. })
  564. .call(waitForDraw, function () {
  565. if (flow) {
  566. flow();
  567. }
  568. if (config.onrendered) {
  569. config.onrendered.call($$);
  570. }
  571. });
  572. }
  573. else {
  574. $$.redrawBar(drawBar);
  575. $$.redrawLine(drawLine);
  576. $$.redrawArea(drawArea);
  577. $$.redrawCircle(cx, cy);
  578. $$.redrawText(xForText, yForText, options.flow);
  579. $$.redrawRegion();
  580. $$.redrawGrid();
  581. if (config.onrendered) {
  582. config.onrendered.call($$);
  583. }
  584. }
  585. // update fadein condition
  586. $$.mapToIds($$.data.targets).forEach(function (id) {
  587. $$.withoutFadeIn[id] = true;
  588. });
  589. };
  590. c3_chart_internal_fn.updateAndRedraw = function (options) {
  591. var $$ = this, config = $$.config, transitions;
  592. options = options || {};
  593. // same with redraw
  594. options.withTransition = getOption(options, "withTransition", true);
  595. options.withTransform = getOption(options, "withTransform", false);
  596. options.withLegend = getOption(options, "withLegend", false);
  597. // NOT same with redraw
  598. options.withUpdateXDomain = true;
  599. options.withUpdateOrgXDomain = true;
  600. options.withTransitionForExit = false;
  601. options.withTransitionForTransform = getOption(options, "withTransitionForTransform", options.withTransition);
  602. // MEMO: this needs to be called before updateLegend and it means this ALWAYS needs to be called)
  603. $$.updateSizes();
  604. // MEMO: called in updateLegend in redraw if withLegend
  605. if (!(options.withLegend && config.legend_show)) {
  606. transitions = $$.axis.generateTransitions(options.withTransitionForAxis ? config.transition_duration : 0);
  607. // Update scales
  608. $$.updateScales();
  609. $$.updateSvgSize();
  610. // Update g positions
  611. $$.transformAll(options.withTransitionForTransform, transitions);
  612. }
  613. // Draw with new sizes & scales
  614. $$.redraw(options, transitions);
  615. };
  616. c3_chart_internal_fn.redrawWithoutRescale = function () {
  617. this.redraw({
  618. withY: false,
  619. withSubchart: false,
  620. withEventRect: false,
  621. withTransitionForAxis: false
  622. });
  623. };
  624. c3_chart_internal_fn.isTimeSeries = function () {
  625. return this.config.axis_x_type === 'timeseries';
  626. };
  627. c3_chart_internal_fn.isCategorized = function () {
  628. return this.config.axis_x_type.indexOf('categor') >= 0;
  629. };
  630. c3_chart_internal_fn.isCustomX = function () {
  631. var $$ = this, config = $$.config;
  632. return !$$.isTimeSeries() && (config.data_x || notEmpty(config.data_xs));
  633. };
  634. c3_chart_internal_fn.isTimeSeriesY = function () {
  635. return this.config.axis_y_type === 'timeseries';
  636. };
  637. c3_chart_internal_fn.getTranslate = function (target) {
  638. var $$ = this, config = $$.config, x, y;
  639. if (target === 'main') {
  640. x = asHalfPixel($$.margin.left);
  641. y = asHalfPixel($$.margin.top);
  642. } else if (target === 'context') {
  643. x = asHalfPixel($$.margin2.left);
  644. y = asHalfPixel($$.margin2.top);
  645. } else if (target === 'legend') {
  646. x = $$.margin3.left;
  647. y = $$.margin3.top;
  648. } else if (target === 'x') {
  649. x = 0;
  650. y = config.axis_rotated ? 0 : $$.height;
  651. } else if (target === 'y') {
  652. x = 0;
  653. y = config.axis_rotated ? $$.height : 0;
  654. } else if (target === 'y2') {
  655. x = config.axis_rotated ? 0 : $$.width;
  656. y = config.axis_rotated ? 1 : 0;
  657. } else if (target === 'subx') {
  658. x = 0;
  659. y = config.axis_rotated ? 0 : $$.height2;
  660. } else if (target === 'arc') {
  661. x = $$.arcWidth / 2;
  662. y = $$.arcHeight / 2;
  663. }
  664. return "translate(" + x + "," + y + ")";
  665. };
  666. c3_chart_internal_fn.initialOpacity = function (d) {
  667. return d.value !== null && this.withoutFadeIn[d.id] ? 1 : 0;
  668. };
  669. c3_chart_internal_fn.initialOpacityForCircle = function (d) {
  670. return d.value !== null && this.withoutFadeIn[d.id] ? this.opacityForCircle(d) : 0;
  671. };
  672. c3_chart_internal_fn.opacityForCircle = function (d) {
  673. var opacity = this.config.point_show ? 1 : 0;
  674. return isValue(d.value) ? (this.isScatterType(d) ? 0.5 : opacity) : 0;
  675. };
  676. c3_chart_internal_fn.opacityForText = function () {
  677. return this.hasDataLabel() ? 1 : 0;
  678. };
  679. c3_chart_internal_fn.xx = function (d) {
  680. return d ? this.x(d.x) : null;
  681. };
  682. c3_chart_internal_fn.xv = function (d) {
  683. var $$ = this, value = d.value;
  684. if ($$.isTimeSeries()) {
  685. value = $$.parseDate(d.value);
  686. }
  687. else if ($$.isCategorized() && typeof d.value === 'string') {
  688. value = $$.config.axis_x_categories.indexOf(d.value);
  689. }
  690. return Math.ceil($$.x(value));
  691. };
  692. c3_chart_internal_fn.yv = function (d) {
  693. var $$ = this,
  694. yScale = d.axis && d.axis === 'y2' ? $$.y2 : $$.y;
  695. return Math.ceil(yScale(d.value));
  696. };
  697. c3_chart_internal_fn.subxx = function (d) {
  698. return d ? this.subX(d.x) : null;
  699. };
  700. c3_chart_internal_fn.transformMain = function (withTransition, transitions) {
  701. var $$ = this,
  702. xAxis, yAxis, y2Axis;
  703. if (transitions && transitions.axisX) {
  704. xAxis = transitions.axisX;
  705. } else {
  706. xAxis = $$.main.select('.' + CLASS.axisX);
  707. if (withTransition) { xAxis = xAxis.transition(); }
  708. }
  709. if (transitions && transitions.axisY) {
  710. yAxis = transitions.axisY;
  711. } else {
  712. yAxis = $$.main.select('.' + CLASS.axisY);
  713. if (withTransition) { yAxis = yAxis.transition(); }
  714. }
  715. if (transitions && transitions.axisY2) {
  716. y2Axis = transitions.axisY2;
  717. } else {
  718. y2Axis = $$.main.select('.' + CLASS.axisY2);
  719. if (withTransition) { y2Axis = y2Axis.transition(); }
  720. }
  721. (withTransition ? $$.main.transition() : $$.main).attr("transform", $$.getTranslate('main'));
  722. xAxis.attr("transform", $$.getTranslate('x'));
  723. yAxis.attr("transform", $$.getTranslate('y'));
  724. y2Axis.attr("transform", $$.getTranslate('y2'));
  725. $$.main.select('.' + CLASS.chartArcs).attr("transform", $$.getTranslate('arc'));
  726. };
  727. c3_chart_internal_fn.transformAll = function (withTransition, transitions) {
  728. var $$ = this;
  729. $$.transformMain(withTransition, transitions);
  730. if ($$.config.subchart_show) { $$.transformContext(withTransition, transitions); }
  731. if ($$.legend) { $$.transformLegend(withTransition); }
  732. };
  733. c3_chart_internal_fn.updateSvgSize = function () {
  734. var $$ = this,
  735. brush = $$.svg.select(".c3-brush .background");
  736. $$.svg.attr('width', $$.currentWidth).attr('height', $$.currentHeight);
  737. $$.svg.selectAll(['#' + $$.clipId, '#' + $$.clipIdForGrid]).select('rect')
  738. .attr('width', $$.width)
  739. .attr('height', $$.height);
  740. $$.svg.select('#' + $$.clipIdForXAxis).select('rect')
  741. .attr('x', $$.getXAxisClipX.bind($$))
  742. .attr('y', $$.getXAxisClipY.bind($$))
  743. .attr('width', $$.getXAxisClipWidth.bind($$))
  744. .attr('height', $$.getXAxisClipHeight.bind($$));
  745. $$.svg.select('#' + $$.clipIdForYAxis).select('rect')
  746. .attr('x', $$.getYAxisClipX.bind($$))
  747. .attr('y', $$.getYAxisClipY.bind($$))
  748. .attr('width', $$.getYAxisClipWidth.bind($$))
  749. .attr('height', $$.getYAxisClipHeight.bind($$));
  750. $$.svg.select('#' + $$.clipIdForSubchart).select('rect')
  751. .attr('width', $$.width)
  752. .attr('height', brush.size() ? brush.attr('height') : 0);
  753. $$.svg.select('.' + CLASS.zoomRect)
  754. .attr('width', $$.width)
  755. .attr('height', $$.height);
  756. // MEMO: parent div's height will be bigger than svg when <!DOCTYPE html>
  757. $$.selectChart.style('max-height', $$.currentHeight + "px");
  758. };
  759. c3_chart_internal_fn.updateDimension = function (withoutAxis) {
  760. var $$ = this;
  761. if (!withoutAxis) {
  762. if ($$.config.axis_rotated) {
  763. $$.axes.x.call($$.xAxis);
  764. $$.axes.subx.call($$.subXAxis);
  765. } else {
  766. $$.axes.y.call($$.yAxis);
  767. $$.axes.y2.call($$.y2Axis);
  768. }
  769. }
  770. $$.updateSizes();
  771. $$.updateScales();
  772. $$.updateSvgSize();
  773. $$.transformAll(false);
  774. };
  775. c3_chart_internal_fn.observeInserted = function (selection) {
  776. var $$ = this, observer;
  777. if (typeof MutationObserver === 'undefined') {
  778. window.console.error("MutationObserver not defined.");
  779. return;
  780. }
  781. observer= new MutationObserver(function (mutations) {
  782. mutations.forEach(function (mutation) {
  783. if (mutation.type === 'childList' && mutation.previousSibling) {
  784. observer.disconnect();
  785. // need to wait for completion of load because size calculation requires the actual sizes determined after that completion
  786. $$.intervalForObserveInserted = window.setInterval(function () {
  787. // parentNode will NOT be null when completed
  788. if (selection.node().parentNode) {
  789. window.clearInterval($$.intervalForObserveInserted);
  790. $$.updateDimension();
  791. if ($$.brush) { $$.brush.update(); }
  792. $$.config.oninit.call($$);
  793. $$.redraw({
  794. withTransform: true,
  795. withUpdateXDomain: true,
  796. withUpdateOrgXDomain: true,
  797. withTransition: false,
  798. withTransitionForTransform: false,
  799. withLegend: true
  800. });
  801. selection.transition().style('opacity', 1);
  802. }
  803. }, 10);
  804. }
  805. });
  806. });
  807. observer.observe(selection.node(), {attributes: true, childList: true, characterData: true});
  808. };
  809. c3_chart_internal_fn.bindResize = function () {
  810. var $$ = this, config = $$.config;
  811. $$.resizeFunction = $$.generateResize();
  812. $$.resizeFunction.add(function () {
  813. config.onresize.call($$);
  814. });
  815. if (config.resize_auto) {
  816. $$.resizeFunction.add(function () {
  817. if ($$.resizeTimeout !== undefined) {
  818. window.clearTimeout($$.resizeTimeout);
  819. }
  820. $$.resizeTimeout = window.setTimeout(function () {
  821. delete $$.resizeTimeout;
  822. $$.api.flush();
  823. }, 100);
  824. });
  825. }
  826. $$.resizeFunction.add(function () {
  827. config.onresized.call($$);
  828. });
  829. if (window.attachEvent) {
  830. window.attachEvent('onresize', $$.resizeFunction);
  831. } else if (window.addEventListener) {
  832. window.addEventListener('resize', $$.resizeFunction, false);
  833. } else {
  834. // fallback to this, if this is a very old browser
  835. var wrapper = window.onresize;
  836. if (!wrapper) {
  837. // create a wrapper that will call all charts
  838. wrapper = $$.generateResize();
  839. } else if (!wrapper.add || !wrapper.remove) {
  840. // there is already a handler registered, make sure we call it too
  841. wrapper = $$.generateResize();
  842. wrapper.add(window.onresize);
  843. }
  844. // add this graph to the wrapper, we will be removed if the user calls destroy
  845. wrapper.add($$.resizeFunction);
  846. window.onresize = wrapper;
  847. }
  848. };
  849. c3_chart_internal_fn.generateResize = function () {
  850. var resizeFunctions = [];
  851. function callResizeFunctions() {
  852. resizeFunctions.forEach(function (f) {
  853. f();
  854. });
  855. }
  856. callResizeFunctions.add = function (f) {
  857. resizeFunctions.push(f);
  858. };
  859. callResizeFunctions.remove = function (f) {
  860. for (var i = 0; i < resizeFunctions.length; i++) {
  861. if (resizeFunctions[i] === f) {
  862. resizeFunctions.splice(i, 1);
  863. break;
  864. }
  865. }
  866. };
  867. return callResizeFunctions;
  868. };
  869. c3_chart_internal_fn.endall = function (transition, callback) {
  870. var n = 0;
  871. transition
  872. .each(function () { ++n; })
  873. .each("end", function () {
  874. if (!--n) { callback.apply(this, arguments); }
  875. });
  876. };
  877. c3_chart_internal_fn.generateWait = function () {
  878. var transitionsToWait = [],
  879. f = function (transition, callback) {
  880. var timer = setInterval(function () {
  881. var done = 0;
  882. transitionsToWait.forEach(function (t) {
  883. if (t.empty()) {
  884. done += 1;
  885. return;
  886. }
  887. try {
  888. t.transition();
  889. } catch (e) {
  890. done += 1;
  891. }
  892. });
  893. if (done === transitionsToWait.length) {
  894. clearInterval(timer);
  895. if (callback) { callback(); }
  896. }
  897. }, 10);
  898. };
  899. f.add = function (transition) {
  900. transitionsToWait.push(transition);
  901. };
  902. return f;
  903. };
  904. c3_chart_internal_fn.parseDate = function (date) {
  905. var $$ = this, parsedDate;
  906. if (date instanceof Date) {
  907. parsedDate = date;
  908. } else if (typeof date === 'string') {
  909. parsedDate = $$.dataTimeFormat($$.config.data_xFormat).parse(date);
  910. } else if (typeof date === 'number' && !isNaN(date)) {
  911. parsedDate = new Date(+date);
  912. }
  913. if (!parsedDate || isNaN(+parsedDate)) {
  914. window.console.error("Failed to parse x '" + date + "' to Date object");
  915. }
  916. return parsedDate;
  917. };
  918. c3_chart_internal_fn.isTabVisible = function () {
  919. var hidden;
  920. if (typeof document.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support
  921. hidden = "hidden";
  922. } else if (typeof document.mozHidden !== "undefined") {
  923. hidden = "mozHidden";
  924. } else if (typeof document.msHidden !== "undefined") {
  925. hidden = "msHidden";
  926. } else if (typeof document.webkitHidden !== "undefined") {
  927. hidden = "webkitHidden";
  928. }
  929. return document[hidden] ? false : true;
  930. };
  931. c3_chart_internal_fn.getDefaultConfig = function () {
  932. var config = {
  933. bindto: '#chart',
  934. svg_classname: undefined,
  935. size_width: undefined,
  936. size_height: undefined,
  937. padding_left: undefined,
  938. padding_right: undefined,
  939. padding_top: undefined,
  940. padding_bottom: undefined,
  941. resize_auto: true,
  942. zoom_enabled: false,
  943. zoom_extent: undefined,
  944. zoom_privileged: false,
  945. zoom_rescale: false,
  946. zoom_onzoom: function () {},
  947. zoom_onzoomstart: function () {},
  948. zoom_onzoomend: function () {},
  949. zoom_x_min: undefined,
  950. zoom_x_max: undefined,
  951. interaction_brighten: true,
  952. interaction_enabled: true,
  953. onmouseover: function () {},
  954. onmouseout: function () {},
  955. onresize: function () {},
  956. onresized: function () {},
  957. oninit: function () {},
  958. onrendered: function () {},
  959. transition_duration: 350,
  960. data_x: undefined,
  961. data_xs: {},
  962. data_xFormat: '%Y-%m-%d',
  963. data_xLocaltime: true,
  964. data_xSort: true,
  965. data_idConverter: function (id) { return id; },
  966. data_names: {},
  967. data_classes: {},
  968. data_groups: [],
  969. data_axes: {},
  970. data_type: undefined,
  971. data_types: {},
  972. data_labels: {},
  973. data_order: 'desc',
  974. data_regions: {},
  975. data_color: undefined,
  976. data_colors: {},
  977. data_hide: false,
  978. data_filter: undefined,
  979. data_selection_enabled: false,
  980. data_selection_grouped: false,
  981. data_selection_isselectable: function () { return true; },
  982. data_selection_multiple: true,
  983. data_selection_draggable: false,
  984. data_onclick: function () {},
  985. data_onmouseover: function () {},
  986. data_onmouseout: function () {},
  987. data_onselected: function () {},
  988. data_onunselected: function () {},
  989. data_url: undefined,
  990. data_headers: undefined,
  991. data_json: undefined,
  992. data_rows: undefined,
  993. data_columns: undefined,
  994. data_mimeType: undefined,
  995. data_keys: undefined,
  996. // configuration for no plot-able data supplied.
  997. data_empty_label_text: "",
  998. // subchart
  999. subchart_show: false,
  1000. subchart_size_height: 60,
  1001. subchart_axis_x_show: true,
  1002. subchart_onbrush: function () {},
  1003. // color
  1004. color_pattern: [],
  1005. color_threshold: {},
  1006. // legend
  1007. legend_show: true,
  1008. legend_hide: false,
  1009. legend_position: 'bottom',
  1010. legend_inset_anchor: 'top-left',
  1011. legend_inset_x: 10,
  1012. legend_inset_y: 0,
  1013. legend_inset_step: undefined,
  1014. legend_item_onclick: undefined,
  1015. legend_item_onmouseover: undefined,
  1016. legend_item_onmouseout: undefined,
  1017. legend_equally: false,
  1018. legend_padding: 0,
  1019. legend_item_tile_width: 10,
  1020. legend_item_tile_height: 10,
  1021. // axis
  1022. axis_rotated: false,
  1023. axis_x_show: true,
  1024. axis_x_type: 'indexed',
  1025. axis_x_localtime: true,
  1026. axis_x_categories: [],
  1027. axis_x_tick_centered: false,
  1028. axis_x_tick_format: undefined,
  1029. axis_x_tick_culling: {},
  1030. axis_x_tick_culling_max: 10,
  1031. axis_x_tick_count: undefined,
  1032. axis_x_tick_fit: true,
  1033. axis_x_tick_values: null,
  1034. axis_x_tick_rotate: 0,
  1035. axis_x_tick_outer: true,
  1036. axis_x_tick_multiline: true,
  1037. axis_x_tick_width: null,
  1038. axis_x_max: undefined,
  1039. axis_x_min: undefined,
  1040. axis_x_padding: {},
  1041. axis_x_height: undefined,
  1042. axis_x_extent: undefined,
  1043. axis_x_label: {},
  1044. axis_y_show: true,
  1045. axis_y_type: undefined,
  1046. axis_y_max: undefined,
  1047. axis_y_min: undefined,
  1048. axis_y_inverted: false,
  1049. axis_y_center: undefined,
  1050. axis_y_inner: undefined,
  1051. axis_y_label: {},
  1052. axis_y_tick_format: undefined,
  1053. axis_y_tick_outer: true,
  1054. axis_y_tick_values: null,
  1055. axis_y_tick_rotate: 0,
  1056. axis_y_tick_count: undefined,
  1057. axis_y_tick_time_value: undefined,
  1058. axis_y_tick_time_interval: undefined,
  1059. axis_y_padding: {},
  1060. axis_y_default: undefined,
  1061. axis_y2_show: false,
  1062. axis_y2_max: undefined,
  1063. axis_y2_min: undefined,
  1064. axis_y2_inverted: false,
  1065. axis_y2_center: undefined,
  1066. axis_y2_inner: undefined,
  1067. axis_y2_label: {},
  1068. axis_y2_tick_format: undefined,
  1069. axis_y2_tick_outer: true,
  1070. axis_y2_tick_values: null,
  1071. axis_y2_tick_count: undefined,
  1072. axis_y2_padding: {},
  1073. axis_y2_default: undefined,
  1074. // grid
  1075. grid_x_show: false,
  1076. grid_x_type: 'tick',
  1077. grid_x_lines: [],
  1078. grid_y_show: false,
  1079. // not used
  1080. // grid_y_type: 'tick',
  1081. grid_y_lines: [],
  1082. grid_y_ticks: 10,
  1083. grid_focus_show: true,
  1084. grid_lines_front: true,
  1085. // point - point of each data
  1086. point_show: true,
  1087. point_r: 2.5,
  1088. point_sensitivity: 10,
  1089. point_focus_expand_enabled: true,
  1090. point_focus_expand_r: undefined,
  1091. point_select_r: undefined,
  1092. // line
  1093. line_connectNull: false,
  1094. line_step_type: 'step',
  1095. // bar
  1096. bar_width: undefined,
  1097. bar_width_ratio: 0.6,
  1098. bar_width_max: undefined,
  1099. bar_zerobased: true,
  1100. // area
  1101. area_zerobased: true,
  1102. area_above: false,
  1103. // pie
  1104. pie_label_show: true,
  1105. pie_label_format: undefined,
  1106. pie_label_threshold: 0.05,
  1107. pie_label_ratio: undefined,
  1108. pie_expand: {},
  1109. pie_expand_duration: 50,
  1110. // gauge
  1111. gauge_fullCircle: false,
  1112. gauge_label_show: true,
  1113. gauge_label_format: undefined,
  1114. gauge_min: 0,
  1115. gauge_max: 100,
  1116. gauge_startingAngle: -1 * Math.PI/2,
  1117. gauge_units: undefined,
  1118. gauge_width: undefined,
  1119. gauge_expand: {},
  1120. gauge_expand_duration: 50,
  1121. // donut
  1122. donut_label_show: true,
  1123. donut_label_format: undefined,
  1124. donut_label_threshold: 0.05,
  1125. donut_label_ratio: undefined,
  1126. donut_width: undefined,
  1127. donut_title: "",
  1128. donut_expand: {},
  1129. donut_expand_duration: 50,
  1130. // spline
  1131. spline_interpolation_type: 'cardinal',
  1132. // region - region to change style
  1133. regions: [],
  1134. // tooltip - show when mouseover on each data
  1135. tooltip_show: true,
  1136. tooltip_grouped: true,
  1137. tooltip_format_title: undefined,
  1138. tooltip_format_name: undefined,
  1139. tooltip_format_value: undefined,
  1140. tooltip_position: undefined,
  1141. tooltip_contents: function (d, defaultTitleFormat, defaultValueFormat, color) {
  1142. return this.getTooltipContent ? this.getTooltipContent(d, defaultTitleFormat, defaultValueFormat, color) : '';
  1143. },
  1144. tooltip_init_show: false,
  1145. tooltip_init_x: 0,
  1146. tooltip_init_position: {top: '0px', left: '50px'},
  1147. tooltip_onshow: function () {},
  1148. tooltip_onhide: function () {},
  1149. // title
  1150. title_text: undefined,
  1151. title_padding: {
  1152. top: 0,
  1153. right: 0,
  1154. bottom: 0,
  1155. left: 0
  1156. },
  1157. title_position: 'top-center',
  1158. };
  1159. Object.keys(this.additionalConfig).forEach(function (key) {
  1160. config[key] = this.additionalConfig[key];
  1161. }, this);
  1162. return config;
  1163. };
  1164. c3_chart_internal_fn.additionalConfig = {};
  1165. c3_chart_internal_fn.loadConfig = function (config) {
  1166. var this_config = this.config, target, keys, read;
  1167. function find() {
  1168. var key = keys.shift();
  1169. // console.log("key =>", key, ", target =>", target);
  1170. if (key && target && typeof target === 'object' && key in target) {
  1171. target = target[key];
  1172. return find();
  1173. }
  1174. else if (!key) {
  1175. return target;
  1176. }
  1177. else {
  1178. return undefined;
  1179. }
  1180. }
  1181. Object.keys(this_config).forEach(function (key) {
  1182. target = config;
  1183. keys = key.split('_');
  1184. read = find();
  1185. // console.log("CONFIG : ", key, read);
  1186. if (isDefined(read)) {
  1187. this_config[key] = read;
  1188. }
  1189. });
  1190. };
  1191. c3_chart_internal_fn.getScale = function (min, max, forTimeseries) {
  1192. return (forTimeseries ? this.d3.time.scale() : this.d3.scale.linear()).range([min, max]);
  1193. };
  1194. c3_chart_internal_fn.getX = function (min, max, domain, offset) {
  1195. var $$ = this,
  1196. scale = $$.getScale(min, max, $$.isTimeSeries()),
  1197. _scale = domain ? scale.domain(domain) : scale, key;
  1198. // Define customized scale if categorized axis
  1199. if ($$.isCategorized()) {
  1200. offset = offset || function () { return 0; };
  1201. scale = function (d, raw) {
  1202. var v = _scale(d) + offset(d);
  1203. return raw ? v : Math.ceil(v);
  1204. };
  1205. } else {
  1206. scale = function (d, raw) {
  1207. var v = _scale(d);
  1208. return raw ? v : Math.ceil(v);
  1209. };
  1210. }
  1211. // define functions
  1212. for (key in _scale) {
  1213. scale[key] = _scale[key];
  1214. }
  1215. scale.orgDomain = function () {
  1216. return _scale.domain();
  1217. };
  1218. // define custom domain() for categorized axis
  1219. if ($$.isCategorized()) {
  1220. scale.domain = function (domain) {
  1221. if (!arguments.length) {
  1222. domain = this.orgDomain();
  1223. return [domain[0], domain[1] + 1];
  1224. }
  1225. _scale.domain(domain);
  1226. return scale;
  1227. };
  1228. }
  1229. return scale;
  1230. };
  1231. c3_chart_internal_fn.getY = function (min, max, domain) {
  1232. var scale = this.getScale(min, max, this.isTimeSeriesY());
  1233. if (domain) { scale.domain(domain); }
  1234. return scale;
  1235. };
  1236. c3_chart_internal_fn.getYScale = function (id) {
  1237. return this.axis.getId(id) === 'y2' ? this.y2 : this.y;
  1238. };
  1239. c3_chart_internal_fn.getSubYScale = function (id) {
  1240. return this.axis.getId(id) === 'y2' ? this.subY2 : this.subY;
  1241. };
  1242. c3_chart_internal_fn.updateScales = function () {
  1243. var $$ = this, config = $$.config,
  1244. forInit = !$$.x;
  1245. // update edges
  1246. $$.xMin = config.axis_rotated ? 1 : 0;
  1247. $$.xMax = config.axis_rotated ? $$.height : $$.width;
  1248. $$.yMin = config.axis_rotated ? 0 : $$.height;
  1249. $$.yMax = config.axis_rotated ? $$.width : 1;
  1250. $$.subXMin = $$.xMin;
  1251. $$.subXMax = $$.xMax;
  1252. $$.subYMin = config.axis_rotated ? 0 : $$.height2;
  1253. $$.subYMax = config.axis_rotated ? $$.width2 : 1;
  1254. // update scales
  1255. $$.x = $$.getX($$.xMin, $$.xMax, forInit ? undefined : $$.x.orgDomain(), function () { return $$.xAxis.tickOffset(); });
  1256. $$.y = $$.getY($$.yMin, $$.yMax, forInit ? config.axis_y_default : $$.y.domain());
  1257. $$.y2 = $$.getY($$.yMin, $$.yMax, forInit ? config.axis_y2_default : $$.y2.domain());
  1258. $$.subX = $$.getX($$.xMin, $$.xMax, $$.orgXDomain, function (d) { return d % 1 ? 0 : $$.subXAxis.tickOffset(); });
  1259. $$.subY = $$.getY($$.subYMin, $$.subYMax, forInit ? config.axis_y_default : $$.subY.domain());
  1260. $$.subY2 = $$.getY($$.subYMin, $$.subYMax, forInit ? config.axis_y2_default : $$.subY2.domain());
  1261. // update axes
  1262. $$.xAxisTickFormat = $$.axis.getXAxisTickFormat();
  1263. $$.xAxisTickValues = $$.axis.getXAxisTickValues();
  1264. $$.yAxisTickValues = $$.axis.getYAxisTickValues();
  1265. $$.y2AxisTickValues = $$.axis.getY2AxisTickValues();
  1266. $$.xAxis = $$.axis.getXAxis($$.x, $$.xOrient, $$.xAxisTickFormat, $$.xAxisTickValues, config.axis_x_tick_outer);
  1267. $$.subXAxis = $$.axis.getXAxis($$.subX, $$.subXOrient, $$.xAxisTickFormat, $$.xAxisTickValues, config.axis_x_tick_outer);
  1268. $$.yAxis = $$.axis.getYAxis($$.y, $$.yOrient, config.axis_y_tick_format, $$.yAxisTickValues, config.axis_y_tick_outer);
  1269. $$.y2Axis = $$.axis.getYAxis($$.y2, $$.y2Orient, config.axis_y2_tick_format, $$.y2AxisTickValues, config.axis_y2_tick_outer);
  1270. // Set initialized scales to brush and zoom
  1271. if (!forInit) {
  1272. if ($$.brush) { $$.brush.scale($$.subX); }
  1273. if (config.zoom_enabled) { $$.zoom.scale($$.x); }
  1274. }
  1275. // update for arc
  1276. if ($$.updateArc) { $$.updateArc(); }
  1277. };
  1278. c3_chart_internal_fn.getYDomainMin = function (targets) {
  1279. var $$ = this, config = $$.config,
  1280. ids = $$.mapToIds(targets), ys = $$.getValuesAsIdKeyed(targets),
  1281. j, k, baseId, idsInGroup, id, hasNegativeValue;
  1282. if (config.data_groups.length > 0) {
  1283. hasNegativeValue = $$.hasNegativeValueInTargets(targets);
  1284. for (j = 0; j < config.data_groups.length; j++) {
  1285. // Determine baseId
  1286. idsInGroup = config.data_groups[j].filter(function (id) { return ids.indexOf(id) >= 0; });
  1287. if (idsInGroup.length === 0) { continue; }
  1288. baseId = idsInGroup[0];
  1289. // Consider negative values
  1290. if (hasNegativeValue && ys[baseId]) {
  1291. ys[baseId].forEach(function (v, i) {
  1292. ys[baseId][i] = v < 0 ? v : 0;
  1293. });
  1294. }
  1295. // Compute min
  1296. for (k = 1; k < idsInGroup.length; k++) {
  1297. id = idsInGroup[k];
  1298. if (! ys[id]) { continue; }
  1299. ys[id].forEach(function (v, i) {
  1300. if ($$.axis.getId(id) === $$.axis.getId(baseId) && ys[baseId] && !(hasNegativeValue && +v > 0)) {
  1301. ys[baseId][i] += +v;
  1302. }
  1303. });
  1304. }
  1305. }
  1306. }
  1307. return $$.d3.min(Object.keys(ys).map(function (key) { return $$.d3.min(ys[key]); }));
  1308. };
  1309. c3_chart_internal_fn.getYDomainMax = function (targets) {
  1310. var $$ = this, config = $$.config,
  1311. ids = $$.mapToIds(targets), ys = $$.getValuesAsIdKeyed(targets),
  1312. j, k, baseId, idsInGroup, id, hasPositiveValue;
  1313. if (config.data_groups.length > 0) {
  1314. hasPositiveValue = $$.hasPositiveValueInTargets(targets);
  1315. for (j = 0; j < config.data_groups.length; j++) {
  1316. // Determine baseId
  1317. idsInGroup = config.data_groups[j].filter(function (id) { return ids.indexOf(id) >= 0; });
  1318. if (idsInGroup.length === 0) { continue; }
  1319. baseId = idsInGroup[0];
  1320. // Consider positive values
  1321. if (hasPositiveValue && ys[baseId]) {
  1322. ys[baseId].forEach(function (v, i) {
  1323. ys[baseId][i] = v > 0 ? v : 0;
  1324. });
  1325. }
  1326. // Compute max
  1327. for (k = 1; k < idsInGroup.length; k++) {
  1328. id = idsInGroup[k];
  1329. if (! ys[id]) { continue; }
  1330. ys[id].forEach(function (v, i) {
  1331. if ($$.axis.getId(id) === $$.axis.getId(baseId) && ys[baseId] && !(hasPositiveValue && +v < 0)) {
  1332. ys[baseId][i] += +v;
  1333. }
  1334. });
  1335. }
  1336. }
  1337. }
  1338. return $$.d3.max(Object.keys(ys).map(function (key) { return $$.d3.max(ys[key]); }));
  1339. };
  1340. c3_chart_internal_fn.getYDomain = function (targets, axisId, xDomain) {
  1341. var $$ = this, config = $$.config,
  1342. targetsByAxisId = targets.filter(function (t) { return $$.axis.getId(t.id) === axisId; }),
  1343. yTargets = xDomain ? $$.filterByXDomain(targetsByAxisId, xDomain) : targetsByAxisId,
  1344. yMin = axisId === 'y2' ? config.axis_y2_min : config.axis_y_min,
  1345. yMax = axisId === 'y2' ? config.axis_y2_max : config.axis_y_max,
  1346. yDomainMin = $$.getYDomainMin(yTargets),
  1347. yDomainMax = $$.getYDomainMax(yTargets),
  1348. domain, domainLength, padding, padding_top, padding_bottom,
  1349. center = axisId === 'y2' ? config.axis_y2_center : config.axis_y_center,
  1350. yDomainAbs, lengths, diff, ratio, isAllPositive, isAllNegative,
  1351. isZeroBased = ($$.hasType('bar', yTargets) && config.bar_zerobased) || ($$.hasType('area', yTargets) && config.area_zerobased),
  1352. isInverted = axisId === 'y2' ? config.axis_y2_inverted : config.axis_y_inverted,
  1353. showHorizontalDataLabel = $$.hasDataLabel() && config.axis_rotated,
  1354. showVerticalDataLabel = $$.hasDataLabel() && !config.axis_rotated;
  1355. // MEMO: avoid inverting domain unexpectedly
  1356. yDomainMin = isValue(yMin) ? yMin : isValue(yMax) ? (yDomainMin < yMax ? yDomainMin : yMax - 10) : yDomainMin;
  1357. yDomainMax = isValue(yMax) ? yMax : isValue(yMin) ? (yMin < yDomainMax ? yDomainMax : yMin + 10) : yDomainMax;
  1358. if (yTargets.length === 0) { // use current domain if target of axisId is none
  1359. return axisId === 'y2' ? $$.y2.domain() : $$.y.domain();
  1360. }
  1361. if (isNaN(yDomainMin)) { // set minimum to zero when not number
  1362. yDomainMin = 0;
  1363. }
  1364. if (isNaN(yDomainMax)) { // set maximum to have same value as yDomainMin
  1365. yDomainMax = yDomainMin;
  1366. }
  1367. if (yDomainMin === yDomainMax) {
  1368. yDomainMin < 0 ? yDomainMax = 0 : yDomainMin = 0;
  1369. }
  1370. isAllPositive = yDomainMin >= 0 && yDomainMax >= 0;
  1371. isAllNegative = yDomainMin <= 0 && yDomainMax <= 0;
  1372. // Cancel zerobased if axis_*_min / axis_*_max specified
  1373. if ((isValue(yMin) && isAllPositive) || (isValue(yMax) && isAllNegative)) {
  1374. isZeroBased = false;
  1375. }
  1376. // Bar/Area chart should be 0-based if all positive|negative
  1377. if (isZeroBased) {
  1378. if (isAllPositive) { yDomainMin = 0; }
  1379. if (isAllNegative) { yDomainMax = 0; }
  1380. }
  1381. domainLength = Math.abs(yDomainMax - yDomainMin);
  1382. padding = padding_top = padding_bottom = domainLength * 0.1;
  1383. if (typeof center !== 'undefined') {
  1384. yDomainAbs = Math.max(Math.abs(yDomainMin), Math.abs(yDomainMax));
  1385. yDomainMax = center + yDomainAbs;
  1386. yDomainMin = center - yDomainAbs;
  1387. }
  1388. // add padding for data label
  1389. if (showHorizontalDataLabel) {
  1390. lengths = $$.getDataLabelLength(yDomainMin, yDomainMax, 'width');
  1391. diff = diffDomain($$.y.range());
  1392. ratio = [lengths[0] / diff, lengths[1] / diff];
  1393. padding_top += domainLength * (ratio[1] / (1 - ratio[0] - ratio[1]));
  1394. padding_bottom += domainLength * (ratio[0] / (1 - ratio[0] - ratio[1]));
  1395. } else if (showVerticalDataLabel) {
  1396. lengths = $$.getDataLabelLength(yDomainMin, yDomainMax, 'height');
  1397. padding_top += $$.axis.convertPixelsToAxisPadding(lengths[1], domainLength);
  1398. padding_bottom += $$.axis.convertPixelsToAxisPadding(lengths[0], domainLength);
  1399. }
  1400. if (axisId === 'y' && notEmpty(config.axis_y_padding)) {
  1401. padding_top = $$.axis.getPadding(config.axis_y_padding, 'top', padding_top, domainLength);
  1402. padding_bottom = $$.axis.getPadding(config.axis_y_padding, 'bottom', padding_bottom, domainLength);
  1403. }
  1404. if (axisId === 'y2' && notEmpty(config.axis_y2_padding)) {
  1405. padding_top = $$.axis.getPadding(config.axis_y2_padding, 'top', padding_top, domainLength);
  1406. padding_bottom = $$.axis.getPadding(config.axis_y2_padding, 'bottom', padding_bottom, domainLength);
  1407. }
  1408. // Bar/Area chart should be 0-based if all positive|negative
  1409. if (isZeroBased) {
  1410. if (isAllPositive) { padding_bottom = yDomainMin; }
  1411. if (isAllNegative) { padding_top = -yDomainMax; }
  1412. }
  1413. domain = [yDomainMin - padding_bottom, yDomainMax + padding_top];
  1414. return isInverted ? domain.reverse() : domain;
  1415. };
  1416. c3_chart_internal_fn.getXDomainMin = function (targets) {
  1417. var $$ = this, config = $$.config;
  1418. return isDefined(config.axis_x_min) ?
  1419. ($$.isTimeSeries() ? this.parseDate(config.axis_x_min) : config.axis_x_min) :
  1420. $$.d3.min(targets, function (t) { return $$.d3.min(t.values, function (v) { return v.x; }); });
  1421. };
  1422. c3_chart_internal_fn.getXDomainMax = function (targets) {
  1423. var $$ = this, config = $$.config;
  1424. return isDefined(config.axis_x_max) ?
  1425. ($$.isTimeSeries() ? this.parseDate(config.axis_x_max) : config.axis_x_max) :
  1426. $$.d3.max(targets, function (t) { return $$.d3.max(t.values, function (v) { return v.x; }); });
  1427. };
  1428. c3_chart_internal_fn.getXDomainPadding = function (domain) {
  1429. var $$ = this, config = $$.config,
  1430. diff = domain[1] - domain[0],
  1431. maxDataCount, padding, paddingLeft, paddingRight;
  1432. if ($$.isCategorized()) {
  1433. padding = 0;
  1434. } else if ($$.hasType('bar')) {
  1435. maxDataCount = $$.getMaxDataCount();
  1436. padding = maxDataCount > 1 ? (diff / (maxDataCount - 1)) / 2 : 0.5;
  1437. } else {
  1438. padding = diff * 0.01;
  1439. }
  1440. if (typeof config.axis_x_padding === 'object' && notEmpty(config.axis_x_padding)) {
  1441. paddingLeft = isValue(config.axis_x_padding.left) ? config.axis_x_padding.left : padding;
  1442. paddingRight = isValue(config.axis_x_padding.right) ? config.axis_x_padding.right : padding;
  1443. } else if (typeof config.axis_x_padding === 'number') {
  1444. paddingLeft = paddingRight = config.axis_x_padding;
  1445. } else {
  1446. paddingLeft = paddingRight = padding;
  1447. }
  1448. return {left: paddingLeft, right: paddingRight};
  1449. };
  1450. c3_chart_internal_fn.getXDomain = function (targets) {
  1451. var $$ = this,
  1452. xDomain = [$$.getXDomainMin(targets), $$.getXDomainMax(targets)],
  1453. firstX = xDomain[0], lastX = xDomain[1],
  1454. padding = $$.getXDomainPadding(xDomain),
  1455. min = 0, max = 0;
  1456. // show center of x domain if min and max are the same
  1457. if ((firstX - lastX) === 0 && !$$.isCategorized()) {
  1458. if ($$.isTimeSeries()) {
  1459. firstX = new Date(firstX.getTime() * 0.5);
  1460. lastX = new Date(lastX.getTime() * 1.5);
  1461. } else {
  1462. firstX = firstX === 0 ? 1 : (firstX * 0.5);
  1463. lastX = lastX === 0 ? -1 : (lastX * 1.5);
  1464. }
  1465. }
  1466. if (firstX || firstX === 0) {
  1467. min = $$.isTimeSeries() ? new Date(firstX.getTime() - padding.left) : firstX - padding.left;
  1468. }
  1469. if (lastX || lastX === 0) {
  1470. max = $$.isTimeSeries() ? new Date(lastX.getTime() + padding.right) : lastX + padding.right;
  1471. }
  1472. return [min, max];
  1473. };
  1474. c3_chart_internal_fn.updateXDomain = function (targets, withUpdateXDomain, withUpdateOrgXDomain, withTrim, domain) {
  1475. var $$ = this, config = $$.config;
  1476. if (withUpdateOrgXDomain) {
  1477. $$.x.domain(domain ? domain : $$.d3.extent($$.getXDomain(targets)));
  1478. $$.orgXDomain = $$.x.domain();
  1479. if (config.zoom_enabled) { $$.zoom.scale($$.x).updateScaleExtent(); }
  1480. $$.subX.domain($$.x.domain());
  1481. if ($$.brush) { $$.brush.scale($$.subX); }
  1482. }
  1483. if (withUpdateXDomain) {
  1484. $$.x.domain(domain ? domain : (!$$.brush || $$.brush.empty()) ? $$.orgXDomain : $$.brush.extent());
  1485. if (config.zoom_enabled) { $$.zoom.scale($$.x).updateScaleExtent(); }
  1486. }
  1487. // Trim domain when too big by zoom mousemove event
  1488. if (withTrim) { $$.x.domain($$.trimXDomain($$.x.orgDomain())); }
  1489. return $$.x.domain();
  1490. };
  1491. c3_chart_internal_fn.trimXDomain = function (domain) {
  1492. var zoomDomain = this.getZoomDomain(),
  1493. min = zoomDomain[0], max = zoomDomain[1];
  1494. if (domain[0] <= min) {
  1495. domain[1] = +domain[1] + (min - domain[0]);
  1496. domain[0] = min;
  1497. }
  1498. if (max <= domain[1]) {
  1499. domain[0] = +domain[0] - (domain[1] - max);
  1500. domain[1] = max;
  1501. }
  1502. return domain;
  1503. };
  1504. c3_chart_internal_fn.isX = function (key) {
  1505. var $$ = this, config = $$.config;
  1506. return (config.data_x && key === config.data_x) || (notEmpty(config.data_xs) && hasValue(config.data_xs, key));
  1507. };
  1508. c3_chart_internal_fn.isNotX = function (key) {
  1509. return !this.isX(key);
  1510. };
  1511. c3_chart_internal_fn.getXKey = function (id) {
  1512. var $$ = this, config = $$.config;
  1513. return config.data_x ? config.data_x : notEmpty(config.data_xs) ? config.data_xs[id] : null;
  1514. };
  1515. c3_chart_internal_fn.getXValuesOfXKey = function (key, targets) {
  1516. var $$ = this,
  1517. xValues, ids = targets && notEmpty(targets) ? $$.mapToIds(targets) : [];
  1518. ids.forEach(function (id) {
  1519. if ($$.getXKey(id) === key) {
  1520. xValues = $$.data.xs[id];
  1521. }
  1522. });
  1523. return xValues;
  1524. };
  1525. c3_chart_internal_fn.getIndexByX = function (x) {
  1526. var $$ = this,
  1527. data = $$.filterByX($$.data.targets, x);
  1528. return data.length ? data[0].index : null;
  1529. };
  1530. c3_chart_internal_fn.getXValue = function (id, i) {
  1531. var $$ = this;
  1532. return id in $$.data.xs && $$.data.xs[id] && isValue($$.data.xs[id][i]) ? $$.data.xs[id][i] : i;
  1533. };
  1534. c3_chart_internal_fn.getOtherTargetXs = function () {
  1535. var $$ = this,
  1536. idsForX = Object.keys($$.data.xs);
  1537. return idsForX.length ? $$.data.xs[idsForX[0]] : null;
  1538. };
  1539. c3_chart_internal_fn.getOtherTargetX = function (index) {
  1540. var xs = this.getOtherTargetXs();
  1541. return xs && index < xs.length ? xs[index] : null;
  1542. };
  1543. c3_chart_internal_fn.addXs = function (xs) {
  1544. var $$ = this;
  1545. Object.keys(xs).forEach(function (id) {
  1546. $$.config.data_xs[id] = xs[id];
  1547. });
  1548. };
  1549. c3_chart_internal_fn.hasMultipleX = function (xs) {
  1550. return this.d3.set(Object.keys(xs).map(function (id) { return xs[id]; })).size() > 1;
  1551. };
  1552. c3_chart_internal_fn.isMultipleX = function () {
  1553. return notEmpty(this.config.data_xs) || !this.config.data_xSort || this.hasType('scatter');
  1554. };
  1555. c3_chart_internal_fn.addName = function (data) {
  1556. var $$ = this, name;
  1557. if (data) {
  1558. name = $$.config.data_names[data.id];
  1559. data.name = name !== undefined ? name : data.id;
  1560. }
  1561. return data;
  1562. };
  1563. c3_chart_internal_fn.getValueOnIndex = function (values, index) {
  1564. var valueOnIndex = values.filter(function (v) { return v.index === index; });
  1565. return valueOnIndex.length ? valueOnIndex[0] : null;
  1566. };
  1567. c3_chart_internal_fn.updateTargetX = function (targets, x) {
  1568. var $$ = this;
  1569. targets.forEach(function (t) {
  1570. t.values.forEach(function (v, i) {
  1571. v.x = $$.generateTargetX(x[i], t.id, i);
  1572. });
  1573. $$.data.xs[t.id] = x;
  1574. });
  1575. };
  1576. c3_chart_internal_fn.updateTargetXs = function (targets, xs) {
  1577. var $$ = this;
  1578. targets.forEach(function (t) {
  1579. if (xs[t.id]) {
  1580. $$.updateTargetX([t], xs[t.id]);
  1581. }
  1582. });
  1583. };
  1584. c3_chart_internal_fn.generateTargetX = function (rawX, id, index) {
  1585. var $$ = this, x;
  1586. if ($$.isTimeSeries()) {
  1587. x = rawX ? $$.parseDate(rawX) : $$.parseDate($$.getXValue(id, index));
  1588. }
  1589. else if ($$.isCustomX() && !$$.isCategorized()) {
  1590. x = isValue(rawX) ? +rawX : $$.getXValue(id, index);
  1591. }
  1592. else {
  1593. x = index;
  1594. }
  1595. return x;
  1596. };
  1597. c3_chart_internal_fn.cloneTarget = function (target) {
  1598. return {
  1599. id : target.id,
  1600. id_org : target.id_org,
  1601. values : target.values.map(function (d) {
  1602. return {x: d.x, value: d.value, id: d.id};
  1603. })
  1604. };
  1605. };
  1606. c3_chart_internal_fn.updateXs = function () {
  1607. var $$ = this;
  1608. if ($$.data.targets.length) {
  1609. $$.xs = [];
  1610. $$.data.targets[0].values.forEach(function (v) {
  1611. $$.xs[v.index] = v.x;
  1612. });
  1613. }
  1614. };
  1615. c3_chart_internal_fn.getPrevX = function (i) {
  1616. var x = this.xs[i - 1];
  1617. return typeof x !== 'undefined' ? x : null;
  1618. };
  1619. c3_chart_internal_fn.getNextX = function (i) {
  1620. var x = this.xs[i + 1];
  1621. return typeof x !== 'undefined' ? x : null;
  1622. };
  1623. c3_chart_internal_fn.getMaxDataCount = function () {
  1624. var $$ = this;
  1625. return $$.d3.max($$.data.targets, function (t) { return t.values.length; });
  1626. };
  1627. c3_chart_internal_fn.getMaxDataCountTarget = function (targets) {
  1628. var length = targets.length, max = 0, maxTarget;
  1629. if (length > 1) {
  1630. targets.forEach(function (t) {
  1631. if (t.values.length > max) {
  1632. maxTarget = t;
  1633. max = t.values.length;
  1634. }
  1635. });
  1636. } else {
  1637. maxTarget = length ? targets[0] : null;
  1638. }
  1639. return maxTarget;
  1640. };
  1641. c3_chart_internal_fn.getEdgeX = function (targets) {
  1642. var $$ = this;
  1643. return !targets.length ? [0, 0] : [
  1644. $$.d3.min(targets, function (t) { return t.values[0].x; }),
  1645. $$.d3.max(targets, function (t) { return t.values[t.values.length - 1].x; })
  1646. ];
  1647. };
  1648. c3_chart_internal_fn.mapToIds = function (targets) {
  1649. return targets.map(function (d) { return d.id; });
  1650. };
  1651. c3_chart_internal_fn.mapToTargetIds = function (ids) {
  1652. var $$ = this;
  1653. return ids ? [].concat(ids) : $$.mapToIds($$.data.targets);
  1654. };
  1655. c3_chart_internal_fn.hasTarget = function (targets, id) {
  1656. var ids = this.mapToIds(targets), i;
  1657. for (i = 0; i < ids.length; i++) {
  1658. if (ids[i] === id) {
  1659. return true;
  1660. }
  1661. }
  1662. return false;
  1663. };
  1664. c3_chart_internal_fn.isTargetToShow = function (targetId) {
  1665. return this.hiddenTargetIds.indexOf(targetId) < 0;
  1666. };
  1667. c3_chart_internal_fn.isLegendToShow = function (targetId) {
  1668. return this.hiddenLegendIds.indexOf(targetId) < 0;
  1669. };
  1670. c3_chart_internal_fn.filterTargetsToShow = function (targets) {
  1671. var $$ = this;
  1672. return targets.filter(function (t) { return $$.isTargetToShow(t.id); });
  1673. };
  1674. c3_chart_internal_fn.mapTargetsToUniqueXs = function (targets) {
  1675. var $$ = this;
  1676. var xs = $$.d3.set($$.d3.merge(targets.map(function (t) { return t.values.map(function (v) { return +v.x; }); }))).values();
  1677. xs = $$.isTimeSeries() ? xs.map(function (x) { return new Date(+x); }) : xs.map(function (x) { return +x; });
  1678. return xs.sort(function (a, b) { return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; });
  1679. };
  1680. c3_chart_internal_fn.addHiddenTargetIds = function (targetIds) {
  1681. this.hiddenTargetIds = this.hiddenTargetIds.concat(targetIds);
  1682. };
  1683. c3_chart_internal_fn.removeHiddenTargetIds = function (targetIds) {
  1684. this.hiddenTargetIds = this.hiddenTargetIds.filter(function (id) { return targetIds.indexOf(id) < 0; });
  1685. };
  1686. c3_chart_internal_fn.addHiddenLegendIds = function (targetIds) {
  1687. this.hiddenLegendIds = this.hiddenLegendIds.concat(targetIds);
  1688. };
  1689. c3_chart_internal_fn.removeHiddenLegendIds = function (targetIds) {
  1690. this.hiddenLegendIds = this.hiddenLegendIds.filter(function (id) { return targetIds.indexOf(id) < 0; });
  1691. };
  1692. c3_chart_internal_fn.getValuesAsIdKeyed = function (targets) {
  1693. var ys = {};
  1694. targets.forEach(function (t) {
  1695. ys[t.id] = [];
  1696. t.values.forEach(function (v) {
  1697. ys[t.id].push(v.value);
  1698. });
  1699. });
  1700. return ys;
  1701. };
  1702. c3_chart_internal_fn.checkValueInTargets = function (targets, checker) {
  1703. var ids = Object.keys(targets), i, j, values;
  1704. for (i = 0; i < ids.length; i++) {
  1705. values = targets[ids[i]].values;
  1706. for (j = 0; j < values.length; j++) {
  1707. if (checker(values[j].value)) {
  1708. return true;
  1709. }
  1710. }
  1711. }
  1712. return false;
  1713. };
  1714. c3_chart_internal_fn.hasNegativeValueInTargets = function (targets) {
  1715. return this.checkValueInTargets(targets, function (v) { return v < 0; });
  1716. };
  1717. c3_chart_internal_fn.hasPositiveValueInTargets = function (targets) {
  1718. return this.checkValueInTargets(targets, function (v) { return v > 0; });
  1719. };
  1720. c3_chart_internal_fn.isOrderDesc = function () {
  1721. var config = this.config;
  1722. return typeof(config.data_order) === 'string' && config.data_order.toLowerCase() === 'desc';
  1723. };
  1724. c3_chart_internal_fn.isOrderAsc = function () {
  1725. var config = this.config;
  1726. return typeof(config.data_order) === 'string' && config.data_order.toLowerCase() === 'asc';
  1727. };
  1728. c3_chart_internal_fn.orderTargets = function (targets) {
  1729. var $$ = this, config = $$.config, orderAsc = $$.isOrderAsc(), orderDesc = $$.isOrderDesc();
  1730. if (orderAsc || orderDesc) {
  1731. targets.sort(function (t1, t2) {
  1732. var reducer = function (p, c) { return p + Math.abs(c.value); };
  1733. var t1Sum = t1.values.reduce(reducer, 0),
  1734. t2Sum = t2.values.reduce(reducer, 0);
  1735. return orderAsc ? t2Sum - t1Sum : t1Sum - t2Sum;
  1736. });
  1737. } else if (isFunction(config.data_order)) {
  1738. targets.sort(config.data_order);
  1739. } // TODO: accept name array for order
  1740. return targets;
  1741. };
  1742. c3_chart_internal_fn.filterByX = function (targets, x) {
  1743. return this.d3.merge(targets.map(function (t) { return t.values; })).filter(function (v) { return v.x - x === 0; });
  1744. };
  1745. c3_chart_internal_fn.filterRemoveNull = function (data) {
  1746. return data.filter(function (d) { return isValue(d.value); });
  1747. };
  1748. c3_chart_internal_fn.filterByXDomain = function (targets, xDomain) {
  1749. return targets.map(function (t) {
  1750. return {
  1751. id: t.id,
  1752. id_org: t.id_org,
  1753. values: t.values.filter(function (v) {
  1754. return xDomain[0] <= v.x && v.x <= xDomain[1];
  1755. })
  1756. };
  1757. });
  1758. };
  1759. c3_chart_internal_fn.hasDataLabel = function () {
  1760. var config = this.config;
  1761. if (typeof config.data_labels === 'boolean' && config.data_labels) {
  1762. return true;
  1763. } else if (typeof config.data_labels === 'object' && notEmpty(config.data_labels)) {
  1764. return true;
  1765. }
  1766. return false;
  1767. };
  1768. c3_chart_internal_fn.getDataLabelLength = function (min, max, key) {
  1769. var $$ = this,
  1770. lengths = [0, 0], paddingCoef = 1.3;
  1771. $$.selectChart.select('svg').selectAll('.dummy')
  1772. .data([min, max])
  1773. .enter().append('text')
  1774. .text(function (d) { return $$.dataLabelFormat(d.id)(d); })
  1775. .each(function (d, i) {
  1776. lengths[i] = this.getBoundingClientRect()[key] * paddingCoef;
  1777. })
  1778. .remove();
  1779. return lengths;
  1780. };
  1781. c3_chart_internal_fn.isNoneArc = function (d) {
  1782. return this.hasTarget(this.data.targets, d.id);
  1783. },
  1784. c3_chart_internal_fn.isArc = function (d) {
  1785. return 'data' in d && this.hasTarget(this.data.targets, d.data.id);
  1786. };
  1787. c3_chart_internal_fn.findSameXOfValues = function (values, index) {
  1788. var i, targetX = values[index].x, sames = [];
  1789. for (i = index - 1; i >= 0; i--) {
  1790. if (targetX !== values[i].x) { break; }
  1791. sames.push(values[i]);
  1792. }
  1793. for (i = index; i < values.length; i++) {
  1794. if (targetX !== values[i].x) { break; }
  1795. sames.push(values[i]);
  1796. }
  1797. return sames;
  1798. };
  1799. c3_chart_internal_fn.findClosestFromTargets = function (targets, pos) {
  1800. var $$ = this, candidates;
  1801. // map to array of closest points of each target
  1802. candidates = targets.map(function (target) {
  1803. return $$.findClosest(target.values, pos);
  1804. });
  1805. // decide closest point and return
  1806. return $$.findClosest(candidates, pos);
  1807. };
  1808. c3_chart_internal_fn.findClosest = function (values, pos) {
  1809. var $$ = this, minDist = $$.config.point_sensitivity, closest;
  1810. // find mouseovering bar
  1811. values.filter(function (v) { return v && $$.isBarType(v.id); }).forEach(function (v) {
  1812. var shape = $$.main.select('.' + CLASS.bars + $$.getTargetSelectorSuffix(v.id) + ' .' + CLASS.bar + '-' + v.index).node();
  1813. if (!closest && $$.isWithinBar(shape)) {
  1814. closest = v;
  1815. }
  1816. });
  1817. // find closest point from non-bar
  1818. values.filter(function (v) { return v && !$$.isBarType(v.id); }).forEach(function (v) {
  1819. var d = $$.dist(v, pos);
  1820. if (d < minDist) {
  1821. minDist = d;
  1822. closest = v;
  1823. }
  1824. });
  1825. return closest;
  1826. };
  1827. c3_chart_internal_fn.dist = function (data, pos) {
  1828. var $$ = this, config = $$.config,
  1829. xIndex = config.axis_rotated ? 1 : 0,
  1830. yIndex = config.axis_rotated ? 0 : 1,
  1831. y = $$.circleY(data, data.index),
  1832. x = $$.x(data.x);
  1833. return Math.sqrt(Math.pow(x - pos[xIndex], 2) + Math.pow(y - pos[yIndex], 2));
  1834. };
  1835. c3_chart_internal_fn.convertValuesToStep = function (values) {
  1836. var converted = [].concat(values), i;
  1837. if (!this.isCategorized()) {
  1838. return values;
  1839. }
  1840. for (i = values.length + 1; 0 < i; i--) {
  1841. converted[i] = converted[i - 1];
  1842. }
  1843. converted[0] = {
  1844. x: converted[0].x - 1,
  1845. value: converted[0].value,
  1846. id: converted[0].id
  1847. };
  1848. converted[values.length + 1] = {
  1849. x: converted[values.length].x + 1,
  1850. value: converted[values.length].value,
  1851. id: converted[values.length].id
  1852. };
  1853. return converted;
  1854. };
  1855. c3_chart_internal_fn.updateDataAttributes = function (name, attrs) {
  1856. var $$ = this, config = $$.config, current = config['data_' + name];
  1857. if (typeof attrs === 'undefined') { return current; }
  1858. Object.keys(attrs).forEach(function (id) {
  1859. current[id] = attrs[id];
  1860. });
  1861. $$.redraw({withLegend: true});
  1862. return current;
  1863. };
  1864. c3_chart_internal_fn.convertUrlToData = function (url, mimeType, headers, keys, done) {
  1865. var $$ = this, type = mimeType ? mimeType : 'csv';
  1866. var req = $$.d3.xhr(url);
  1867. if (headers) {
  1868. Object.keys(headers).forEach(function (header) {
  1869. req.header(header, headers[header]);
  1870. });
  1871. }
  1872. req.get(function (error, data) {
  1873. var d;
  1874. if (!data) {
  1875. throw new Error(error.responseURL + ' ' + error.status + ' (' + error.statusText + ')');
  1876. }
  1877. if (type === 'json') {
  1878. d = $$.convertJsonToData(JSON.parse(data.response), keys);
  1879. } else if (type === 'tsv') {
  1880. d = $$.convertTsvToData(data.response);
  1881. } else {
  1882. d = $$.convertCsvToData(data.response);
  1883. }
  1884. done.call($$, d);
  1885. });
  1886. };
  1887. c3_chart_internal_fn.convertXsvToData = function (xsv, parser) {
  1888. var rows = parser.parseRows(xsv), d;
  1889. if (rows.length === 1) {
  1890. d = [{}];
  1891. rows[0].forEach(function (id) {
  1892. d[0][id] = null;
  1893. });
  1894. } else {
  1895. d = parser.parse(xsv);
  1896. }
  1897. return d;
  1898. };
  1899. c3_chart_internal_fn.convertCsvToData = function (csv) {
  1900. return this.convertXsvToData(csv, this.d3.csv);
  1901. };
  1902. c3_chart_internal_fn.convertTsvToData = function (tsv) {
  1903. return this.convertXsvToData(tsv, this.d3.tsv);
  1904. };
  1905. c3_chart_internal_fn.convertJsonToData = function (json, keys) {
  1906. var $$ = this,
  1907. new_rows = [], targetKeys, data;
  1908. if (keys) { // when keys specified, json would be an array that includes objects
  1909. if (keys.x) {
  1910. targetKeys = keys.value.concat(keys.x);
  1911. $$.config.data_x = keys.x;
  1912. } else {
  1913. targetKeys = keys.value;
  1914. }
  1915. new_rows.push(targetKeys);
  1916. json.forEach(function (o) {
  1917. var new_row = [];
  1918. targetKeys.forEach(function (key) {
  1919. // convert undefined to null because undefined data will be removed in convertDataToTargets()
  1920. var v = $$.findValueInJson(o, key);
  1921. if (isUndefined(v)) {
  1922. v = null;
  1923. }
  1924. new_row.push(v);
  1925. });
  1926. new_rows.push(new_row);
  1927. });
  1928. data = $$.convertRowsToData(new_rows);
  1929. } else {
  1930. Object.keys(json).forEach(function (key) {
  1931. new_rows.push([key].concat(json[key]));
  1932. });
  1933. data = $$.convertColumnsToData(new_rows);
  1934. }
  1935. return data;
  1936. };
  1937. c3_chart_internal_fn.findValueInJson = function (object, path) {
  1938. path = path.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties (replace [] with .)
  1939. path = path.replace(/^\./, ''); // strip a leading dot
  1940. var pathArray = path.split('.');
  1941. for (var i = 0; i < pathArray.length; ++i) {
  1942. var k = pathArray[i];
  1943. if (k in object) {
  1944. object = object[k];
  1945. } else {
  1946. return;
  1947. }
  1948. }
  1949. return object;
  1950. };
  1951. c3_chart_internal_fn.convertRowsToData = function (rows) {
  1952. var keys = rows[0], new_row = {}, new_rows = [], i, j;
  1953. for (i = 1; i < rows.length; i++) {
  1954. new_row = {};
  1955. for (j = 0; j < rows[i].length; j++) {
  1956. if (isUndefined(rows[i][j])) {
  1957. throw new Error("Source data is missing a component at (" + i + "," + j + ")!");
  1958. }
  1959. new_row[keys[j]] = rows[i][j];
  1960. }
  1961. new_rows.push(new_row);
  1962. }
  1963. return new_rows;
  1964. };
  1965. c3_chart_internal_fn.convertColumnsToData = function (columns) {
  1966. var new_rows = [], i, j, key;
  1967. for (i = 0; i < columns.length; i++) {
  1968. key = columns[i][0];
  1969. for (j = 1; j < columns[i].length; j++) {
  1970. if (isUndefined(new_rows[j - 1])) {
  1971. new_rows[j - 1] = {};
  1972. }
  1973. if (isUndefined(columns[i][j])) {
  1974. throw new Error("Source data is missing a component at (" + i + "," + j + ")!");
  1975. }
  1976. new_rows[j - 1][key] = columns[i][j];
  1977. }
  1978. }
  1979. return new_rows;
  1980. };
  1981. c3_chart_internal_fn.convertDataToTargets = function (data, appendXs) {
  1982. var $$ = this, config = $$.config,
  1983. ids = $$.d3.keys(data[0]).filter($$.isNotX, $$),
  1984. xs = $$.d3.keys(data[0]).filter($$.isX, $$),
  1985. targets;
  1986. // save x for update data by load when custom x and c3.x API
  1987. ids.forEach(function (id) {
  1988. var xKey = $$.getXKey(id);
  1989. if ($$.isCustomX() || $$.isTimeSeries()) {
  1990. // if included in input data
  1991. if (xs.indexOf(xKey) >= 0) {
  1992. $$.data.xs[id] = (appendXs && $$.data.xs[id] ? $$.data.xs[id] : []).concat(
  1993. data.map(function (d) { return d[xKey]; })
  1994. .filter(isValue)
  1995. .map(function (rawX, i) { return $$.generateTargetX(rawX, id, i); })
  1996. );
  1997. }
  1998. // if not included in input data, find from preloaded data of other id's x
  1999. else if (config.data_x) {
  2000. $$.data.xs[id] = $$.getOtherTargetXs();
  2001. }
  2002. // if not included in input data, find from preloaded data
  2003. else if (notEmpty(config.data_xs)) {
  2004. $$.data.xs[id] = $$.getXValuesOfXKey(xKey, $$.data.targets);
  2005. }
  2006. // MEMO: if no x included, use same x of current will be used
  2007. } else {
  2008. $$.data.xs[id] = data.map(function (d, i) { return i; });
  2009. }
  2010. });
  2011. // check x is defined
  2012. ids.forEach(function (id) {
  2013. if (!$$.data.xs[id]) {
  2014. throw new Error('x is not defined for id = "' + id + '".');
  2015. }
  2016. });
  2017. // convert to target
  2018. targets = ids.map(function (id, index) {
  2019. var convertedId = config.data_idConverter(id);
  2020. return {
  2021. id: convertedId,
  2022. id_org: id,
  2023. values: data.map(function (d, i) {
  2024. var xKey = $$.getXKey(id), rawX = d[xKey],
  2025. value = d[id] !== null && !isNaN(d[id]) ? +d[id] : null, x;
  2026. // use x as categories if custom x and categorized
  2027. if ($$.isCustomX() && $$.isCategorized() && index === 0 && !isUndefined(rawX)) {
  2028. if (index === 0 && i === 0) {
  2029. config.axis_x_categories = [];
  2030. }
  2031. x = config.axis_x_categories.indexOf(rawX);
  2032. if (x === -1) {
  2033. x = config.axis_x_categories.length;
  2034. config.axis_x_categories.push(rawX);
  2035. }
  2036. } else {
  2037. x = $$.generateTargetX(rawX, id, i);
  2038. }
  2039. // mark as x = undefined if value is undefined and filter to remove after mapped
  2040. if (isUndefined(d[id]) || $$.data.xs[id].length <= i) {
  2041. x = undefined;
  2042. }
  2043. return {x: x, value: value, id: convertedId};
  2044. }).filter(function (v) { return isDefined(v.x); })
  2045. };
  2046. });
  2047. // finish targets
  2048. targets.forEach(function (t) {
  2049. var i;
  2050. // sort values by its x
  2051. if (config.data_xSort) {
  2052. t.values = t.values.sort(function (v1, v2) {
  2053. var x1 = v1.x || v1.x === 0 ? v1.x : Infinity,
  2054. x2 = v2.x || v2.x === 0 ? v2.x : Infinity;
  2055. return x1 - x2;
  2056. });
  2057. }
  2058. // indexing each value
  2059. i = 0;
  2060. t.values.forEach(function (v) {
  2061. v.index = i++;
  2062. });
  2063. // this needs to be sorted because its index and value.index is identical
  2064. $$.data.xs[t.id].sort(function (v1, v2) {
  2065. return v1 - v2;
  2066. });
  2067. });
  2068. // cache information about values
  2069. $$.hasNegativeValue = $$.hasNegativeValueInTargets(targets);
  2070. $$.hasPositiveValue = $$.hasPositiveValueInTargets(targets);
  2071. // set target types
  2072. if (config.data_type) {
  2073. $$.setTargetType($$.mapToIds(targets).filter(function (id) { return ! (id in config.data_types); }), config.data_type);
  2074. }
  2075. // cache as original id keyed
  2076. targets.forEach(function (d) {
  2077. $$.addCache(d.id_org, d);
  2078. });
  2079. return targets;
  2080. };
  2081. c3_chart_internal_fn.load = function (targets, args) {
  2082. var $$ = this;
  2083. if (targets) {
  2084. // filter loading targets if needed
  2085. if (args.filter) {
  2086. targets = targets.filter(args.filter);
  2087. }
  2088. // set type if args.types || args.type specified
  2089. if (args.type || args.types) {
  2090. targets.forEach(function (t) {
  2091. var type = args.types && args.types[t.id] ? args.types[t.id] : args.type;
  2092. $$.setTargetType(t.id, type);
  2093. });
  2094. }
  2095. // Update/Add data
  2096. $$.data.targets.forEach(function (d) {
  2097. for (var i = 0; i < targets.length; i++) {
  2098. if (d.id === targets[i].id) {
  2099. d.values = targets[i].values;
  2100. targets.splice(i, 1);
  2101. break;
  2102. }
  2103. }
  2104. });
  2105. $$.data.targets = $$.data.targets.concat(targets); // add remained
  2106. }
  2107. // Set targets
  2108. $$.updateTargets($$.data.targets);
  2109. // Redraw with new targets
  2110. $$.redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true, withLegend: true});
  2111. if (args.done) { args.done(); }
  2112. };
  2113. c3_chart_internal_fn.loadFromArgs = function (args) {
  2114. var $$ = this;
  2115. if (args.data) {
  2116. $$.load($$.convertDataToTargets(args.data), args);
  2117. }
  2118. else if (args.url) {
  2119. $$.convertUrlToData(args.url, args.mimeType, args.headers, args.keys, function (data) {
  2120. $$.load($$.convertDataToTargets(data), args);
  2121. });
  2122. }
  2123. else if (args.json) {
  2124. $$.load($$.convertDataToTargets($$.convertJsonToData(args.json, args.keys)), args);
  2125. }
  2126. else if (args.rows) {
  2127. $$.load($$.convertDataToTargets($$.convertRowsToData(args.rows)), args);
  2128. }
  2129. else if (args.columns) {
  2130. $$.load($$.convertDataToTargets($$.convertColumnsToData(args.columns)), args);
  2131. }
  2132. else {
  2133. $$.load(null, args);
  2134. }
  2135. };
  2136. c3_chart_internal_fn.unload = function (targetIds, done) {
  2137. var $$ = this;
  2138. if (!done) {
  2139. done = function () {};
  2140. }
  2141. // filter existing target
  2142. targetIds = targetIds.filter(function (id) { return $$.hasTarget($$.data.targets, id); });
  2143. // If no target, call done and return
  2144. if (!targetIds || targetIds.length === 0) {
  2145. done();
  2146. return;
  2147. }
  2148. $$.svg.selectAll(targetIds.map(function (id) { return $$.selectorTarget(id); }))
  2149. .transition()
  2150. .style('opacity', 0)
  2151. .remove()
  2152. .call($$.endall, done);
  2153. targetIds.forEach(function (id) {
  2154. // Reset fadein for future load
  2155. $$.withoutFadeIn[id] = false;
  2156. // Remove target's elements
  2157. if ($$.legend) {
  2158. $$.legend.selectAll('.' + CLASS.legendItem + $$.getTargetSelectorSuffix(id)).remove();
  2159. }
  2160. // Remove target
  2161. $$.data.targets = $$.data.targets.filter(function (t) {
  2162. return t.id !== id;
  2163. });
  2164. });
  2165. };
  2166. c3_chart_internal_fn.categoryName = function (i) {
  2167. var config = this.config;
  2168. return i < config.axis_x_categories.length ? config.axis_x_categories[i] : i;
  2169. };
  2170. c3_chart_internal_fn.initEventRect = function () {
  2171. var $$ = this;
  2172. $$.main.select('.' + CLASS.chart).append("g")
  2173. .attr("class", CLASS.eventRects)
  2174. .style('fill-opacity', 0);
  2175. };
  2176. c3_chart_internal_fn.redrawEventRect = function () {
  2177. var $$ = this, config = $$.config,
  2178. eventRectUpdate, maxDataCountTarget,
  2179. isMultipleX = $$.isMultipleX();
  2180. // rects for mouseover
  2181. var eventRects = $$.main.select('.' + CLASS.eventRects)
  2182. .style('cursor', config.zoom_enabled ? config.axis_rotated ? 'ns-resize' : 'ew-resize' : null)
  2183. .classed(CLASS.eventRectsMultiple, isMultipleX)
  2184. .classed(CLASS.eventRectsSingle, !isMultipleX);
  2185. // clear old rects
  2186. eventRects.selectAll('.' + CLASS.eventRect).remove();
  2187. // open as public variable
  2188. $$.eventRect = eventRects.selectAll('.' + CLASS.eventRect);
  2189. if (isMultipleX) {
  2190. eventRectUpdate = $$.eventRect.data([0]);
  2191. // enter : only one rect will be added
  2192. $$.generateEventRectsForMultipleXs(eventRectUpdate.enter());
  2193. // update
  2194. $$.updateEventRect(eventRectUpdate);
  2195. // exit : not needed because always only one rect exists
  2196. }
  2197. else {
  2198. // Set data and update $$.eventRect
  2199. maxDataCountTarget = $$.getMaxDataCountTarget($$.data.targets);
  2200. eventRects.datum(maxDataCountTarget ? maxDataCountTarget.values : []);
  2201. $$.eventRect = eventRects.selectAll('.' + CLASS.eventRect);
  2202. eventRectUpdate = $$.eventRect.data(function (d) { return d; });
  2203. // enter
  2204. $$.generateEventRectsForSingleX(eventRectUpdate.enter());
  2205. // update
  2206. $$.updateEventRect(eventRectUpdate);
  2207. // exit
  2208. eventRectUpdate.exit().remove();
  2209. }
  2210. };
  2211. c3_chart_internal_fn.updateEventRect = function (eventRectUpdate) {
  2212. var $$ = this, config = $$.config,
  2213. x, y, w, h, rectW, rectX;
  2214. // set update selection if null
  2215. eventRectUpdate = eventRectUpdate || $$.eventRect.data(function (d) { return d; });
  2216. if ($$.isMultipleX()) {
  2217. // TODO: rotated not supported yet
  2218. x = 0;
  2219. y = 0;
  2220. w = $$.width;
  2221. h = $$.height;
  2222. }
  2223. else {
  2224. if (($$.isCustomX() || $$.isTimeSeries()) && !$$.isCategorized()) {
  2225. // update index for x that is used by prevX and nextX
  2226. $$.updateXs();
  2227. rectW = function (d) {
  2228. var prevX = $$.getPrevX(d.index), nextX = $$.getNextX(d.index);
  2229. // if there this is a single data point make the eventRect full width (or height)
  2230. if (prevX === null && nextX === null) {
  2231. return config.axis_rotated ? $$.height : $$.width;
  2232. }
  2233. if (prevX === null) { prevX = $$.x.domain()[0]; }
  2234. if (nextX === null) { nextX = $$.x.domain()[1]; }
  2235. return Math.max(0, ($$.x(nextX) - $$.x(prevX)) / 2);
  2236. };
  2237. rectX = function (d) {
  2238. var prevX = $$.getPrevX(d.index), nextX = $$.getNextX(d.index),
  2239. thisX = $$.data.xs[d.id][d.index];
  2240. // if there this is a single data point position the eventRect at 0
  2241. if (prevX === null && nextX === null) {
  2242. return 0;
  2243. }
  2244. if (prevX === null) { prevX = $$.x.domain()[0]; }
  2245. return ($$.x(thisX) + $$.x(prevX)) / 2;
  2246. };
  2247. } else {
  2248. rectW = $$.getEventRectWidth();
  2249. rectX = function (d) {
  2250. return $$.x(d.x) - (rectW / 2);
  2251. };
  2252. }
  2253. x = config.axis_rotated ? 0 : rectX;
  2254. y = config.axis_rotated ? rectX : 0;
  2255. w = config.axis_rotated ? $$.width : rectW;
  2256. h = config.axis_rotated ? rectW : $$.height;
  2257. }
  2258. eventRectUpdate
  2259. .attr('class', $$.classEvent.bind($$))
  2260. .attr("x", x)
  2261. .attr("y", y)
  2262. .attr("width", w)
  2263. .attr("height", h);
  2264. };
  2265. c3_chart_internal_fn.generateEventRectsForSingleX = function (eventRectEnter) {
  2266. var $$ = this, d3 = $$.d3, config = $$.config;
  2267. eventRectEnter.append("rect")
  2268. .attr("class", $$.classEvent.bind($$))
  2269. .style("cursor", config.data_selection_enabled && config.data_selection_grouped ? "pointer" : null)
  2270. .on('mouseover', function (d) {
  2271. var index = d.index;
  2272. if ($$.dragging || $$.flowing) { return; } // do nothing while dragging/flowing
  2273. if ($$.hasArcType()) { return; }
  2274. // Expand shapes for selection
  2275. if (config.point_focus_expand_enabled) { $$.expandCircles(index, null, true); }
  2276. $$.expandBars(index, null, true);
  2277. // Call event handler
  2278. $$.main.selectAll('.' + CLASS.shape + '-' + index).each(function (d) {
  2279. config.data_onmouseover.call($$.api, d);
  2280. });
  2281. })
  2282. .on('mouseout', function (d) {
  2283. var index = d.index;
  2284. if (!$$.config) { return; } // chart is destroyed
  2285. if ($$.hasArcType()) { return; }
  2286. $$.hideXGridFocus();
  2287. $$.hideTooltip();
  2288. // Undo expanded shapes
  2289. $$.unexpandCircles();
  2290. $$.unexpandBars();
  2291. // Call event handler
  2292. $$.main.selectAll('.' + CLASS.shape + '-' + index).each(function (d) {
  2293. config.data_onmouseout.call($$.api, d);
  2294. });
  2295. })
  2296. .on('mousemove', function (d) {
  2297. var selectedData, index = d.index,
  2298. eventRect = $$.svg.select('.' + CLASS.eventRect + '-' + index);
  2299. if ($$.dragging || $$.flowing) { return; } // do nothing while dragging/flowing
  2300. if ($$.hasArcType()) { return; }
  2301. if ($$.isStepType(d) && $$.config.line_step_type === 'step-after' && d3.mouse(this)[0] < $$.x($$.getXValue(d.id, index))) {
  2302. index -= 1;
  2303. }
  2304. // Show tooltip
  2305. selectedData = $$.filterTargetsToShow($$.data.targets).map(function (t) {
  2306. return $$.addName($$.getValueOnIndex(t.values, index));
  2307. });
  2308. if (config.tooltip_grouped) {
  2309. $$.showTooltip(selectedData, this);
  2310. $$.showXGridFocus(selectedData);
  2311. }
  2312. if (config.tooltip_grouped && (!config.data_selection_enabled || config.data_selection_grouped)) {
  2313. return;
  2314. }
  2315. $$.main.selectAll('.' + CLASS.shape + '-' + index)
  2316. .each(function () {
  2317. d3.select(this).classed(CLASS.EXPANDED, true);
  2318. if (config.data_selection_enabled) {
  2319. eventRect.style('cursor', config.data_selection_grouped ? 'pointer' : null);
  2320. }
  2321. if (!config.tooltip_grouped) {
  2322. $$.hideXGridFocus();
  2323. $$.hideTooltip();
  2324. if (!config.data_selection_grouped) {
  2325. $$.unexpandCircles(index);
  2326. $$.unexpandBars(index);
  2327. }
  2328. }
  2329. })
  2330. .filter(function (d) {
  2331. return $$.isWithinShape(this, d);
  2332. })
  2333. .each(function (d) {
  2334. if (config.data_selection_enabled && (config.data_selection_grouped || config.data_selection_isselectable(d))) {
  2335. eventRect.style('cursor', 'pointer');
  2336. }
  2337. if (!config.tooltip_grouped) {
  2338. $$.showTooltip([d], this);
  2339. $$.showXGridFocus([d]);
  2340. if (config.point_focus_expand_enabled) { $$.expandCircles(index, d.id, true); }
  2341. $$.expandBars(index, d.id, true);
  2342. }
  2343. });
  2344. })
  2345. .on('click', function (d) {
  2346. var index = d.index;
  2347. if ($$.hasArcType() || !$$.toggleShape) { return; }
  2348. if ($$.cancelClick) {
  2349. $$.cancelClick = false;
  2350. return;
  2351. }
  2352. if ($$.isStepType(d) && config.line_step_type === 'step-after' && d3.mouse(this)[0] < $$.x($$.getXValue(d.id, index))) {
  2353. index -= 1;
  2354. }
  2355. $$.main.selectAll('.' + CLASS.shape + '-' + index).each(function (d) {
  2356. if (config.data_selection_grouped || $$.isWithinShape(this, d)) {
  2357. $$.toggleShape(this, d, index);
  2358. $$.config.data_onclick.call($$.api, d, this);
  2359. }
  2360. });
  2361. })
  2362. .call(
  2363. config.data_selection_draggable && $$.drag ? (
  2364. d3.behavior.drag().origin(Object)
  2365. .on('drag', function () { $$.drag(d3.mouse(this)); })
  2366. .on('dragstart', function () { $$.dragstart(d3.mouse(this)); })
  2367. .on('dragend', function () { $$.dragend(); })
  2368. ) : function () {}
  2369. );
  2370. };
  2371. c3_chart_internal_fn.generateEventRectsForMultipleXs = function (eventRectEnter) {
  2372. var $$ = this, d3 = $$.d3, config = $$.config;
  2373. function mouseout() {
  2374. $$.svg.select('.' + CLASS.eventRect).style('cursor', null);
  2375. $$.hideXGridFocus();
  2376. $$.hideTooltip();
  2377. $$.unexpandCircles();
  2378. $$.unexpandBars();
  2379. }
  2380. eventRectEnter.append('rect')
  2381. .attr('x', 0)
  2382. .attr('y', 0)
  2383. .attr('width', $$.width)
  2384. .attr('height', $$.height)
  2385. .attr('class', CLASS.eventRect)
  2386. .on('mouseout', function () {
  2387. if (!$$.config) { return; } // chart is destroyed
  2388. if ($$.hasArcType()) { return; }
  2389. mouseout();
  2390. })
  2391. .on('mousemove', function () {
  2392. var targetsToShow = $$.filterTargetsToShow($$.data.targets);
  2393. var mouse, closest, sameXData, selectedData;
  2394. if ($$.dragging) { return; } // do nothing when dragging
  2395. if ($$.hasArcType(targetsToShow)) { return; }
  2396. mouse = d3.mouse(this);
  2397. closest = $$.findClosestFromTargets(targetsToShow, mouse);
  2398. if ($$.mouseover && (!closest || closest.id !== $$.mouseover.id)) {
  2399. config.data_onmouseout.call($$.api, $$.mouseover);
  2400. $$.mouseover = undefined;
  2401. }
  2402. if (! closest) {
  2403. mouseout();
  2404. return;
  2405. }
  2406. if ($$.isScatterType(closest) || !config.tooltip_grouped) {
  2407. sameXData = [closest];
  2408. } else {
  2409. sameXData = $$.filterByX(targetsToShow, closest.x);
  2410. }
  2411. // show tooltip when cursor is close to some point
  2412. selectedData = sameXData.map(function (d) {
  2413. return $$.addName(d);
  2414. });
  2415. $$.showTooltip(selectedData, this);
  2416. // expand points
  2417. if (config.point_focus_expand_enabled) {
  2418. $$.expandCircles(closest.index, closest.id, true);
  2419. }
  2420. $$.expandBars(closest.index, closest.id, true);
  2421. // Show xgrid focus line
  2422. $$.showXGridFocus(selectedData);
  2423. // Show cursor as pointer if point is close to mouse position
  2424. if ($$.isBarType(closest.id) || $$.dist(closest, mouse) < config.point_sensitivity) {
  2425. $$.svg.select('.' + CLASS.eventRect).style('cursor', 'pointer');
  2426. if (!$$.mouseover) {
  2427. config.data_onmouseover.call($$.api, closest);
  2428. $$.mouseover = closest;
  2429. }
  2430. }
  2431. })
  2432. .on('click', function () {
  2433. var targetsToShow = $$.filterTargetsToShow($$.data.targets);
  2434. var mouse, closest;
  2435. if ($$.hasArcType(targetsToShow)) { return; }
  2436. mouse = d3.mouse(this);
  2437. closest = $$.findClosestFromTargets(targetsToShow, mouse);
  2438. if (! closest) { return; }
  2439. // select if selection enabled
  2440. if ($$.isBarType(closest.id) || $$.dist(closest, mouse) < config.point_sensitivity) {
  2441. $$.main.selectAll('.' + CLASS.shapes + $$.getTargetSelectorSuffix(closest.id)).selectAll('.' + CLASS.shape + '-' + closest.index).each(function () {
  2442. if (config.data_selection_grouped || $$.isWithinShape(this, closest)) {
  2443. $$.toggleShape(this, closest, closest.index);
  2444. $$.config.data_onclick.call($$.api, closest, this);
  2445. }
  2446. });
  2447. }
  2448. })
  2449. .call(
  2450. config.data_selection_draggable && $$.drag ? (
  2451. d3.behavior.drag().origin(Object)
  2452. .on('drag', function () { $$.drag(d3.mouse(this)); })
  2453. .on('dragstart', function () { $$.dragstart(d3.mouse(this)); })
  2454. .on('dragend', function () { $$.dragend(); })
  2455. ) : function () {}
  2456. );
  2457. };
  2458. c3_chart_internal_fn.dispatchEvent = function (type, index, mouse) {
  2459. var $$ = this,
  2460. selector = '.' + CLASS.eventRect + (!$$.isMultipleX() ? '-' + index : ''),
  2461. eventRect = $$.main.select(selector).node(),
  2462. box = eventRect.getBoundingClientRect(),
  2463. x = box.left + (mouse ? mouse[0] : 0),
  2464. y = box.top + (mouse ? mouse[1] : 0),
  2465. event = document.createEvent("MouseEvents");
  2466. event.initMouseEvent(type, true, true, window, 0, x, y, x, y,
  2467. false, false, false, false, 0, null);
  2468. eventRect.dispatchEvent(event);
  2469. };
  2470. c3_chart_internal_fn.getCurrentWidth = function () {
  2471. var $$ = this, config = $$.config;
  2472. return config.size_width ? config.size_width : $$.getParentWidth();
  2473. };
  2474. c3_chart_internal_fn.getCurrentHeight = function () {
  2475. var $$ = this, config = $$.config,
  2476. h = config.size_height ? config.size_height : $$.getParentHeight();
  2477. return h > 0 ? h : 320 / ($$.hasType('gauge') && !config.gauge_fullCircle ? 2 : 1);
  2478. };
  2479. c3_chart_internal_fn.getCurrentPaddingTop = function () {
  2480. var $$ = this,
  2481. config = $$.config,
  2482. padding = isValue(config.padding_top) ? config.padding_top : 0;
  2483. if ($$.title && $$.title.node()) {
  2484. padding += $$.getTitlePadding();
  2485. }
  2486. return padding;
  2487. };
  2488. c3_chart_internal_fn.getCurrentPaddingBottom = function () {
  2489. var config = this.config;
  2490. return isValue(config.padding_bottom) ? config.padding_bottom : 0;
  2491. };
  2492. c3_chart_internal_fn.getCurrentPaddingLeft = function (withoutRecompute) {
  2493. var $$ = this, config = $$.config;
  2494. if (isValue(config.padding_left)) {
  2495. return config.padding_left;
  2496. } else if (config.axis_rotated) {
  2497. return !config.axis_x_show ? 1 : Math.max(ceil10($$.getAxisWidthByAxisId('x', withoutRecompute)), 40);
  2498. } else if (!config.axis_y_show || config.axis_y_inner) { // && !config.axis_rotated
  2499. return $$.axis.getYAxisLabelPosition().isOuter ? 30 : 1;
  2500. } else {
  2501. return ceil10($$.getAxisWidthByAxisId('y', withoutRecompute));
  2502. }
  2503. };
  2504. c3_chart_internal_fn.getCurrentPaddingRight = function () {
  2505. var $$ = this, config = $$.config,
  2506. defaultPadding = 10, legendWidthOnRight = $$.isLegendRight ? $$.getLegendWidth() + 20 : 0;
  2507. if (isValue(config.padding_right)) {
  2508. return config.padding_right + 1; // 1 is needed not to hide tick line
  2509. } else if (config.axis_rotated) {
  2510. return defaultPadding + legendWidthOnRight;
  2511. } else if (!config.axis_y2_show || config.axis_y2_inner) { // && !config.axis_rotated
  2512. return 2 + legendWidthOnRight + ($$.axis.getY2AxisLabelPosition().isOuter ? 20 : 0);
  2513. } else {
  2514. return ceil10($$.getAxisWidthByAxisId('y2')) + legendWidthOnRight;
  2515. }
  2516. };
  2517. c3_chart_internal_fn.getParentRectValue = function (key) {
  2518. var parent = this.selectChart.node(), v;
  2519. while (parent && parent.tagName !== 'BODY') {
  2520. try {
  2521. v = parent.getBoundingClientRect()[key];
  2522. } catch(e) {
  2523. if (key === 'width') {
  2524. // In IE in certain cases getBoundingClientRect
  2525. // will cause an "unspecified error"
  2526. v = parent.offsetWidth;
  2527. }
  2528. }
  2529. if (v) {
  2530. break;
  2531. }
  2532. parent = parent.parentNode;
  2533. }
  2534. return v;
  2535. };
  2536. c3_chart_internal_fn.getParentWidth = function () {
  2537. return this.getParentRectValue('width');
  2538. };
  2539. c3_chart_internal_fn.getParentHeight = function () {
  2540. var h = this.selectChart.style('height');
  2541. return h.indexOf('px') > 0 ? +h.replace('px', '') : 0;
  2542. };
  2543. c3_chart_internal_fn.getSvgLeft = function (withoutRecompute) {
  2544. var $$ = this, config = $$.config,
  2545. hasLeftAxisRect = config.axis_rotated || (!config.axis_rotated && !config.axis_y_inner),
  2546. leftAxisClass = config.axis_rotated ? CLASS.axisX : CLASS.axisY,
  2547. leftAxis = $$.main.select('.' + leftAxisClass).node(),
  2548. svgRect = leftAxis && hasLeftAxisRect ? leftAxis.getBoundingClientRect() : {right: 0},
  2549. chartRect = $$.selectChart.node().getBoundingClientRect(),
  2550. hasArc = $$.hasArcType(),
  2551. svgLeft = svgRect.right - chartRect.left - (hasArc ? 0 : $$.getCurrentPaddingLeft(withoutRecompute));
  2552. return svgLeft > 0 ? svgLeft : 0;
  2553. };
  2554. c3_chart_internal_fn.getAxisWidthByAxisId = function (id, withoutRecompute) {
  2555. var $$ = this, position = $$.axis.getLabelPositionById(id);
  2556. return $$.axis.getMaxTickWidth(id, withoutRecompute) + (position.isInner ? 20 : 40);
  2557. };
  2558. c3_chart_internal_fn.getHorizontalAxisHeight = function (axisId) {
  2559. var $$ = this, config = $$.config, h = 30;
  2560. if (axisId === 'x' && !config.axis_x_show) { return 8; }
  2561. if (axisId === 'x' && config.axis_x_height) { return config.axis_x_height; }
  2562. if (axisId === 'y' && !config.axis_y_show) {
  2563. return config.legend_show && !$$.isLegendRight && !$$.isLegendInset ? 10 : 1;
  2564. }
  2565. if (axisId === 'y2' && !config.axis_y2_show) { return $$.rotated_padding_top; }
  2566. // Calculate x axis height when tick rotated
  2567. if (axisId === 'x' && !config.axis_rotated && config.axis_x_tick_rotate) {
  2568. h = 30 + $$.axis.getMaxTickWidth(axisId) * Math.cos(Math.PI * (90 - config.axis_x_tick_rotate) / 180);
  2569. }
  2570. // Calculate y axis height when tick rotated
  2571. if (axisId === 'y' && config.axis_rotated && config.axis_y_tick_rotate) {
  2572. h = 30 + $$.axis.getMaxTickWidth(axisId) * Math.cos(Math.PI * (90 - config.axis_y_tick_rotate) / 180);
  2573. }
  2574. return h + ($$.axis.getLabelPositionById(axisId).isInner ? 0 : 10) + (axisId === 'y2' ? -10 : 0);
  2575. };
  2576. c3_chart_internal_fn.getEventRectWidth = function () {
  2577. return Math.max(0, this.xAxis.tickInterval());
  2578. };
  2579. c3_chart_internal_fn.getShapeIndices = function (typeFilter) {
  2580. var $$ = this, config = $$.config,
  2581. indices = {}, i = 0, j, k;
  2582. $$.filterTargetsToShow($$.data.targets.filter(typeFilter, $$)).forEach(function (d) {
  2583. for (j = 0; j < config.data_groups.length; j++) {
  2584. if (config.data_groups[j].indexOf(d.id) < 0) { continue; }
  2585. for (k = 0; k < config.data_groups[j].length; k++) {
  2586. if (config.data_groups[j][k] in indices) {
  2587. indices[d.id] = indices[config.data_groups[j][k]];
  2588. break;
  2589. }
  2590. }
  2591. }
  2592. if (isUndefined(indices[d.id])) { indices[d.id] = i++; }
  2593. });
  2594. indices.__max__ = i - 1;
  2595. return indices;
  2596. };
  2597. c3_chart_internal_fn.getShapeX = function (offset, targetsNum, indices, isSub) {
  2598. var $$ = this, scale = isSub ? $$.subX : $$.x;
  2599. return function (d) {
  2600. var index = d.id in indices ? indices[d.id] : 0;
  2601. return d.x || d.x === 0 ? scale(d.x) - offset * (targetsNum / 2 - index) : 0;
  2602. };
  2603. };
  2604. c3_chart_internal_fn.getShapeY = function (isSub) {
  2605. var $$ = this;
  2606. return function (d) {
  2607. var scale = isSub ? $$.getSubYScale(d.id) : $$.getYScale(d.id);
  2608. return scale(d.value);
  2609. };
  2610. };
  2611. c3_chart_internal_fn.getShapeOffset = function (typeFilter, indices, isSub) {
  2612. var $$ = this,
  2613. targets = $$.orderTargets($$.filterTargetsToShow($$.data.targets.filter(typeFilter, $$))),
  2614. targetIds = targets.map(function (t) { return t.id; });
  2615. return function (d, i) {
  2616. var scale = isSub ? $$.getSubYScale(d.id) : $$.getYScale(d.id),
  2617. y0 = scale(0), offset = y0;
  2618. targets.forEach(function (t) {
  2619. var values = $$.isStepType(d) ? $$.convertValuesToStep(t.values) : t.values;
  2620. if (t.id === d.id || indices[t.id] !== indices[d.id]) { return; }
  2621. if (targetIds.indexOf(t.id) < targetIds.indexOf(d.id)) {
  2622. // check if the x values line up
  2623. if (typeof values[i] === 'undefined' || +values[i].x !== +d.x) { // "+" for timeseries
  2624. // if not, try to find the value that does line up
  2625. i = -1;
  2626. values.forEach(function (v, j) {
  2627. if (v.x === d.x) {
  2628. i = j;
  2629. }
  2630. });
  2631. }
  2632. if (i in values && values[i].value * d.value >= 0) {
  2633. offset += scale(values[i].value) - y0;
  2634. }
  2635. }
  2636. });
  2637. return offset;
  2638. };
  2639. };
  2640. c3_chart_internal_fn.isWithinShape = function (that, d) {
  2641. var $$ = this,
  2642. shape = $$.d3.select(that), isWithin;
  2643. if (!$$.isTargetToShow(d.id)) {
  2644. isWithin = false;
  2645. }
  2646. else if (that.nodeName === 'circle') {
  2647. isWithin = $$.isStepType(d) ? $$.isWithinStep(that, $$.getYScale(d.id)(d.value)) : $$.isWithinCircle(that, $$.pointSelectR(d) * 1.5);
  2648. }
  2649. else if (that.nodeName === 'path') {
  2650. isWithin = shape.classed(CLASS.bar) ? $$.isWithinBar(that) : true;
  2651. }
  2652. return isWithin;
  2653. };
  2654. c3_chart_internal_fn.getInterpolate = function (d) {
  2655. var $$ = this,
  2656. interpolation = $$.isInterpolationType($$.config.spline_interpolation_type) ? $$.config.spline_interpolation_type : 'cardinal';
  2657. return $$.isSplineType(d) ? interpolation : $$.isStepType(d) ? $$.config.line_step_type : "linear";
  2658. };
  2659. c3_chart_internal_fn.initLine = function () {
  2660. var $$ = this;
  2661. $$.main.select('.' + CLASS.chart).append("g")
  2662. .attr("class", CLASS.chartLines);
  2663. };
  2664. c3_chart_internal_fn.updateTargetsForLine = function (targets) {
  2665. var $$ = this, config = $$.config,
  2666. mainLineUpdate, mainLineEnter,
  2667. classChartLine = $$.classChartLine.bind($$),
  2668. classLines = $$.classLines.bind($$),
  2669. classAreas = $$.classAreas.bind($$),
  2670. classCircles = $$.classCircles.bind($$),
  2671. classFocus = $$.classFocus.bind($$);
  2672. mainLineUpdate = $$.main.select('.' + CLASS.chartLines).selectAll('.' + CLASS.chartLine)
  2673. .data(targets)
  2674. .attr('class', function (d) { return classChartLine(d) + classFocus(d); });
  2675. mainLineEnter = mainLineUpdate.enter().append('g')
  2676. .attr('class', classChartLine)
  2677. .style('opacity', 0)
  2678. .style("pointer-events", "none");
  2679. // Lines for each data
  2680. mainLineEnter.append('g')
  2681. .attr("class", classLines);
  2682. // Areas
  2683. mainLineEnter.append('g')
  2684. .attr('class', classAreas);
  2685. // Circles for each data point on lines
  2686. mainLineEnter.append('g')
  2687. .attr("class", function (d) { return $$.generateClass(CLASS.selectedCircles, d.id); });
  2688. mainLineEnter.append('g')
  2689. .attr("class", classCircles)
  2690. .style("cursor", function (d) { return config.data_selection_isselectable(d) ? "pointer" : null; });
  2691. // Update date for selected circles
  2692. targets.forEach(function (t) {
  2693. $$.main.selectAll('.' + CLASS.selectedCircles + $$.getTargetSelectorSuffix(t.id)).selectAll('.' + CLASS.selectedCircle).each(function (d) {
  2694. d.value = t.values[d.index].value;
  2695. });
  2696. });
  2697. // MEMO: can not keep same color...
  2698. //mainLineUpdate.exit().remove();
  2699. };
  2700. c3_chart_internal_fn.updateLine = function (durationForExit) {
  2701. var $$ = this;
  2702. $$.mainLine = $$.main.selectAll('.' + CLASS.lines).selectAll('.' + CLASS.line)
  2703. .data($$.lineData.bind($$));
  2704. $$.mainLine.enter().append('path')
  2705. .attr('class', $$.classLine.bind($$))
  2706. .style("stroke", $$.color);
  2707. $$.mainLine
  2708. .style("opacity", $$.initialOpacity.bind($$))
  2709. .style('shape-rendering', function (d) { return $$.isStepType(d) ? 'crispEdges' : ''; })
  2710. .attr('transform', null);
  2711. $$.mainLine.exit().transition().duration(durationForExit)
  2712. .style('opacity', 0)
  2713. .remove();
  2714. };
  2715. c3_chart_internal_fn.redrawLine = function (drawLine, withTransition) {
  2716. return [
  2717. (withTransition ? this.mainLine.transition(Math.random().toString()) : this.mainLine)
  2718. .attr("d", drawLine)
  2719. .style("stroke", this.color)
  2720. .style("opacity", 1)
  2721. ];
  2722. };
  2723. c3_chart_internal_fn.generateDrawLine = function (lineIndices, isSub) {
  2724. var $$ = this, config = $$.config,
  2725. line = $$.d3.svg.line(),
  2726. getPoints = $$.generateGetLinePoints(lineIndices, isSub),
  2727. yScaleGetter = isSub ? $$.getSubYScale : $$.getYScale,
  2728. xValue = function (d) { return (isSub ? $$.subxx : $$.xx).call($$, d); },
  2729. yValue = function (d, i) {
  2730. return config.data_groups.length > 0 ? getPoints(d, i)[0][1] : yScaleGetter.call($$, d.id)(d.value);
  2731. };
  2732. line = config.axis_rotated ? line.x(yValue).y(xValue) : line.x(xValue).y(yValue);
  2733. if (!config.line_connectNull) { line = line.defined(function (d) { return d.value != null; }); }
  2734. return function (d) {
  2735. var values = config.line_connectNull ? $$.filterRemoveNull(d.values) : d.values,
  2736. x = isSub ? $$.x : $$.subX, y = yScaleGetter.call($$, d.id), x0 = 0, y0 = 0, path;
  2737. if ($$.isLineType(d)) {
  2738. if (config.data_regions[d.id]) {
  2739. path = $$.lineWithRegions(values, x, y, config.data_regions[d.id]);
  2740. } else {
  2741. if ($$.isStepType(d)) { values = $$.convertValuesToStep(values); }
  2742. path = line.interpolate($$.getInterpolate(d))(values);
  2743. }
  2744. } else {
  2745. if (values[0]) {
  2746. x0 = x(values[0].x);
  2747. y0 = y(values[0].value);
  2748. }
  2749. path = config.axis_rotated ? "M " + y0 + " " + x0 : "M " + x0 + " " + y0;
  2750. }
  2751. return path ? path : "M 0 0";
  2752. };
  2753. };
  2754. c3_chart_internal_fn.generateGetLinePoints = function (lineIndices, isSub) { // partial duplication of generateGetBarPoints
  2755. var $$ = this, config = $$.config,
  2756. lineTargetsNum = lineIndices.__max__ + 1,
  2757. x = $$.getShapeX(0, lineTargetsNum, lineIndices, !!isSub),
  2758. y = $$.getShapeY(!!isSub),
  2759. lineOffset = $$.getShapeOffset($$.isLineType, lineIndices, !!isSub),
  2760. yScale = isSub ? $$.getSubYScale : $$.getYScale;
  2761. return function (d, i) {
  2762. var y0 = yScale.call($$, d.id)(0),
  2763. offset = lineOffset(d, i) || y0, // offset is for stacked area chart
  2764. posX = x(d), posY = y(d);
  2765. // fix posY not to overflow opposite quadrant
  2766. if (config.axis_rotated) {
  2767. if ((0 < d.value && posY < y0) || (d.value < 0 && y0 < posY)) { posY = y0; }
  2768. }
  2769. // 1 point that marks the line position
  2770. return [
  2771. [posX, posY - (y0 - offset)],
  2772. [posX, posY - (y0 - offset)], // needed for compatibility
  2773. [posX, posY - (y0 - offset)], // needed for compatibility
  2774. [posX, posY - (y0 - offset)] // needed for compatibility
  2775. ];
  2776. };
  2777. };
  2778. c3_chart_internal_fn.lineWithRegions = function (d, x, y, _regions) {
  2779. var $$ = this, config = $$.config,
  2780. prev = -1, i, j,
  2781. s = "M", sWithRegion,
  2782. xp, yp, dx, dy, dd, diff, diffx2,
  2783. xOffset = $$.isCategorized() ? 0.5 : 0,
  2784. xValue, yValue,
  2785. regions = [];
  2786. function isWithinRegions(x, regions) {
  2787. var i;
  2788. for (i = 0; i < regions.length; i++) {
  2789. if (regions[i].start < x && x <= regions[i].end) { return true; }
  2790. }
  2791. return false;
  2792. }
  2793. // Check start/end of regions
  2794. if (isDefined(_regions)) {
  2795. for (i = 0; i < _regions.length; i++) {
  2796. regions[i] = {};
  2797. if (isUndefined(_regions[i].start)) {
  2798. regions[i].start = d[0].x;
  2799. } else {
  2800. regions[i].start = $$.isTimeSeries() ? $$.parseDate(_regions[i].start) : _regions[i].start;
  2801. }
  2802. if (isUndefined(_regions[i].end)) {
  2803. regions[i].end = d[d.length - 1].x;
  2804. } else {
  2805. regions[i].end = $$.isTimeSeries() ? $$.parseDate(_regions[i].end) : _regions[i].end;
  2806. }
  2807. }
  2808. }
  2809. // Set scales
  2810. xValue = config.axis_rotated ? function (d) { return y(d.value); } : function (d) { return x(d.x); };
  2811. yValue = config.axis_rotated ? function (d) { return x(d.x); } : function (d) { return y(d.value); };
  2812. // Define svg generator function for region
  2813. function generateM(points) {
  2814. return 'M' + points[0][0] + ' ' + points[0][1] + ' ' + points[1][0] + ' ' + points[1][1];
  2815. }
  2816. if ($$.isTimeSeries()) {
  2817. sWithRegion = function (d0, d1, j, diff) {
  2818. var x0 = d0.x.getTime(), x_diff = d1.x - d0.x,
  2819. xv0 = new Date(x0 + x_diff * j),
  2820. xv1 = new Date(x0 + x_diff * (j + diff)),
  2821. points;
  2822. if (config.axis_rotated) {
  2823. points = [[y(yp(j)), x(xv0)], [y(yp(j + diff)), x(xv1)]];
  2824. } else {
  2825. points = [[x(xv0), y(yp(j))], [x(xv1), y(yp(j + diff))]];
  2826. }
  2827. return generateM(points);
  2828. };
  2829. } else {
  2830. sWithRegion = function (d0, d1, j, diff) {
  2831. var points;
  2832. if (config.axis_rotated) {
  2833. points = [[y(yp(j), true), x(xp(j))], [y(yp(j + diff), true), x(xp(j + diff))]];
  2834. } else {
  2835. points = [[x(xp(j), true), y(yp(j))], [x(xp(j + diff), true), y(yp(j + diff))]];
  2836. }
  2837. return generateM(points);
  2838. };
  2839. }
  2840. // Generate
  2841. for (i = 0; i < d.length; i++) {
  2842. // Draw as normal
  2843. if (isUndefined(regions) || ! isWithinRegions(d[i].x, regions)) {
  2844. s += " " + xValue(d[i]) + " " + yValue(d[i]);
  2845. }
  2846. // Draw with region // TODO: Fix for horizotal charts
  2847. else {
  2848. xp = $$.getScale(d[i - 1].x + xOffset, d[i].x + xOffset, $$.isTimeSeries());
  2849. yp = $$.getScale(d[i - 1].value, d[i].value);
  2850. dx = x(d[i].x) - x(d[i - 1].x);
  2851. dy = y(d[i].value) - y(d[i - 1].value);
  2852. dd = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));
  2853. diff = 2 / dd;
  2854. diffx2 = diff * 2;
  2855. for (j = diff; j <= 1; j += diffx2) {
  2856. s += sWithRegion(d[i - 1], d[i], j, diff);
  2857. }
  2858. }
  2859. prev = d[i].x;
  2860. }
  2861. return s;
  2862. };
  2863. c3_chart_internal_fn.updateArea = function (durationForExit) {
  2864. var $$ = this, d3 = $$.d3;
  2865. $$.mainArea = $$.main.selectAll('.' + CLASS.areas).selectAll('.' + CLASS.area)
  2866. .data($$.lineData.bind($$));
  2867. $$.mainArea.enter().append('path')
  2868. .attr("class", $$.classArea.bind($$))
  2869. .style("fill", $$.color)
  2870. .style("opacity", function () { $$.orgAreaOpacity = +d3.select(this).style('opacity'); return 0; });
  2871. $$.mainArea
  2872. .style("opacity", $$.orgAreaOpacity);
  2873. $$.mainArea.exit().transition().duration(durationForExit)
  2874. .style('opacity', 0)
  2875. .remove();
  2876. };
  2877. c3_chart_internal_fn.redrawArea = function (drawArea, withTransition) {
  2878. return [
  2879. (withTransition ? this.mainArea.transition(Math.random().toString()) : this.mainArea)
  2880. .attr("d", drawArea)
  2881. .style("fill", this.color)
  2882. .style("opacity", this.orgAreaOpacity)
  2883. ];
  2884. };
  2885. c3_chart_internal_fn.generateDrawArea = function (areaIndices, isSub) {
  2886. var $$ = this, config = $$.config, area = $$.d3.svg.area(),
  2887. getPoints = $$.generateGetAreaPoints(areaIndices, isSub),
  2888. yScaleGetter = isSub ? $$.getSubYScale : $$.getYScale,
  2889. xValue = function (d) { return (isSub ? $$.subxx : $$.xx).call($$, d); },
  2890. value0 = function (d, i) {
  2891. return config.data_groups.length > 0 ? getPoints(d, i)[0][1] : yScaleGetter.call($$, d.id)($$.getAreaBaseValue(d.id));
  2892. },
  2893. value1 = function (d, i) {
  2894. return config.data_groups.length > 0 ? getPoints(d, i)[1][1] : yScaleGetter.call($$, d.id)(d.value);
  2895. };
  2896. area = config.axis_rotated ? area.x0(value0).x1(value1).y(xValue) : area.x(xValue).y0(config.area_above ? 0 : value0).y1(value1);
  2897. if (!config.line_connectNull) {
  2898. area = area.defined(function (d) { return d.value !== null; });
  2899. }
  2900. return function (d) {
  2901. var values = config.line_connectNull ? $$.filterRemoveNull(d.values) : d.values,
  2902. x0 = 0, y0 = 0, path;
  2903. if ($$.isAreaType(d)) {
  2904. if ($$.isStepType(d)) { values = $$.convertValuesToStep(values); }
  2905. path = area.interpolate($$.getInterpolate(d))(values);
  2906. } else {
  2907. if (values[0]) {
  2908. x0 = $$.x(values[0].x);
  2909. y0 = $$.getYScale(d.id)(values[0].value);
  2910. }
  2911. path = config.axis_rotated ? "M " + y0 + " " + x0 : "M " + x0 + " " + y0;
  2912. }
  2913. return path ? path : "M 0 0";
  2914. };
  2915. };
  2916. c3_chart_internal_fn.getAreaBaseValue = function () {
  2917. return 0;
  2918. };
  2919. c3_chart_internal_fn.generateGetAreaPoints = function (areaIndices, isSub) { // partial duplication of generateGetBarPoints
  2920. var $$ = this, config = $$.config,
  2921. areaTargetsNum = areaIndices.__max__ + 1,
  2922. x = $$.getShapeX(0, areaTargetsNum, areaIndices, !!isSub),
  2923. y = $$.getShapeY(!!isSub),
  2924. areaOffset = $$.getShapeOffset($$.isAreaType, areaIndices, !!isSub),
  2925. yScale = isSub ? $$.getSubYScale : $$.getYScale;
  2926. return function (d, i) {
  2927. var y0 = yScale.call($$, d.id)(0),
  2928. offset = areaOffset(d, i) || y0, // offset is for stacked area chart
  2929. posX = x(d), posY = y(d);
  2930. // fix posY not to overflow opposite quadrant
  2931. if (config.axis_rotated) {
  2932. if ((0 < d.value && posY < y0) || (d.value < 0 && y0 < posY)) { posY = y0; }
  2933. }
  2934. // 1 point that marks the area position
  2935. return [
  2936. [posX, offset],
  2937. [posX, posY - (y0 - offset)],
  2938. [posX, posY - (y0 - offset)], // needed for compatibility
  2939. [posX, offset] // needed for compatibility
  2940. ];
  2941. };
  2942. };
  2943. c3_chart_internal_fn.updateCircle = function () {
  2944. var $$ = this;
  2945. $$.mainCircle = $$.main.selectAll('.' + CLASS.circles).selectAll('.' + CLASS.circle)
  2946. .data($$.lineOrScatterData.bind($$));
  2947. $$.mainCircle.enter().append("circle")
  2948. .attr("class", $$.classCircle.bind($$))
  2949. .attr("r", $$.pointR.bind($$))
  2950. .style("fill", $$.color);
  2951. $$.mainCircle
  2952. .style("opacity", $$.initialOpacityForCircle.bind($$));
  2953. $$.mainCircle.exit().remove();
  2954. };
  2955. c3_chart_internal_fn.redrawCircle = function (cx, cy, withTransition) {
  2956. var selectedCircles = this.main.selectAll('.' + CLASS.selectedCircle);
  2957. return [
  2958. (withTransition ? this.mainCircle.transition(Math.random().toString()) : this.mainCircle)
  2959. .style('opacity', this.opacityForCircle.bind(this))
  2960. .style("fill", this.color)
  2961. .attr("cx", cx)
  2962. .attr("cy", cy),
  2963. (withTransition ? selectedCircles.transition(Math.random().toString()) : selectedCircles)
  2964. .attr("cx", cx)
  2965. .attr("cy", cy)
  2966. ];
  2967. };
  2968. c3_chart_internal_fn.circleX = function (d) {
  2969. return d.x || d.x === 0 ? this.x(d.x) : null;
  2970. };
  2971. c3_chart_internal_fn.updateCircleY = function () {
  2972. var $$ = this, lineIndices, getPoints;
  2973. if ($$.config.data_groups.length > 0) {
  2974. lineIndices = $$.getShapeIndices($$.isLineType),
  2975. getPoints = $$.generateGetLinePoints(lineIndices);
  2976. $$.circleY = function (d, i) {
  2977. return getPoints(d, i)[0][1];
  2978. };
  2979. } else {
  2980. $$.circleY = function (d) {
  2981. return $$.getYScale(d.id)(d.value);
  2982. };
  2983. }
  2984. };
  2985. c3_chart_internal_fn.getCircles = function (i, id) {
  2986. var $$ = this;
  2987. return (id ? $$.main.selectAll('.' + CLASS.circles + $$.getTargetSelectorSuffix(id)) : $$.main).selectAll('.' + CLASS.circle + (isValue(i) ? '-' + i : ''));
  2988. };
  2989. c3_chart_internal_fn.expandCircles = function (i, id, reset) {
  2990. var $$ = this,
  2991. r = $$.pointExpandedR.bind($$);
  2992. if (reset) { $$.unexpandCircles(); }
  2993. $$.getCircles(i, id)
  2994. .classed(CLASS.EXPANDED, true)
  2995. .attr('r', r);
  2996. };
  2997. c3_chart_internal_fn.unexpandCircles = function (i) {
  2998. var $$ = this,
  2999. r = $$.pointR.bind($$);
  3000. $$.getCircles(i)
  3001. .filter(function () { return $$.d3.select(this).classed(CLASS.EXPANDED); })
  3002. .classed(CLASS.EXPANDED, false)
  3003. .attr('r', r);
  3004. };
  3005. c3_chart_internal_fn.pointR = function (d) {
  3006. var $$ = this, config = $$.config;
  3007. return $$.isStepType(d) ? 0 : (isFunction(config.point_r) ? config.point_r(d) : config.point_r);
  3008. };
  3009. c3_chart_internal_fn.pointExpandedR = function (d) {
  3010. var $$ = this, config = $$.config;
  3011. return config.point_focus_expand_enabled ? (config.point_focus_expand_r ? config.point_focus_expand_r : $$.pointR(d) * 1.75) : $$.pointR(d);
  3012. };
  3013. c3_chart_internal_fn.pointSelectR = function (d) {
  3014. var $$ = this, config = $$.config;
  3015. return isFunction(config.point_select_r) ? config.point_select_r(d) : ((config.point_select_r) ? config.point_select_r : $$.pointR(d) * 4);
  3016. };
  3017. c3_chart_internal_fn.isWithinCircle = function (that, r) {
  3018. var d3 = this.d3,
  3019. mouse = d3.mouse(that), d3_this = d3.select(that),
  3020. cx = +d3_this.attr("cx"), cy = +d3_this.attr("cy");
  3021. return Math.sqrt(Math.pow(cx - mouse[0], 2) + Math.pow(cy - mouse[1], 2)) < r;
  3022. };
  3023. c3_chart_internal_fn.isWithinStep = function (that, y) {
  3024. return Math.abs(y - this.d3.mouse(that)[1]) < 30;
  3025. };
  3026. c3_chart_internal_fn.initBar = function () {
  3027. var $$ = this;
  3028. $$.main.select('.' + CLASS.chart).append("g")
  3029. .attr("class", CLASS.chartBars);
  3030. };
  3031. c3_chart_internal_fn.updateTargetsForBar = function (targets) {
  3032. var $$ = this, config = $$.config,
  3033. mainBarUpdate, mainBarEnter,
  3034. classChartBar = $$.classChartBar.bind($$),
  3035. classBars = $$.classBars.bind($$),
  3036. classFocus = $$.classFocus.bind($$);
  3037. mainBarUpdate = $$.main.select('.' + CLASS.chartBars).selectAll('.' + CLASS.chartBar)
  3038. .data(targets)
  3039. .attr('class', function (d) { return classChartBar(d) + classFocus(d); });
  3040. mainBarEnter = mainBarUpdate.enter().append('g')
  3041. .attr('class', classChartBar)
  3042. .style('opacity', 0)
  3043. .style("pointer-events", "none");
  3044. // Bars for each data
  3045. mainBarEnter.append('g')
  3046. .attr("class", classBars)
  3047. .style("cursor", function (d) { return config.data_selection_isselectable(d) ? "pointer" : null; });
  3048. };
  3049. c3_chart_internal_fn.updateBar = function (durationForExit) {
  3050. var $$ = this,
  3051. barData = $$.barData.bind($$),
  3052. classBar = $$.classBar.bind($$),
  3053. initialOpacity = $$.initialOpacity.bind($$),
  3054. color = function (d) { return $$.color(d.id); };
  3055. $$.mainBar = $$.main.selectAll('.' + CLASS.bars).selectAll('.' + CLASS.bar)
  3056. .data(barData);
  3057. $$.mainBar.enter().append('path')
  3058. .attr("class", classBar)
  3059. .style("stroke", color)
  3060. .style("fill", color);
  3061. $$.mainBar
  3062. .style("opacity", initialOpacity);
  3063. $$.mainBar.exit().transition().duration(durationForExit)
  3064. .style('opacity', 0)
  3065. .remove();
  3066. };
  3067. c3_chart_internal_fn.redrawBar = function (drawBar, withTransition) {
  3068. return [
  3069. (withTransition ? this.mainBar.transition(Math.random().toString()) : this.mainBar)
  3070. .attr('d', drawBar)
  3071. .style("fill", this.color)
  3072. .style("opacity", 1)
  3073. ];
  3074. };
  3075. c3_chart_internal_fn.getBarW = function (axis, barTargetsNum) {
  3076. var $$ = this, config = $$.config,
  3077. w = typeof config.bar_width === 'number' ? config.bar_width : barTargetsNum ? (axis.tickInterval() * config.bar_width_ratio) / barTargetsNum : 0;
  3078. return config.bar_width_max && w > config.bar_width_max ? config.bar_width_max : w;
  3079. };
  3080. c3_chart_internal_fn.getBars = function (i, id) {
  3081. var $$ = this;
  3082. return (id ? $$.main.selectAll('.' + CLASS.bars + $$.getTargetSelectorSuffix(id)) : $$.main).selectAll('.' + CLASS.bar + (isValue(i) ? '-' + i : ''));
  3083. };
  3084. c3_chart_internal_fn.expandBars = function (i, id, reset) {
  3085. var $$ = this;
  3086. if (reset) { $$.unexpandBars(); }
  3087. $$.getBars(i, id).classed(CLASS.EXPANDED, true);
  3088. };
  3089. c3_chart_internal_fn.unexpandBars = function (i) {
  3090. var $$ = this;
  3091. $$.getBars(i).classed(CLASS.EXPANDED, false);
  3092. };
  3093. c3_chart_internal_fn.generateDrawBar = function (barIndices, isSub) {
  3094. var $$ = this, config = $$.config,
  3095. getPoints = $$.generateGetBarPoints(barIndices, isSub);
  3096. return function (d, i) {
  3097. // 4 points that make a bar
  3098. var points = getPoints(d, i);
  3099. // switch points if axis is rotated, not applicable for sub chart
  3100. var indexX = config.axis_rotated ? 1 : 0;
  3101. var indexY = config.axis_rotated ? 0 : 1;
  3102. var path = 'M ' + points[0][indexX] + ',' + points[0][indexY] + ' ' +
  3103. 'L' + points[1][indexX] + ',' + points[1][indexY] + ' ' +
  3104. 'L' + points[2][indexX] + ',' + points[2][indexY] + ' ' +
  3105. 'L' + points[3][indexX] + ',' + points[3][indexY] + ' ' +
  3106. 'z';
  3107. return path;
  3108. };
  3109. };
  3110. c3_chart_internal_fn.generateGetBarPoints = function (barIndices, isSub) {
  3111. var $$ = this,
  3112. axis = isSub ? $$.subXAxis : $$.xAxis,
  3113. barTargetsNum = barIndices.__max__ + 1,
  3114. barW = $$.getBarW(axis, barTargetsNum),
  3115. barX = $$.getShapeX(barW, barTargetsNum, barIndices, !!isSub),
  3116. barY = $$.getShapeY(!!isSub),
  3117. barOffset = $$.getShapeOffset($$.isBarType, barIndices, !!isSub),
  3118. yScale = isSub ? $$.getSubYScale : $$.getYScale;
  3119. return function (d, i) {
  3120. var y0 = yScale.call($$, d.id)(0),
  3121. offset = barOffset(d, i) || y0, // offset is for stacked bar chart
  3122. posX = barX(d), posY = barY(d);
  3123. // fix posY not to overflow opposite quadrant
  3124. if ($$.config.axis_rotated) {
  3125. if ((0 < d.value && posY < y0) || (d.value < 0 && y0 < posY)) { posY = y0; }
  3126. }
  3127. // 4 points that make a bar
  3128. return [
  3129. [posX, offset],
  3130. [posX, posY - (y0 - offset)],
  3131. [posX + barW, posY - (y0 - offset)],
  3132. [posX + barW, offset]
  3133. ];
  3134. };
  3135. };
  3136. c3_chart_internal_fn.isWithinBar = function (that) {
  3137. var mouse = this.d3.mouse(that), box = that.getBoundingClientRect(),
  3138. seg0 = that.pathSegList.getItem(0), seg1 = that.pathSegList.getItem(1),
  3139. x = Math.min(seg0.x, seg1.x), y = Math.min(seg0.y, seg1.y),
  3140. w = box.width, h = box.height, offset = 2,
  3141. sx = x - offset, ex = x + w + offset, sy = y + h + offset, ey = y - offset;
  3142. return sx < mouse[0] && mouse[0] < ex && ey < mouse[1] && mouse[1] < sy;
  3143. };
  3144. c3_chart_internal_fn.initText = function () {
  3145. var $$ = this;
  3146. $$.main.select('.' + CLASS.chart).append("g")
  3147. .attr("class", CLASS.chartTexts);
  3148. $$.mainText = $$.d3.selectAll([]);
  3149. };
  3150. c3_chart_internal_fn.updateTargetsForText = function (targets) {
  3151. var $$ = this, mainTextUpdate, mainTextEnter,
  3152. classChartText = $$.classChartText.bind($$),
  3153. classTexts = $$.classTexts.bind($$),
  3154. classFocus = $$.classFocus.bind($$);
  3155. mainTextUpdate = $$.main.select('.' + CLASS.chartTexts).selectAll('.' + CLASS.chartText)
  3156. .data(targets)
  3157. .attr('class', function (d) { return classChartText(d) + classFocus(d); });
  3158. mainTextEnter = mainTextUpdate.enter().append('g')
  3159. .attr('class', classChartText)
  3160. .style('opacity', 0)
  3161. .style("pointer-events", "none");
  3162. mainTextEnter.append('g')
  3163. .attr('class', classTexts);
  3164. };
  3165. c3_chart_internal_fn.updateText = function (durationForExit) {
  3166. var $$ = this, config = $$.config,
  3167. barOrLineData = $$.barOrLineData.bind($$),
  3168. classText = $$.classText.bind($$);
  3169. $$.mainText = $$.main.selectAll('.' + CLASS.texts).selectAll('.' + CLASS.text)
  3170. .data(barOrLineData);
  3171. $$.mainText.enter().append('text')
  3172. .attr("class", classText)
  3173. .attr('text-anchor', function (d) { return config.axis_rotated ? (d.value < 0 ? 'end' : 'start') : 'middle'; })
  3174. .style("stroke", 'none')
  3175. .style("fill", function (d) { return $$.color(d); })
  3176. .style("fill-opacity", 0);
  3177. $$.mainText
  3178. .text(function (d, i, j) { return $$.dataLabelFormat(d.id)(d.value, d.id, i, j); });
  3179. $$.mainText.exit()
  3180. .transition().duration(durationForExit)
  3181. .style('fill-opacity', 0)
  3182. .remove();
  3183. };
  3184. c3_chart_internal_fn.redrawText = function (xForText, yForText, forFlow, withTransition) {
  3185. return [
  3186. (withTransition ? this.mainText.transition() : this.mainText)
  3187. .attr('x', xForText)
  3188. .attr('y', yForText)
  3189. .style("fill", this.color)
  3190. .style("fill-opacity", forFlow ? 0 : this.opacityForText.bind(this))
  3191. ];
  3192. };
  3193. c3_chart_internal_fn.getTextRect = function (text, cls, element) {
  3194. var dummy = this.d3.select('body').append('div').classed('c3', true),
  3195. svg = dummy.append("svg").style('visibility', 'hidden').style('position', 'fixed').style('top', 0).style('left', 0),
  3196. font = this.d3.select(element).style('font'),
  3197. rect;
  3198. svg.selectAll('.dummy')
  3199. .data([text])
  3200. .enter().append('text')
  3201. .classed(cls ? cls : "", true)
  3202. .style('font', font)
  3203. .text(text)
  3204. .each(function () { rect = this.getBoundingClientRect(); });
  3205. dummy.remove();
  3206. return rect;
  3207. };
  3208. c3_chart_internal_fn.generateXYForText = function (areaIndices, barIndices, lineIndices, forX) {
  3209. var $$ = this,
  3210. getAreaPoints = $$.generateGetAreaPoints(areaIndices, false),
  3211. getBarPoints = $$.generateGetBarPoints(barIndices, false),
  3212. getLinePoints = $$.generateGetLinePoints(lineIndices, false),
  3213. getter = forX ? $$.getXForText : $$.getYForText;
  3214. return function (d, i) {
  3215. var getPoints = $$.isAreaType(d) ? getAreaPoints : $$.isBarType(d) ? getBarPoints : getLinePoints;
  3216. return getter.call($$, getPoints(d, i), d, this);
  3217. };
  3218. };
  3219. c3_chart_internal_fn.getXForText = function (points, d, textElement) {
  3220. var $$ = this,
  3221. box = textElement.getBoundingClientRect(), xPos, padding;
  3222. if ($$.config.axis_rotated) {
  3223. padding = $$.isBarType(d) ? 4 : 6;
  3224. xPos = points[2][1] + padding * (d.value < 0 ? -1 : 1);
  3225. } else {
  3226. xPos = $$.hasType('bar') ? (points[2][0] + points[0][0]) / 2 : points[0][0];
  3227. }
  3228. // show labels regardless of the domain if value is null
  3229. if (d.value === null) {
  3230. if (xPos > $$.width) {
  3231. xPos = $$.width - box.width;
  3232. } else if (xPos < 0) {
  3233. xPos = 4;
  3234. }
  3235. }
  3236. return xPos;
  3237. };
  3238. c3_chart_internal_fn.getYForText = function (points, d, textElement) {
  3239. var $$ = this,
  3240. box = textElement.getBoundingClientRect(),
  3241. yPos;
  3242. if ($$.config.axis_rotated) {
  3243. yPos = (points[0][0] + points[2][0] + box.height * 0.6) / 2;
  3244. } else {
  3245. yPos = points[2][1];
  3246. if (d.value < 0 || (d.value === 0 && !$$.hasPositiveValue)) {
  3247. yPos += box.height;
  3248. if ($$.isBarType(d) && $$.isSafari()) {
  3249. yPos -= 3;
  3250. }
  3251. else if (!$$.isBarType(d) && $$.isChrome()) {
  3252. yPos += 3;
  3253. }
  3254. } else {
  3255. yPos += $$.isBarType(d) ? -3 : -6;
  3256. }
  3257. }
  3258. // show labels regardless of the domain if value is null
  3259. if (d.value === null && !$$.config.axis_rotated) {
  3260. if (yPos < box.height) {
  3261. yPos = box.height;
  3262. } else if (yPos > this.height) {
  3263. yPos = this.height - 4;
  3264. }
  3265. }
  3266. return yPos;
  3267. };
  3268. c3_chart_internal_fn.setTargetType = function (targetIds, type) {
  3269. var $$ = this, config = $$.config;
  3270. $$.mapToTargetIds(targetIds).forEach(function (id) {
  3271. $$.withoutFadeIn[id] = (type === config.data_types[id]);
  3272. config.data_types[id] = type;
  3273. });
  3274. if (!targetIds) {
  3275. config.data_type = type;
  3276. }
  3277. };
  3278. c3_chart_internal_fn.hasType = function (type, targets) {
  3279. var $$ = this, types = $$.config.data_types, has = false;
  3280. targets = targets || $$.data.targets;
  3281. if (targets && targets.length) {
  3282. targets.forEach(function (target) {
  3283. var t = types[target.id];
  3284. if ((t && t.indexOf(type) >= 0) || (!t && type === 'line')) {
  3285. has = true;
  3286. }
  3287. });
  3288. } else if (Object.keys(types).length) {
  3289. Object.keys(types).forEach(function (id) {
  3290. if (types[id] === type) { has = true; }
  3291. });
  3292. } else {
  3293. has = $$.config.data_type === type;
  3294. }
  3295. return has;
  3296. };
  3297. c3_chart_internal_fn.hasArcType = function (targets) {
  3298. return this.hasType('pie', targets) || this.hasType('donut', targets) || this.hasType('gauge', targets);
  3299. };
  3300. c3_chart_internal_fn.isLineType = function (d) {
  3301. var config = this.config, id = isString(d) ? d : d.id;
  3302. return !config.data_types[id] || ['line', 'spline', 'area', 'area-spline', 'step', 'area-step'].indexOf(config.data_types[id]) >= 0;
  3303. };
  3304. c3_chart_internal_fn.isStepType = function (d) {
  3305. var id = isString(d) ? d : d.id;
  3306. return ['step', 'area-step'].indexOf(this.config.data_types[id]) >= 0;
  3307. };
  3308. c3_chart_internal_fn.isSplineType = function (d) {
  3309. var id = isString(d) ? d : d.id;
  3310. return ['spline', 'area-spline'].indexOf(this.config.data_types[id]) >= 0;
  3311. };
  3312. c3_chart_internal_fn.isAreaType = function (d) {
  3313. var id = isString(d) ? d : d.id;
  3314. return ['area', 'area-spline', 'area-step'].indexOf(this.config.data_types[id]) >= 0;
  3315. };
  3316. c3_chart_internal_fn.isBarType = function (d) {
  3317. var id = isString(d) ? d : d.id;
  3318. return this.config.data_types[id] === 'bar';
  3319. };
  3320. c3_chart_internal_fn.isScatterType = function (d) {
  3321. var id = isString(d) ? d : d.id;
  3322. return this.config.data_types[id] === 'scatter';
  3323. };
  3324. c3_chart_internal_fn.isPieType = function (d) {
  3325. var id = isString(d) ? d : d.id;
  3326. return this.config.data_types[id] === 'pie';
  3327. };
  3328. c3_chart_internal_fn.isGaugeType = function (d) {
  3329. var id = isString(d) ? d : d.id;
  3330. return this.config.data_types[id] === 'gauge';
  3331. };
  3332. c3_chart_internal_fn.isDonutType = function (d) {
  3333. var id = isString(d) ? d : d.id;
  3334. return this.config.data_types[id] === 'donut';
  3335. };
  3336. c3_chart_internal_fn.isArcType = function (d) {
  3337. return this.isPieType(d) || this.isDonutType(d) || this.isGaugeType(d);
  3338. };
  3339. c3_chart_internal_fn.lineData = function (d) {
  3340. return this.isLineType(d) ? [d] : [];
  3341. };
  3342. c3_chart_internal_fn.arcData = function (d) {
  3343. return this.isArcType(d.data) ? [d] : [];
  3344. };
  3345. /* not used
  3346. function scatterData(d) {
  3347. return isScatterType(d) ? d.values : [];
  3348. }
  3349. */
  3350. c3_chart_internal_fn.barData = function (d) {
  3351. return this.isBarType(d) ? d.values : [];
  3352. };
  3353. c3_chart_internal_fn.lineOrScatterData = function (d) {
  3354. return this.isLineType(d) || this.isScatterType(d) ? d.values : [];
  3355. };
  3356. c3_chart_internal_fn.barOrLineData = function (d) {
  3357. return this.isBarType(d) || this.isLineType(d) ? d.values : [];
  3358. };
  3359. c3_chart_internal_fn.isInterpolationType = function (type) {
  3360. return ['linear', 'linear-closed', 'basis', 'basis-open', 'basis-closed', 'bundle', 'cardinal', 'cardinal-open', 'cardinal-closed', 'monotone'].indexOf(type) >= 0;
  3361. };
  3362. c3_chart_internal_fn.initGrid = function () {
  3363. var $$ = this, config = $$.config, d3 = $$.d3;
  3364. $$.grid = $$.main.append('g')
  3365. .attr("clip-path", $$.clipPathForGrid)
  3366. .attr('class', CLASS.grid);
  3367. if (config.grid_x_show) {
  3368. $$.grid.append("g").attr("class", CLASS.xgrids);
  3369. }
  3370. if (config.grid_y_show) {
  3371. $$.grid.append('g').attr('class', CLASS.ygrids);
  3372. }
  3373. if (config.grid_focus_show) {
  3374. $$.grid.append('g')
  3375. .attr("class", CLASS.xgridFocus)
  3376. .append('line')
  3377. .attr('class', CLASS.xgridFocus);
  3378. }
  3379. $$.xgrid = d3.selectAll([]);
  3380. if (!config.grid_lines_front) { $$.initGridLines(); }
  3381. };
  3382. c3_chart_internal_fn.initGridLines = function () {
  3383. var $$ = this, d3 = $$.d3;
  3384. $$.gridLines = $$.main.append('g')
  3385. .attr("clip-path", $$.clipPathForGrid)
  3386. .attr('class', CLASS.grid + ' ' + CLASS.gridLines);
  3387. $$.gridLines.append('g').attr("class", CLASS.xgridLines);
  3388. $$.gridLines.append('g').attr('class', CLASS.ygridLines);
  3389. $$.xgridLines = d3.selectAll([]);
  3390. };
  3391. c3_chart_internal_fn.updateXGrid = function (withoutUpdate) {
  3392. var $$ = this, config = $$.config, d3 = $$.d3,
  3393. xgridData = $$.generateGridData(config.grid_x_type, $$.x),
  3394. tickOffset = $$.isCategorized() ? $$.xAxis.tickOffset() : 0;
  3395. $$.xgridAttr = config.axis_rotated ? {
  3396. 'x1': 0,
  3397. 'x2': $$.width,
  3398. 'y1': function (d) { return $$.x(d) - tickOffset; },
  3399. 'y2': function (d) { return $$.x(d) - tickOffset; }
  3400. } : {
  3401. 'x1': function (d) { return $$.x(d) + tickOffset; },
  3402. 'x2': function (d) { return $$.x(d) + tickOffset; },
  3403. 'y1': 0,
  3404. 'y2': $$.height
  3405. };
  3406. $$.xgrid = $$.main.select('.' + CLASS.xgrids).selectAll('.' + CLASS.xgrid)
  3407. .data(xgridData);
  3408. $$.xgrid.enter().append('line').attr("class", CLASS.xgrid);
  3409. if (!withoutUpdate) {
  3410. $$.xgrid.attr($$.xgridAttr)
  3411. .style("opacity", function () { return +d3.select(this).attr(config.axis_rotated ? 'y1' : 'x1') === (config.axis_rotated ? $$.height : 0) ? 0 : 1; });
  3412. }
  3413. $$.xgrid.exit().remove();
  3414. };
  3415. c3_chart_internal_fn.updateYGrid = function () {
  3416. var $$ = this, config = $$.config,
  3417. gridValues = $$.yAxis.tickValues() || $$.y.ticks(config.grid_y_ticks);
  3418. $$.ygrid = $$.main.select('.' + CLASS.ygrids).selectAll('.' + CLASS.ygrid)
  3419. .data(gridValues);
  3420. $$.ygrid.enter().append('line')
  3421. .attr('class', CLASS.ygrid);
  3422. $$.ygrid.attr("x1", config.axis_rotated ? $$.y : 0)
  3423. .attr("x2", config.axis_rotated ? $$.y : $$.width)
  3424. .attr("y1", config.axis_rotated ? 0 : $$.y)
  3425. .attr("y2", config.axis_rotated ? $$.height : $$.y);
  3426. $$.ygrid.exit().remove();
  3427. $$.smoothLines($$.ygrid, 'grid');
  3428. };
  3429. c3_chart_internal_fn.gridTextAnchor = function (d) {
  3430. return d.position ? d.position : "end";
  3431. };
  3432. c3_chart_internal_fn.gridTextDx = function (d) {
  3433. return d.position === 'start' ? 4 : d.position === 'middle' ? 0 : -4;
  3434. };
  3435. c3_chart_internal_fn.xGridTextX = function (d) {
  3436. return d.position === 'start' ? -this.height : d.position === 'middle' ? -this.height / 2 : 0;
  3437. };
  3438. c3_chart_internal_fn.yGridTextX = function (d) {
  3439. return d.position === 'start' ? 0 : d.position === 'middle' ? this.width / 2 : this.width;
  3440. };
  3441. c3_chart_internal_fn.updateGrid = function (duration) {
  3442. var $$ = this, main = $$.main, config = $$.config,
  3443. xgridLine, ygridLine, yv;
  3444. // hide if arc type
  3445. $$.grid.style('visibility', $$.hasArcType() ? 'hidden' : 'visible');
  3446. main.select('line.' + CLASS.xgridFocus).style("visibility", "hidden");
  3447. if (config.grid_x_show) {
  3448. $$.updateXGrid();
  3449. }
  3450. $$.xgridLines = main.select('.' + CLASS.xgridLines).selectAll('.' + CLASS.xgridLine)
  3451. .data(config.grid_x_lines);
  3452. // enter
  3453. xgridLine = $$.xgridLines.enter().append('g')
  3454. .attr("class", function (d) { return CLASS.xgridLine + (d['class'] ? ' ' + d['class'] : ''); });
  3455. xgridLine.append('line')
  3456. .style("opacity", 0);
  3457. xgridLine.append('text')
  3458. .attr("text-anchor", $$.gridTextAnchor)
  3459. .attr("transform", config.axis_rotated ? "" : "rotate(-90)")
  3460. .attr('dx', $$.gridTextDx)
  3461. .attr('dy', -5)
  3462. .style("opacity", 0);
  3463. // udpate
  3464. // done in d3.transition() of the end of this function
  3465. // exit
  3466. $$.xgridLines.exit().transition().duration(duration)
  3467. .style("opacity", 0)
  3468. .remove();
  3469. // Y-Grid
  3470. if (config.grid_y_show) {
  3471. $$.updateYGrid();
  3472. }
  3473. $$.ygridLines = main.select('.' + CLASS.ygridLines).selectAll('.' + CLASS.ygridLine)
  3474. .data(config.grid_y_lines);
  3475. // enter
  3476. ygridLine = $$.ygridLines.enter().append('g')
  3477. .attr("class", function (d) { return CLASS.ygridLine + (d['class'] ? ' ' + d['class'] : ''); });
  3478. ygridLine.append('line')
  3479. .style("opacity", 0);
  3480. ygridLine.append('text')
  3481. .attr("text-anchor", $$.gridTextAnchor)
  3482. .attr("transform", config.axis_rotated ? "rotate(-90)" : "")
  3483. .attr('dx', $$.gridTextDx)
  3484. .attr('dy', -5)
  3485. .style("opacity", 0);
  3486. // update
  3487. yv = $$.yv.bind($$);
  3488. $$.ygridLines.select('line')
  3489. .transition().duration(duration)
  3490. .attr("x1", config.axis_rotated ? yv : 0)
  3491. .attr("x2", config.axis_rotated ? yv : $$.width)
  3492. .attr("y1", config.axis_rotated ? 0 : yv)
  3493. .attr("y2", config.axis_rotated ? $$.height : yv)
  3494. .style("opacity", 1);
  3495. $$.ygridLines.select('text')
  3496. .transition().duration(duration)
  3497. .attr("x", config.axis_rotated ? $$.xGridTextX.bind($$) : $$.yGridTextX.bind($$))
  3498. .attr("y", yv)
  3499. .text(function (d) { return d.text; })
  3500. .style("opacity", 1);
  3501. // exit
  3502. $$.ygridLines.exit().transition().duration(duration)
  3503. .style("opacity", 0)
  3504. .remove();
  3505. };
  3506. c3_chart_internal_fn.redrawGrid = function (withTransition) {
  3507. var $$ = this, config = $$.config, xv = $$.xv.bind($$),
  3508. lines = $$.xgridLines.select('line'),
  3509. texts = $$.xgridLines.select('text');
  3510. return [
  3511. (withTransition ? lines.transition() : lines)
  3512. .attr("x1", config.axis_rotated ? 0 : xv)
  3513. .attr("x2", config.axis_rotated ? $$.width : xv)
  3514. .attr("y1", config.axis_rotated ? xv : 0)
  3515. .attr("y2", config.axis_rotated ? xv : $$.height)
  3516. .style("opacity", 1),
  3517. (withTransition ? texts.transition() : texts)
  3518. .attr("x", config.axis_rotated ? $$.yGridTextX.bind($$) : $$.xGridTextX.bind($$))
  3519. .attr("y", xv)
  3520. .text(function (d) { return d.text; })
  3521. .style("opacity", 1)
  3522. ];
  3523. };
  3524. c3_chart_internal_fn.showXGridFocus = function (selectedData) {
  3525. var $$ = this, config = $$.config,
  3526. dataToShow = selectedData.filter(function (d) { return d && isValue(d.value); }),
  3527. focusEl = $$.main.selectAll('line.' + CLASS.xgridFocus),
  3528. xx = $$.xx.bind($$);
  3529. if (! config.tooltip_show) { return; }
  3530. // Hide when scatter plot exists
  3531. if ($$.hasType('scatter') || $$.hasArcType()) { return; }
  3532. focusEl
  3533. .style("visibility", "visible")
  3534. .data([dataToShow[0]])
  3535. .attr(config.axis_rotated ? 'y1' : 'x1', xx)
  3536. .attr(config.axis_rotated ? 'y2' : 'x2', xx);
  3537. $$.smoothLines(focusEl, 'grid');
  3538. };
  3539. c3_chart_internal_fn.hideXGridFocus = function () {
  3540. this.main.select('line.' + CLASS.xgridFocus).style("visibility", "hidden");
  3541. };
  3542. c3_chart_internal_fn.updateXgridFocus = function () {
  3543. var $$ = this, config = $$.config;
  3544. $$.main.select('line.' + CLASS.xgridFocus)
  3545. .attr("x1", config.axis_rotated ? 0 : -10)
  3546. .attr("x2", config.axis_rotated ? $$.width : -10)
  3547. .attr("y1", config.axis_rotated ? -10 : 0)
  3548. .attr("y2", config.axis_rotated ? -10 : $$.height);
  3549. };
  3550. c3_chart_internal_fn.generateGridData = function (type, scale) {
  3551. var $$ = this,
  3552. gridData = [], xDomain, firstYear, lastYear, i,
  3553. tickNum = $$.main.select("." + CLASS.axisX).selectAll('.tick').size();
  3554. if (type === 'year') {
  3555. xDomain = $$.getXDomain();
  3556. firstYear = xDomain[0].getFullYear();
  3557. lastYear = xDomain[1].getFullYear();
  3558. for (i = firstYear; i <= lastYear; i++) {
  3559. gridData.push(new Date(i + '-01-01 00:00:00'));
  3560. }
  3561. } else {
  3562. gridData = scale.ticks(10);
  3563. if (gridData.length > tickNum) { // use only int
  3564. gridData = gridData.filter(function (d) { return ("" + d).indexOf('.') < 0; });
  3565. }
  3566. }
  3567. return gridData;
  3568. };
  3569. c3_chart_internal_fn.getGridFilterToRemove = function (params) {
  3570. return params ? function (line) {
  3571. var found = false;
  3572. [].concat(params).forEach(function (param) {
  3573. if ((('value' in param && line.value === param.value) || ('class' in param && line['class'] === param['class']))) {
  3574. found = true;
  3575. }
  3576. });
  3577. return found;
  3578. } : function () { return true; };
  3579. };
  3580. c3_chart_internal_fn.removeGridLines = function (params, forX) {
  3581. var $$ = this, config = $$.config,
  3582. toRemove = $$.getGridFilterToRemove(params),
  3583. toShow = function (line) { return !toRemove(line); },
  3584. classLines = forX ? CLASS.xgridLines : CLASS.ygridLines,
  3585. classLine = forX ? CLASS.xgridLine : CLASS.ygridLine;
  3586. $$.main.select('.' + classLines).selectAll('.' + classLine).filter(toRemove)
  3587. .transition().duration(config.transition_duration)
  3588. .style('opacity', 0).remove();
  3589. if (forX) {
  3590. config.grid_x_lines = config.grid_x_lines.filter(toShow);
  3591. } else {
  3592. config.grid_y_lines = config.grid_y_lines.filter(toShow);
  3593. }
  3594. };
  3595. c3_chart_internal_fn.initTooltip = function () {
  3596. var $$ = this, config = $$.config, i;
  3597. $$.tooltip = $$.selectChart
  3598. .style("position", "relative")
  3599. .append("div")
  3600. .attr('class', CLASS.tooltipContainer)
  3601. .style("position", "absolute")
  3602. .style("pointer-events", "none")
  3603. .style("display", "none");
  3604. // Show tooltip if needed
  3605. if (config.tooltip_init_show) {
  3606. if ($$.isTimeSeries() && isString(config.tooltip_init_x)) {
  3607. config.tooltip_init_x = $$.parseDate(config.tooltip_init_x);
  3608. for (i = 0; i < $$.data.targets[0].values.length; i++) {
  3609. if (($$.data.targets[0].values[i].x - config.tooltip_init_x) === 0) { break; }
  3610. }
  3611. config.tooltip_init_x = i;
  3612. }
  3613. $$.tooltip.html(config.tooltip_contents.call($$, $$.data.targets.map(function (d) {
  3614. return $$.addName(d.values[config.tooltip_init_x]);
  3615. }), $$.axis.getXAxisTickFormat(), $$.getYFormat($$.hasArcType()), $$.color));
  3616. $$.tooltip.style("top", config.tooltip_init_position.top)
  3617. .style("left", config.tooltip_init_position.left)
  3618. .style("display", "block");
  3619. }
  3620. };
  3621. c3_chart_internal_fn.getTooltipContent = function (d, defaultTitleFormat, defaultValueFormat, color) {
  3622. var $$ = this, config = $$.config,
  3623. titleFormat = config.tooltip_format_title || defaultTitleFormat,
  3624. nameFormat = config.tooltip_format_name || function (name) { return name; },
  3625. valueFormat = config.tooltip_format_value || defaultValueFormat,
  3626. text, i, title, value, name, bgcolor,
  3627. orderAsc = $$.isOrderAsc();
  3628. if (config.data_groups.length === 0) {
  3629. d.sort(function(a, b){
  3630. var v1 = a ? a.value : null, v2 = b ? b.value : null;
  3631. return orderAsc ? v1 - v2 : v2 - v1;
  3632. });
  3633. } else {
  3634. var ids = $$.orderTargets($$.data.targets).map(function (i) {
  3635. return i.id;
  3636. });
  3637. d.sort(function(a, b) {
  3638. var v1 = a ? a.value : null, v2 = b ? b.value : null;
  3639. if (v1 > 0 && v2 > 0) {
  3640. v1 = a ? ids.indexOf(a.id) : null;
  3641. v2 = b ? ids.indexOf(b.id) : null;
  3642. }
  3643. return orderAsc ? v1 - v2 : v2 - v1;
  3644. });
  3645. }
  3646. for (i = 0; i < d.length; i++) {
  3647. if (! (d[i] && (d[i].value || d[i].value === 0))) { continue; }
  3648. if (! text) {
  3649. title = sanitise(titleFormat ? titleFormat(d[i].x) : d[i].x);
  3650. text = "<table class='" + $$.CLASS.tooltip + "'>" + (title || title === 0 ? "<tr><th colspan='2'>" + title + "</th></tr>" : "");
  3651. }
  3652. value = sanitise(valueFormat(d[i].value, d[i].ratio, d[i].id, d[i].index, d));
  3653. if (value !== undefined) {
  3654. // Skip elements when their name is set to null
  3655. if (d[i].name === null) { continue; }
  3656. name = sanitise(nameFormat(d[i].name, d[i].ratio, d[i].id, d[i].index));
  3657. bgcolor = $$.levelColor ? $$.levelColor(d[i].value) : color(d[i].id);
  3658. text += "<tr class='" + $$.CLASS.tooltipName + "-" + $$.getTargetSelectorSuffix(d[i].id) + "'>";
  3659. text += "<td class='name'><span style='background-color:" + bgcolor + "'></span>" + name + "</td>";
  3660. text += "<td class='value'>" + value + "</td>";
  3661. text += "</tr>";
  3662. }
  3663. }
  3664. return text + "</table>";
  3665. };
  3666. c3_chart_internal_fn.tooltipPosition = function (dataToShow, tWidth, tHeight, element) {
  3667. var $$ = this, config = $$.config, d3 = $$.d3;
  3668. var svgLeft, tooltipLeft, tooltipRight, tooltipTop, chartRight;
  3669. var forArc = $$.hasArcType(),
  3670. mouse = d3.mouse(element);
  3671. // Determin tooltip position
  3672. if (forArc) {
  3673. tooltipLeft = (($$.width - ($$.isLegendRight ? $$.getLegendWidth() : 0)) / 2) + mouse[0];
  3674. tooltipTop = ($$.height / 2) + mouse[1] + 20;
  3675. } else {
  3676. svgLeft = $$.getSvgLeft(true);
  3677. if (config.axis_rotated) {
  3678. tooltipLeft = svgLeft + mouse[0] + 100;
  3679. tooltipRight = tooltipLeft + tWidth;
  3680. chartRight = $$.currentWidth - $$.getCurrentPaddingRight();
  3681. tooltipTop = $$.x(dataToShow[0].x) + 20;
  3682. } else {
  3683. tooltipLeft = svgLeft + $$.getCurrentPaddingLeft(true) + $$.x(dataToShow[0].x) + 20;
  3684. tooltipRight = tooltipLeft + tWidth;
  3685. chartRight = svgLeft + $$.currentWidth - $$.getCurrentPaddingRight();
  3686. tooltipTop = mouse[1] + 15;
  3687. }
  3688. if (tooltipRight > chartRight) {
  3689. // 20 is needed for Firefox to keep tooltip width
  3690. tooltipLeft -= tooltipRight - chartRight + 20;
  3691. }
  3692. if (tooltipTop + tHeight > $$.currentHeight) {
  3693. tooltipTop -= tHeight + 30;
  3694. }
  3695. }
  3696. if (tooltipTop < 0) {
  3697. tooltipTop = 0;
  3698. }
  3699. return {top: tooltipTop, left: tooltipLeft};
  3700. };
  3701. c3_chart_internal_fn.showTooltip = function (selectedData, element) {
  3702. var $$ = this, config = $$.config;
  3703. var tWidth, tHeight, position;
  3704. var forArc = $$.hasArcType(),
  3705. dataToShow = selectedData.filter(function (d) { return d && isValue(d.value); }),
  3706. positionFunction = config.tooltip_position || c3_chart_internal_fn.tooltipPosition;
  3707. if (dataToShow.length === 0 || !config.tooltip_show) {
  3708. return;
  3709. }
  3710. $$.tooltip.html(config.tooltip_contents.call($$, selectedData, $$.axis.getXAxisTickFormat(), $$.getYFormat(forArc), $$.color)).style("display", "block");
  3711. // Get tooltip dimensions
  3712. tWidth = $$.tooltip.property('offsetWidth');
  3713. tHeight = $$.tooltip.property('offsetHeight');
  3714. position = positionFunction.call(this, dataToShow, tWidth, tHeight, element);
  3715. // Set tooltip
  3716. $$.tooltip
  3717. .style("top", position.top + "px")
  3718. .style("left", position.left + 'px');
  3719. };
  3720. c3_chart_internal_fn.hideTooltip = function () {
  3721. this.tooltip.style("display", "none");
  3722. };
  3723. c3_chart_internal_fn.initLegend = function () {
  3724. var $$ = this;
  3725. $$.legendItemTextBox = {};
  3726. $$.legendHasRendered = false;
  3727. $$.legend = $$.svg.append("g").attr("transform", $$.getTranslate('legend'));
  3728. if (!$$.config.legend_show) {
  3729. $$.legend.style('visibility', 'hidden');
  3730. $$.hiddenLegendIds = $$.mapToIds($$.data.targets);
  3731. return;
  3732. }
  3733. // MEMO: call here to update legend box and tranlate for all
  3734. // MEMO: translate will be upated by this, so transform not needed in updateLegend()
  3735. $$.updateLegendWithDefaults();
  3736. };
  3737. c3_chart_internal_fn.updateLegendWithDefaults = function () {
  3738. var $$ = this;
  3739. $$.updateLegend($$.mapToIds($$.data.targets), {withTransform: false, withTransitionForTransform: false, withTransition: false});
  3740. };
  3741. c3_chart_internal_fn.updateSizeForLegend = function (legendHeight, legendWidth) {
  3742. var $$ = this, config = $$.config, insetLegendPosition = {
  3743. top: $$.isLegendTop ? $$.getCurrentPaddingTop() + config.legend_inset_y + 5.5 : $$.currentHeight - legendHeight - $$.getCurrentPaddingBottom() - config.legend_inset_y,
  3744. left: $$.isLegendLeft ? $$.getCurrentPaddingLeft() + config.legend_inset_x + 0.5 : $$.currentWidth - legendWidth - $$.getCurrentPaddingRight() - config.legend_inset_x + 0.5
  3745. };
  3746. $$.margin3 = {
  3747. top: $$.isLegendRight ? 0 : $$.isLegendInset ? insetLegendPosition.top : $$.currentHeight - legendHeight,
  3748. right: NaN,
  3749. bottom: 0,
  3750. left: $$.isLegendRight ? $$.currentWidth - legendWidth : $$.isLegendInset ? insetLegendPosition.left : 0
  3751. };
  3752. };
  3753. c3_chart_internal_fn.transformLegend = function (withTransition) {
  3754. var $$ = this;
  3755. (withTransition ? $$.legend.transition() : $$.legend).attr("transform", $$.getTranslate('legend'));
  3756. };
  3757. c3_chart_internal_fn.updateLegendStep = function (step) {
  3758. this.legendStep = step;
  3759. };
  3760. c3_chart_internal_fn.updateLegendItemWidth = function (w) {
  3761. this.legendItemWidth = w;
  3762. };
  3763. c3_chart_internal_fn.updateLegendItemHeight = function (h) {
  3764. this.legendItemHeight = h;
  3765. };
  3766. c3_chart_internal_fn.getLegendWidth = function () {
  3767. var $$ = this;
  3768. return $$.config.legend_show ? $$.isLegendRight || $$.isLegendInset ? $$.legendItemWidth * ($$.legendStep + 1) : $$.currentWidth : 0;
  3769. };
  3770. c3_chart_internal_fn.getLegendHeight = function () {
  3771. var $$ = this, h = 0;
  3772. if ($$.config.legend_show) {
  3773. if ($$.isLegendRight) {
  3774. h = $$.currentHeight;
  3775. } else {
  3776. h = Math.max(20, $$.legendItemHeight) * ($$.legendStep + 1);
  3777. }
  3778. }
  3779. return h;
  3780. };
  3781. c3_chart_internal_fn.opacityForLegend = function (legendItem) {
  3782. return legendItem.classed(CLASS.legendItemHidden) ? null : 1;
  3783. };
  3784. c3_chart_internal_fn.opacityForUnfocusedLegend = function (legendItem) {
  3785. return legendItem.classed(CLASS.legendItemHidden) ? null : 0.3;
  3786. };
  3787. c3_chart_internal_fn.toggleFocusLegend = function (targetIds, focus) {
  3788. var $$ = this;
  3789. targetIds = $$.mapToTargetIds(targetIds);
  3790. $$.legend.selectAll('.' + CLASS.legendItem)
  3791. .filter(function (id) { return targetIds.indexOf(id) >= 0; })
  3792. .classed(CLASS.legendItemFocused, focus)
  3793. .transition().duration(100)
  3794. .style('opacity', function () {
  3795. var opacity = focus ? $$.opacityForLegend : $$.opacityForUnfocusedLegend;
  3796. return opacity.call($$, $$.d3.select(this));
  3797. });
  3798. };
  3799. c3_chart_internal_fn.revertLegend = function () {
  3800. var $$ = this, d3 = $$.d3;
  3801. $$.legend.selectAll('.' + CLASS.legendItem)
  3802. .classed(CLASS.legendItemFocused, false)
  3803. .transition().duration(100)
  3804. .style('opacity', function () { return $$.opacityForLegend(d3.select(this)); });
  3805. };
  3806. c3_chart_internal_fn.showLegend = function (targetIds) {
  3807. var $$ = this, config = $$.config;
  3808. if (!config.legend_show) {
  3809. config.legend_show = true;
  3810. $$.legend.style('visibility', 'visible');
  3811. if (!$$.legendHasRendered) {
  3812. $$.updateLegendWithDefaults();
  3813. }
  3814. }
  3815. $$.removeHiddenLegendIds(targetIds);
  3816. $$.legend.selectAll($$.selectorLegends(targetIds))
  3817. .style('visibility', 'visible')
  3818. .transition()
  3819. .style('opacity', function () { return $$.opacityForLegend($$.d3.select(this)); });
  3820. };
  3821. c3_chart_internal_fn.hideLegend = function (targetIds) {
  3822. var $$ = this, config = $$.config;
  3823. if (config.legend_show && isEmpty(targetIds)) {
  3824. config.legend_show = false;
  3825. $$.legend.style('visibility', 'hidden');
  3826. }
  3827. $$.addHiddenLegendIds(targetIds);
  3828. $$.legend.selectAll($$.selectorLegends(targetIds))
  3829. .style('opacity', 0)
  3830. .style('visibility', 'hidden');
  3831. };
  3832. c3_chart_internal_fn.clearLegendItemTextBoxCache = function () {
  3833. this.legendItemTextBox = {};
  3834. };
  3835. c3_chart_internal_fn.updateLegend = function (targetIds, options, transitions) {
  3836. var $$ = this, config = $$.config;
  3837. var xForLegend, xForLegendText, xForLegendRect, yForLegend, yForLegendText, yForLegendRect, x1ForLegendTile, x2ForLegendTile, yForLegendTile;
  3838. var paddingTop = 4, paddingRight = 10, maxWidth = 0, maxHeight = 0, posMin = 10, tileWidth = config.legend_item_tile_width + 5;
  3839. var l, totalLength = 0, offsets = {}, widths = {}, heights = {}, margins = [0], steps = {}, step = 0;
  3840. var withTransition, withTransitionForTransform;
  3841. var texts, rects, tiles, background;
  3842. // Skip elements when their name is set to null
  3843. targetIds = targetIds.filter(function(id) {
  3844. return !isDefined(config.data_names[id]) || config.data_names[id] !== null;
  3845. });
  3846. options = options || {};
  3847. withTransition = getOption(options, "withTransition", true);
  3848. withTransitionForTransform = getOption(options, "withTransitionForTransform", true);
  3849. function getTextBox(textElement, id) {
  3850. if (!$$.legendItemTextBox[id]) {
  3851. $$.legendItemTextBox[id] = $$.getTextRect(textElement.textContent, CLASS.legendItem, textElement);
  3852. }
  3853. return $$.legendItemTextBox[id];
  3854. }
  3855. function updatePositions(textElement, id, index) {
  3856. var reset = index === 0, isLast = index === targetIds.length - 1,
  3857. box = getTextBox(textElement, id),
  3858. itemWidth = box.width + tileWidth + (isLast && !($$.isLegendRight || $$.isLegendInset) ? 0 : paddingRight) + config.legend_padding,
  3859. itemHeight = box.height + paddingTop,
  3860. itemLength = $$.isLegendRight || $$.isLegendInset ? itemHeight : itemWidth,
  3861. areaLength = $$.isLegendRight || $$.isLegendInset ? $$.getLegendHeight() : $$.getLegendWidth(),
  3862. margin, maxLength;
  3863. // MEMO: care about condifion of step, totalLength
  3864. function updateValues(id, withoutStep) {
  3865. if (!withoutStep) {
  3866. margin = (areaLength - totalLength - itemLength) / 2;
  3867. if (margin < posMin) {
  3868. margin = (areaLength - itemLength) / 2;
  3869. totalLength = 0;
  3870. step++;
  3871. }
  3872. }
  3873. steps[id] = step;
  3874. margins[step] = $$.isLegendInset ? 10 : margin;
  3875. offsets[id] = totalLength;
  3876. totalLength += itemLength;
  3877. }
  3878. if (reset) {
  3879. totalLength = 0;
  3880. step = 0;
  3881. maxWidth = 0;
  3882. maxHeight = 0;
  3883. }
  3884. if (config.legend_show && !$$.isLegendToShow(id)) {
  3885. widths[id] = heights[id] = steps[id] = offsets[id] = 0;
  3886. return;
  3887. }
  3888. widths[id] = itemWidth;
  3889. heights[id] = itemHeight;
  3890. if (!maxWidth || itemWidth >= maxWidth) { maxWidth = itemWidth; }
  3891. if (!maxHeight || itemHeight >= maxHeight) { maxHeight = itemHeight; }
  3892. maxLength = $$.isLegendRight || $$.isLegendInset ? maxHeight : maxWidth;
  3893. if (config.legend_equally) {
  3894. Object.keys(widths).forEach(function (id) { widths[id] = maxWidth; });
  3895. Object.keys(heights).forEach(function (id) { heights[id] = maxHeight; });
  3896. margin = (areaLength - maxLength * targetIds.length) / 2;
  3897. if (margin < posMin) {
  3898. totalLength = 0;
  3899. step = 0;
  3900. targetIds.forEach(function (id) { updateValues(id); });
  3901. }
  3902. else {
  3903. updateValues(id, true);
  3904. }
  3905. } else {
  3906. updateValues(id);
  3907. }
  3908. }
  3909. if ($$.isLegendInset) {
  3910. step = config.legend_inset_step ? config.legend_inset_step : targetIds.length;
  3911. $$.updateLegendStep(step);
  3912. }
  3913. if ($$.isLegendRight) {
  3914. xForLegend = function (id) { return maxWidth * steps[id]; };
  3915. yForLegend = function (id) { return margins[steps[id]] + offsets[id]; };
  3916. } else if ($$.isLegendInset) {
  3917. xForLegend = function (id) { return maxWidth * steps[id] + 10; };
  3918. yForLegend = function (id) { return margins[steps[id]] + offsets[id]; };
  3919. } else {
  3920. xForLegend = function (id) { return margins[steps[id]] + offsets[id]; };
  3921. yForLegend = function (id) { return maxHeight * steps[id]; };
  3922. }
  3923. xForLegendText = function (id, i) { return xForLegend(id, i) + 4 + config.legend_item_tile_width; };
  3924. yForLegendText = function (id, i) { return yForLegend(id, i) + 9; };
  3925. xForLegendRect = function (id, i) { return xForLegend(id, i); };
  3926. yForLegendRect = function (id, i) { return yForLegend(id, i) - 5; };
  3927. x1ForLegendTile = function (id, i) { return xForLegend(id, i) - 2; };
  3928. x2ForLegendTile = function (id, i) { return xForLegend(id, i) - 2 + config.legend_item_tile_width; };
  3929. yForLegendTile = function (id, i) { return yForLegend(id, i) + 4; };
  3930. // Define g for legend area
  3931. l = $$.legend.selectAll('.' + CLASS.legendItem)
  3932. .data(targetIds)
  3933. .enter().append('g')
  3934. .attr('class', function (id) { return $$.generateClass(CLASS.legendItem, id); })
  3935. .style('visibility', function (id) { return $$.isLegendToShow(id) ? 'visible' : 'hidden'; })
  3936. .style('cursor', 'pointer')
  3937. .on('click', function (id) {
  3938. if (config.legend_item_onclick) {
  3939. config.legend_item_onclick.call($$, id);
  3940. } else {
  3941. if ($$.d3.event.altKey) {
  3942. $$.api.hide();
  3943. $$.api.show(id);
  3944. } else {
  3945. $$.api.toggle(id);
  3946. $$.isTargetToShow(id) ? $$.api.focus(id) : $$.api.revert();
  3947. }
  3948. }
  3949. })
  3950. .on('mouseover', function (id) {
  3951. if (config.legend_item_onmouseover) {
  3952. config.legend_item_onmouseover.call($$, id);
  3953. }
  3954. else {
  3955. $$.d3.select(this).classed(CLASS.legendItemFocused, true);
  3956. if (!$$.transiting && $$.isTargetToShow(id)) {
  3957. $$.api.focus(id);
  3958. }
  3959. }
  3960. })
  3961. .on('mouseout', function (id) {
  3962. if (config.legend_item_onmouseout) {
  3963. config.legend_item_onmouseout.call($$, id);
  3964. }
  3965. else {
  3966. $$.d3.select(this).classed(CLASS.legendItemFocused, false);
  3967. $$.api.revert();
  3968. }
  3969. });
  3970. l.append('text')
  3971. .text(function (id) { return isDefined(config.data_names[id]) ? config.data_names[id] : id; })
  3972. .each(function (id, i) { updatePositions(this, id, i); })
  3973. .style("pointer-events", "none")
  3974. .attr('x', $$.isLegendRight || $$.isLegendInset ? xForLegendText : -200)
  3975. .attr('y', $$.isLegendRight || $$.isLegendInset ? -200 : yForLegendText);
  3976. l.append('rect')
  3977. .attr("class", CLASS.legendItemEvent)
  3978. .style('fill-opacity', 0)
  3979. .attr('x', $$.isLegendRight || $$.isLegendInset ? xForLegendRect : -200)
  3980. .attr('y', $$.isLegendRight || $$.isLegendInset ? -200 : yForLegendRect);
  3981. l.append('line')
  3982. .attr('class', CLASS.legendItemTile)
  3983. .style('stroke', $$.color)
  3984. .style("pointer-events", "none")
  3985. .attr('x1', $$.isLegendRight || $$.isLegendInset ? x1ForLegendTile : -200)
  3986. .attr('y1', $$.isLegendRight || $$.isLegendInset ? -200 : yForLegendTile)
  3987. .attr('x2', $$.isLegendRight || $$.isLegendInset ? x2ForLegendTile : -200)
  3988. .attr('y2', $$.isLegendRight || $$.isLegendInset ? -200 : yForLegendTile)
  3989. .attr('stroke-width', config.legend_item_tile_height);
  3990. // Set background for inset legend
  3991. background = $$.legend.select('.' + CLASS.legendBackground + ' rect');
  3992. if ($$.isLegendInset && maxWidth > 0 && background.size() === 0) {
  3993. background = $$.legend.insert('g', '.' + CLASS.legendItem)
  3994. .attr("class", CLASS.legendBackground)
  3995. .append('rect');
  3996. }
  3997. texts = $$.legend.selectAll('text')
  3998. .data(targetIds)
  3999. .text(function (id) { return isDefined(config.data_names[id]) ? config.data_names[id] : id; }) // MEMO: needed for update
  4000. .each(function (id, i) { updatePositions(this, id, i); });
  4001. (withTransition ? texts.transition() : texts)
  4002. .attr('x', xForLegendText)
  4003. .attr('y', yForLegendText);
  4004. rects = $$.legend.selectAll('rect.' + CLASS.legendItemEvent)
  4005. .data(targetIds);
  4006. (withTransition ? rects.transition() : rects)
  4007. .attr('width', function (id) { return widths[id]; })
  4008. .attr('height', function (id) { return heights[id]; })
  4009. .attr('x', xForLegendRect)
  4010. .attr('y', yForLegendRect);
  4011. tiles = $$.legend.selectAll('line.' + CLASS.legendItemTile)
  4012. .data(targetIds);
  4013. (withTransition ? tiles.transition() : tiles)
  4014. .style('stroke', $$.color)
  4015. .attr('x1', x1ForLegendTile)
  4016. .attr('y1', yForLegendTile)
  4017. .attr('x2', x2ForLegendTile)
  4018. .attr('y2', yForLegendTile);
  4019. if (background) {
  4020. (withTransition ? background.transition() : background)
  4021. .attr('height', $$.getLegendHeight() - 12)
  4022. .attr('width', maxWidth * (step + 1) + 10);
  4023. }
  4024. // toggle legend state
  4025. $$.legend.selectAll('.' + CLASS.legendItem)
  4026. .classed(CLASS.legendItemHidden, function (id) { return !$$.isTargetToShow(id); });
  4027. // Update all to reflect change of legend
  4028. $$.updateLegendItemWidth(maxWidth);
  4029. $$.updateLegendItemHeight(maxHeight);
  4030. $$.updateLegendStep(step);
  4031. // Update size and scale
  4032. $$.updateSizes();
  4033. $$.updateScales();
  4034. $$.updateSvgSize();
  4035. // Update g positions
  4036. $$.transformAll(withTransitionForTransform, transitions);
  4037. $$.legendHasRendered = true;
  4038. };
  4039. c3_chart_internal_fn.initTitle = function () {
  4040. var $$ = this;
  4041. $$.title = $$.svg.append("text")
  4042. .text($$.config.title_text)
  4043. .attr("class", $$.CLASS.title);
  4044. };
  4045. c3_chart_internal_fn.redrawTitle = function () {
  4046. var $$ = this;
  4047. $$.title
  4048. .attr("x", $$.xForTitle.bind($$))
  4049. .attr("y", $$.yForTitle.bind($$));
  4050. };
  4051. c3_chart_internal_fn.xForTitle = function () {
  4052. var $$ = this, config = $$.config, position = config.title_position || 'left', x;
  4053. if (position.indexOf('right') >= 0) {
  4054. x = $$.currentWidth - $$.getTextRect($$.title.node().textContent, $$.CLASS.title, $$.title.node()).width - config.title_padding.right;
  4055. } else if (position.indexOf('center') >= 0) {
  4056. x = ($$.currentWidth - $$.getTextRect($$.title.node().textContent, $$.CLASS.title, $$.title.node()).width) / 2;
  4057. } else { // left
  4058. x = config.title_padding.left;
  4059. }
  4060. return x;
  4061. };
  4062. c3_chart_internal_fn.yForTitle = function () {
  4063. var $$ = this;
  4064. return $$.config.title_padding.top + $$.getTextRect($$.title.node().textContent, $$.CLASS.title, $$.title.node()).height;
  4065. };
  4066. c3_chart_internal_fn.getTitlePadding = function() {
  4067. var $$ = this;
  4068. return $$.yForTitle() + $$.config.title_padding.bottom;
  4069. };
  4070. function Axis(owner) {
  4071. API.call(this, owner);
  4072. }
  4073. inherit(API, Axis);
  4074. Axis.prototype.init = function init() {
  4075. var $$ = this.owner, config = $$.config, main = $$.main;
  4076. $$.axes.x = main.append("g")
  4077. .attr("class", CLASS.axis + ' ' + CLASS.axisX)
  4078. .attr("clip-path", $$.clipPathForXAxis)
  4079. .attr("transform", $$.getTranslate('x'))
  4080. .style("visibility", config.axis_x_show ? 'visible' : 'hidden');
  4081. $$.axes.x.append("text")
  4082. .attr("class", CLASS.axisXLabel)
  4083. .attr("transform", config.axis_rotated ? "rotate(-90)" : "")
  4084. .style("text-anchor", this.textAnchorForXAxisLabel.bind(this));
  4085. $$.axes.y = main.append("g")
  4086. .attr("class", CLASS.axis + ' ' + CLASS.axisY)
  4087. .attr("clip-path", config.axis_y_inner ? "" : $$.clipPathForYAxis)
  4088. .attr("transform", $$.getTranslate('y'))
  4089. .style("visibility", config.axis_y_show ? 'visible' : 'hidden');
  4090. $$.axes.y.append("text")
  4091. .attr("class", CLASS.axisYLabel)
  4092. .attr("transform", config.axis_rotated ? "" : "rotate(-90)")
  4093. .style("text-anchor", this.textAnchorForYAxisLabel.bind(this));
  4094. $$.axes.y2 = main.append("g")
  4095. .attr("class", CLASS.axis + ' ' + CLASS.axisY2)
  4096. // clip-path?
  4097. .attr("transform", $$.getTranslate('y2'))
  4098. .style("visibility", config.axis_y2_show ? 'visible' : 'hidden');
  4099. $$.axes.y2.append("text")
  4100. .attr("class", CLASS.axisY2Label)
  4101. .attr("transform", config.axis_rotated ? "" : "rotate(-90)")
  4102. .style("text-anchor", this.textAnchorForY2AxisLabel.bind(this));
  4103. };
  4104. Axis.prototype.getXAxis = function getXAxis(scale, orient, tickFormat, tickValues, withOuterTick, withoutTransition, withoutRotateTickText) {
  4105. var $$ = this.owner, config = $$.config,
  4106. axisParams = {
  4107. isCategory: $$.isCategorized(),
  4108. withOuterTick: withOuterTick,
  4109. tickMultiline: config.axis_x_tick_multiline,
  4110. tickWidth: config.axis_x_tick_width,
  4111. tickTextRotate: withoutRotateTickText ? 0 : config.axis_x_tick_rotate,
  4112. withoutTransition: withoutTransition,
  4113. },
  4114. axis = c3_axis($$.d3, axisParams).scale(scale).orient(orient);
  4115. if ($$.isTimeSeries() && tickValues && typeof tickValues !== "function") {
  4116. tickValues = tickValues.map(function (v) { return $$.parseDate(v); });
  4117. }
  4118. // Set tick
  4119. axis.tickFormat(tickFormat).tickValues(tickValues);
  4120. if ($$.isCategorized()) {
  4121. axis.tickCentered(config.axis_x_tick_centered);
  4122. if (isEmpty(config.axis_x_tick_culling)) {
  4123. config.axis_x_tick_culling = false;
  4124. }
  4125. }
  4126. return axis;
  4127. };
  4128. Axis.prototype.updateXAxisTickValues = function updateXAxisTickValues(targets, axis) {
  4129. var $$ = this.owner, config = $$.config, tickValues;
  4130. if (config.axis_x_tick_fit || config.axis_x_tick_count) {
  4131. tickValues = this.generateTickValues($$.mapTargetsToUniqueXs(targets), config.axis_x_tick_count, $$.isTimeSeries());
  4132. }
  4133. if (axis) {
  4134. axis.tickValues(tickValues);
  4135. } else {
  4136. $$.xAxis.tickValues(tickValues);
  4137. $$.subXAxis.tickValues(tickValues);
  4138. }
  4139. return tickValues;
  4140. };
  4141. Axis.prototype.getYAxis = function getYAxis(scale, orient, tickFormat, tickValues, withOuterTick, withoutTransition, withoutRotateTickText) {
  4142. var $$ = this.owner, config = $$.config,
  4143. axisParams = {
  4144. withOuterTick: withOuterTick,
  4145. withoutTransition: withoutTransition,
  4146. tickTextRotate: withoutRotateTickText ? 0 : config.axis_y_tick_rotate
  4147. },
  4148. axis = c3_axis($$.d3, axisParams).scale(scale).orient(orient).tickFormat(tickFormat);
  4149. if ($$.isTimeSeriesY()) {
  4150. axis.ticks($$.d3.time[config.axis_y_tick_time_value], config.axis_y_tick_time_interval);
  4151. } else {
  4152. axis.tickValues(tickValues);
  4153. }
  4154. return axis;
  4155. };
  4156. Axis.prototype.getId = function getId(id) {
  4157. var config = this.owner.config;
  4158. return id in config.data_axes ? config.data_axes[id] : 'y';
  4159. };
  4160. Axis.prototype.getXAxisTickFormat = function getXAxisTickFormat() {
  4161. var $$ = this.owner, config = $$.config,
  4162. format = $$.isTimeSeries() ? $$.defaultAxisTimeFormat : $$.isCategorized() ? $$.categoryName : function (v) { return v < 0 ? v.toFixed(0) : v; };
  4163. if (config.axis_x_tick_format) {
  4164. if (isFunction(config.axis_x_tick_format)) {
  4165. format = config.axis_x_tick_format;
  4166. } else if ($$.isTimeSeries()) {
  4167. format = function (date) {
  4168. return date ? $$.axisTimeFormat(config.axis_x_tick_format)(date) : "";
  4169. };
  4170. }
  4171. }
  4172. return isFunction(format) ? function (v) { return format.call($$, v); } : format;
  4173. };
  4174. Axis.prototype.getTickValues = function getTickValues(tickValues, axis) {
  4175. return tickValues ? tickValues : axis ? axis.tickValues() : undefined;
  4176. };
  4177. Axis.prototype.getXAxisTickValues = function getXAxisTickValues() {
  4178. return this.getTickValues(this.owner.config.axis_x_tick_values, this.owner.xAxis);
  4179. };
  4180. Axis.prototype.getYAxisTickValues = function getYAxisTickValues() {
  4181. return this.getTickValues(this.owner.config.axis_y_tick_values, this.owner.yAxis);
  4182. };
  4183. Axis.prototype.getY2AxisTickValues = function getY2AxisTickValues() {
  4184. return this.getTickValues(this.owner.config.axis_y2_tick_values, this.owner.y2Axis);
  4185. };
  4186. Axis.prototype.getLabelOptionByAxisId = function getLabelOptionByAxisId(axisId) {
  4187. var $$ = this.owner, config = $$.config, option;
  4188. if (axisId === 'y') {
  4189. option = config.axis_y_label;
  4190. } else if (axisId === 'y2') {
  4191. option = config.axis_y2_label;
  4192. } else if (axisId === 'x') {
  4193. option = config.axis_x_label;
  4194. }
  4195. return option;
  4196. };
  4197. Axis.prototype.getLabelText = function getLabelText(axisId) {
  4198. var option = this.getLabelOptionByAxisId(axisId);
  4199. return isString(option) ? option : option ? option.text : null;
  4200. };
  4201. Axis.prototype.setLabelText = function setLabelText(axisId, text) {
  4202. var $$ = this.owner, config = $$.config,
  4203. option = this.getLabelOptionByAxisId(axisId);
  4204. if (isString(option)) {
  4205. if (axisId === 'y') {
  4206. config.axis_y_label = text;
  4207. } else if (axisId === 'y2') {
  4208. config.axis_y2_label = text;
  4209. } else if (axisId === 'x') {
  4210. config.axis_x_label = text;
  4211. }
  4212. } else if (option) {
  4213. option.text = text;
  4214. }
  4215. };
  4216. Axis.prototype.getLabelPosition = function getLabelPosition(axisId, defaultPosition) {
  4217. var option = this.getLabelOptionByAxisId(axisId),
  4218. position = (option && typeof option === 'object' && option.position) ? option.position : defaultPosition;
  4219. return {
  4220. isInner: position.indexOf('inner') >= 0,
  4221. isOuter: position.indexOf('outer') >= 0,
  4222. isLeft: position.indexOf('left') >= 0,
  4223. isCenter: position.indexOf('center') >= 0,
  4224. isRight: position.indexOf('right') >= 0,
  4225. isTop: position.indexOf('top') >= 0,
  4226. isMiddle: position.indexOf('middle') >= 0,
  4227. isBottom: position.indexOf('bottom') >= 0
  4228. };
  4229. };
  4230. Axis.prototype.getXAxisLabelPosition = function getXAxisLabelPosition() {
  4231. return this.getLabelPosition('x', this.owner.config.axis_rotated ? 'inner-top' : 'inner-right');
  4232. };
  4233. Axis.prototype.getYAxisLabelPosition = function getYAxisLabelPosition() {
  4234. return this.getLabelPosition('y', this.owner.config.axis_rotated ? 'inner-right' : 'inner-top');
  4235. };
  4236. Axis.prototype.getY2AxisLabelPosition = function getY2AxisLabelPosition() {
  4237. return this.getLabelPosition('y2', this.owner.config.axis_rotated ? 'inner-right' : 'inner-top');
  4238. };
  4239. Axis.prototype.getLabelPositionById = function getLabelPositionById(id) {
  4240. return id === 'y2' ? this.getY2AxisLabelPosition() : id === 'y' ? this.getYAxisLabelPosition() : this.getXAxisLabelPosition();
  4241. };
  4242. Axis.prototype.textForXAxisLabel = function textForXAxisLabel() {
  4243. return this.getLabelText('x');
  4244. };
  4245. Axis.prototype.textForYAxisLabel = function textForYAxisLabel() {
  4246. return this.getLabelText('y');
  4247. };
  4248. Axis.prototype.textForY2AxisLabel = function textForY2AxisLabel() {
  4249. return this.getLabelText('y2');
  4250. };
  4251. Axis.prototype.xForAxisLabel = function xForAxisLabel(forHorizontal, position) {
  4252. var $$ = this.owner;
  4253. if (forHorizontal) {
  4254. return position.isLeft ? 0 : position.isCenter ? $$.width / 2 : $$.width;
  4255. } else {
  4256. return position.isBottom ? -$$.height : position.isMiddle ? -$$.height / 2 : 0;
  4257. }
  4258. };
  4259. Axis.prototype.dxForAxisLabel = function dxForAxisLabel(forHorizontal, position) {
  4260. if (forHorizontal) {
  4261. return position.isLeft ? "0.5em" : position.isRight ? "-0.5em" : "0";
  4262. } else {
  4263. return position.isTop ? "-0.5em" : position.isBottom ? "0.5em" : "0";
  4264. }
  4265. };
  4266. Axis.prototype.textAnchorForAxisLabel = function textAnchorForAxisLabel(forHorizontal, position) {
  4267. if (forHorizontal) {
  4268. return position.isLeft ? 'start' : position.isCenter ? 'middle' : 'end';
  4269. } else {
  4270. return position.isBottom ? 'start' : position.isMiddle ? 'middle' : 'end';
  4271. }
  4272. };
  4273. Axis.prototype.xForXAxisLabel = function xForXAxisLabel() {
  4274. return this.xForAxisLabel(!this.owner.config.axis_rotated, this.getXAxisLabelPosition());
  4275. };
  4276. Axis.prototype.xForYAxisLabel = function xForYAxisLabel() {
  4277. return this.xForAxisLabel(this.owner.config.axis_rotated, this.getYAxisLabelPosition());
  4278. };
  4279. Axis.prototype.xForY2AxisLabel = function xForY2AxisLabel() {
  4280. return this.xForAxisLabel(this.owner.config.axis_rotated, this.getY2AxisLabelPosition());
  4281. };
  4282. Axis.prototype.dxForXAxisLabel = function dxForXAxisLabel() {
  4283. return this.dxForAxisLabel(!this.owner.config.axis_rotated, this.getXAxisLabelPosition());
  4284. };
  4285. Axis.prototype.dxForYAxisLabel = function dxForYAxisLabel() {
  4286. return this.dxForAxisLabel(this.owner.config.axis_rotated, this.getYAxisLabelPosition());
  4287. };
  4288. Axis.prototype.dxForY2AxisLabel = function dxForY2AxisLabel() {
  4289. return this.dxForAxisLabel(this.owner.config.axis_rotated, this.getY2AxisLabelPosition());
  4290. };
  4291. Axis.prototype.dyForXAxisLabel = function dyForXAxisLabel() {
  4292. var $$ = this.owner, config = $$.config,
  4293. position = this.getXAxisLabelPosition();
  4294. if (config.axis_rotated) {
  4295. return position.isInner ? "1.2em" : -25 - this.getMaxTickWidth('x');
  4296. } else {
  4297. return position.isInner ? "-0.5em" : config.axis_x_height ? config.axis_x_height - 10 : "3em";
  4298. }
  4299. };
  4300. Axis.prototype.dyForYAxisLabel = function dyForYAxisLabel() {
  4301. var $$ = this.owner,
  4302. position = this.getYAxisLabelPosition();
  4303. if ($$.config.axis_rotated) {
  4304. return position.isInner ? "-0.5em" : "3em";
  4305. } else {
  4306. return position.isInner ? "1.2em" : -10 - ($$.config.axis_y_inner ? 0 : (this.getMaxTickWidth('y') + 10));
  4307. }
  4308. };
  4309. Axis.prototype.dyForY2AxisLabel = function dyForY2AxisLabel() {
  4310. var $$ = this.owner,
  4311. position = this.getY2AxisLabelPosition();
  4312. if ($$.config.axis_rotated) {
  4313. return position.isInner ? "1.2em" : "-2.2em";
  4314. } else {
  4315. return position.isInner ? "-0.5em" : 15 + ($$.config.axis_y2_inner ? 0 : (this.getMaxTickWidth('y2') + 15));
  4316. }
  4317. };
  4318. Axis.prototype.textAnchorForXAxisLabel = function textAnchorForXAxisLabel() {
  4319. var $$ = this.owner;
  4320. return this.textAnchorForAxisLabel(!$$.config.axis_rotated, this.getXAxisLabelPosition());
  4321. };
  4322. Axis.prototype.textAnchorForYAxisLabel = function textAnchorForYAxisLabel() {
  4323. var $$ = this.owner;
  4324. return this.textAnchorForAxisLabel($$.config.axis_rotated, this.getYAxisLabelPosition());
  4325. };
  4326. Axis.prototype.textAnchorForY2AxisLabel = function textAnchorForY2AxisLabel() {
  4327. var $$ = this.owner;
  4328. return this.textAnchorForAxisLabel($$.config.axis_rotated, this.getY2AxisLabelPosition());
  4329. };
  4330. Axis.prototype.getMaxTickWidth = function getMaxTickWidth(id, withoutRecompute) {
  4331. var $$ = this.owner, config = $$.config,
  4332. maxWidth = 0, targetsToShow, scale, axis, dummy, svg;
  4333. if (withoutRecompute && $$.currentMaxTickWidths[id]) {
  4334. return $$.currentMaxTickWidths[id];
  4335. }
  4336. if ($$.svg) {
  4337. targetsToShow = $$.filterTargetsToShow($$.data.targets);
  4338. if (id === 'y') {
  4339. scale = $$.y.copy().domain($$.getYDomain(targetsToShow, 'y'));
  4340. axis = this.getYAxis(scale, $$.yOrient, config.axis_y_tick_format, $$.yAxisTickValues, false, true, true);
  4341. } else if (id === 'y2') {
  4342. scale = $$.y2.copy().domain($$.getYDomain(targetsToShow, 'y2'));
  4343. axis = this.getYAxis(scale, $$.y2Orient, config.axis_y2_tick_format, $$.y2AxisTickValues, false, true, true);
  4344. } else {
  4345. scale = $$.x.copy().domain($$.getXDomain(targetsToShow));
  4346. axis = this.getXAxis(scale, $$.xOrient, $$.xAxisTickFormat, $$.xAxisTickValues, false, true, true);
  4347. this.updateXAxisTickValues(targetsToShow, axis);
  4348. }
  4349. dummy = $$.d3.select('body').append('div').classed('c3', true);
  4350. svg = dummy.append("svg").style('visibility', 'hidden').style('position', 'fixed').style('top', 0).style('left', 0),
  4351. svg.append('g').call(axis).each(function () {
  4352. $$.d3.select(this).selectAll('text').each(function () {
  4353. var box = this.getBoundingClientRect();
  4354. if (maxWidth < box.width) { maxWidth = box.width; }
  4355. });
  4356. dummy.remove();
  4357. });
  4358. }
  4359. $$.currentMaxTickWidths[id] = maxWidth <= 0 ? $$.currentMaxTickWidths[id] : maxWidth;
  4360. return $$.currentMaxTickWidths[id];
  4361. };
  4362. Axis.prototype.updateLabels = function updateLabels(withTransition) {
  4363. var $$ = this.owner;
  4364. var axisXLabel = $$.main.select('.' + CLASS.axisX + ' .' + CLASS.axisXLabel),
  4365. axisYLabel = $$.main.select('.' + CLASS.axisY + ' .' + CLASS.axisYLabel),
  4366. axisY2Label = $$.main.select('.' + CLASS.axisY2 + ' .' + CLASS.axisY2Label);
  4367. (withTransition ? axisXLabel.transition() : axisXLabel)
  4368. .attr("x", this.xForXAxisLabel.bind(this))
  4369. .attr("dx", this.dxForXAxisLabel.bind(this))
  4370. .attr("dy", this.dyForXAxisLabel.bind(this))
  4371. .text(this.textForXAxisLabel.bind(this));
  4372. (withTransition ? axisYLabel.transition() : axisYLabel)
  4373. .attr("x", this.xForYAxisLabel.bind(this))
  4374. .attr("dx", this.dxForYAxisLabel.bind(this))
  4375. .attr("dy", this.dyForYAxisLabel.bind(this))
  4376. .text(this.textForYAxisLabel.bind(this));
  4377. (withTransition ? axisY2Label.transition() : axisY2Label)
  4378. .attr("x", this.xForY2AxisLabel.bind(this))
  4379. .attr("dx", this.dxForY2AxisLabel.bind(this))
  4380. .attr("dy", this.dyForY2AxisLabel.bind(this))
  4381. .text(this.textForY2AxisLabel.bind(this));
  4382. };
  4383. Axis.prototype.getPadding = function getPadding(padding, key, defaultValue, domainLength) {
  4384. var p = typeof padding === 'number' ? padding : padding[key];
  4385. if (!isValue(p)) {
  4386. return defaultValue;
  4387. }
  4388. if (padding.unit === 'ratio') {
  4389. return padding[key] * domainLength;
  4390. }
  4391. // assume padding is pixels if unit is not specified
  4392. return this.convertPixelsToAxisPadding(p, domainLength);
  4393. };
  4394. Axis.prototype.convertPixelsToAxisPadding = function convertPixelsToAxisPadding(pixels, domainLength) {
  4395. var $$ = this.owner,
  4396. length = $$.config.axis_rotated ? $$.width : $$.height;
  4397. return domainLength * (pixels / length);
  4398. };
  4399. Axis.prototype.generateTickValues = function generateTickValues(values, tickCount, forTimeSeries) {
  4400. var tickValues = values, targetCount, start, end, count, interval, i, tickValue;
  4401. if (tickCount) {
  4402. targetCount = isFunction(tickCount) ? tickCount() : tickCount;
  4403. // compute ticks according to tickCount
  4404. if (targetCount === 1) {
  4405. tickValues = [values[0]];
  4406. } else if (targetCount === 2) {
  4407. tickValues = [values[0], values[values.length - 1]];
  4408. } else if (targetCount > 2) {
  4409. count = targetCount - 2;
  4410. start = values[0];
  4411. end = values[values.length - 1];
  4412. interval = (end - start) / (count + 1);
  4413. // re-construct unique values
  4414. tickValues = [start];
  4415. for (i = 0; i < count; i++) {
  4416. tickValue = +start + interval * (i + 1);
  4417. tickValues.push(forTimeSeries ? new Date(tickValue) : tickValue);
  4418. }
  4419. tickValues.push(end);
  4420. }
  4421. }
  4422. if (!forTimeSeries) { tickValues = tickValues.sort(function (a, b) { return a - b; }); }
  4423. return tickValues;
  4424. };
  4425. Axis.prototype.generateTransitions = function generateTransitions(duration) {
  4426. var $$ = this.owner, axes = $$.axes;
  4427. return {
  4428. axisX: duration ? axes.x.transition().duration(duration) : axes.x,
  4429. axisY: duration ? axes.y.transition().duration(duration) : axes.y,
  4430. axisY2: duration ? axes.y2.transition().duration(duration) : axes.y2,
  4431. axisSubX: duration ? axes.subx.transition().duration(duration) : axes.subx
  4432. };
  4433. };
  4434. Axis.prototype.redraw = function redraw(transitions, isHidden) {
  4435. var $$ = this.owner;
  4436. $$.axes.x.style("opacity", isHidden ? 0 : 1);
  4437. $$.axes.y.style("opacity", isHidden ? 0 : 1);
  4438. $$.axes.y2.style("opacity", isHidden ? 0 : 1);
  4439. $$.axes.subx.style("opacity", isHidden ? 0 : 1);
  4440. transitions.axisX.call($$.xAxis);
  4441. transitions.axisY.call($$.yAxis);
  4442. transitions.axisY2.call($$.y2Axis);
  4443. transitions.axisSubX.call($$.subXAxis);
  4444. };
  4445. c3_chart_internal_fn.getClipPath = function (id) {
  4446. var isIE9 = window.navigator.appVersion.toLowerCase().indexOf("msie 9.") >= 0;
  4447. return "url(" + (isIE9 ? "" : document.URL.split('#')[0]) + "#" + id + ")";
  4448. };
  4449. c3_chart_internal_fn.appendClip = function (parent, id) {
  4450. return parent.append("clipPath").attr("id", id).append("rect");
  4451. };
  4452. c3_chart_internal_fn.getAxisClipX = function (forHorizontal) {
  4453. // axis line width + padding for left
  4454. var left = Math.max(30, this.margin.left);
  4455. return forHorizontal ? -(1 + left) : -(left - 1);
  4456. };
  4457. c3_chart_internal_fn.getAxisClipY = function (forHorizontal) {
  4458. return forHorizontal ? -20 : -this.margin.top;
  4459. };
  4460. c3_chart_internal_fn.getXAxisClipX = function () {
  4461. var $$ = this;
  4462. return $$.getAxisClipX(!$$.config.axis_rotated);
  4463. };
  4464. c3_chart_internal_fn.getXAxisClipY = function () {
  4465. var $$ = this;
  4466. return $$.getAxisClipY(!$$.config.axis_rotated);
  4467. };
  4468. c3_chart_internal_fn.getYAxisClipX = function () {
  4469. var $$ = this;
  4470. return $$.config.axis_y_inner ? -1 : $$.getAxisClipX($$.config.axis_rotated);
  4471. };
  4472. c3_chart_internal_fn.getYAxisClipY = function () {
  4473. var $$ = this;
  4474. return $$.getAxisClipY($$.config.axis_rotated);
  4475. };
  4476. c3_chart_internal_fn.getAxisClipWidth = function (forHorizontal) {
  4477. var $$ = this,
  4478. left = Math.max(30, $$.margin.left),
  4479. right = Math.max(30, $$.margin.right);
  4480. // width + axis line width + padding for left/right
  4481. return forHorizontal ? $$.width + 2 + left + right : $$.margin.left + 20;
  4482. };
  4483. c3_chart_internal_fn.getAxisClipHeight = function (forHorizontal) {
  4484. // less than 20 is not enough to show the axis label 'outer' without legend
  4485. return (forHorizontal ? this.margin.bottom : (this.margin.top + this.height)) + 20;
  4486. };
  4487. c3_chart_internal_fn.getXAxisClipWidth = function () {
  4488. var $$ = this;
  4489. return $$.getAxisClipWidth(!$$.config.axis_rotated);
  4490. };
  4491. c3_chart_internal_fn.getXAxisClipHeight = function () {
  4492. var $$ = this;
  4493. return $$.getAxisClipHeight(!$$.config.axis_rotated);
  4494. };
  4495. c3_chart_internal_fn.getYAxisClipWidth = function () {
  4496. var $$ = this;
  4497. return $$.getAxisClipWidth($$.config.axis_rotated) + ($$.config.axis_y_inner ? 20 : 0);
  4498. };
  4499. c3_chart_internal_fn.getYAxisClipHeight = function () {
  4500. var $$ = this;
  4501. return $$.getAxisClipHeight($$.config.axis_rotated);
  4502. };
  4503. c3_chart_internal_fn.initPie = function () {
  4504. var $$ = this, d3 = $$.d3, config = $$.config;
  4505. $$.pie = d3.layout.pie().value(function (d) {
  4506. return d.values.reduce(function (a, b) { return a + b.value; }, 0);
  4507. });
  4508. if (!config.data_order) {
  4509. $$.pie.sort(null);
  4510. }
  4511. };
  4512. c3_chart_internal_fn.updateRadius = function () {
  4513. var $$ = this, config = $$.config,
  4514. w = config.gauge_width || config.donut_width;
  4515. $$.radiusExpanded = Math.min($$.arcWidth, $$.arcHeight) / 2;
  4516. $$.radius = $$.radiusExpanded * 0.95;
  4517. $$.innerRadiusRatio = w ? ($$.radius - w) / $$.radius : 0.6;
  4518. $$.innerRadius = $$.hasType('donut') || $$.hasType('gauge') ? $$.radius * $$.innerRadiusRatio : 0;
  4519. };
  4520. c3_chart_internal_fn.updateArc = function () {
  4521. var $$ = this;
  4522. $$.svgArc = $$.getSvgArc();
  4523. $$.svgArcExpanded = $$.getSvgArcExpanded();
  4524. $$.svgArcExpandedSub = $$.getSvgArcExpanded(0.98);
  4525. };
  4526. c3_chart_internal_fn.updateAngle = function (d) {
  4527. var $$ = this, config = $$.config,
  4528. found = false, index = 0,
  4529. gMin, gMax, gTic, gValue;
  4530. if (!config) {
  4531. return null;
  4532. }
  4533. $$.pie($$.filterTargetsToShow($$.data.targets)).forEach(function (t) {
  4534. if (! found && t.data.id === d.data.id) {
  4535. found = true;
  4536. d = t;
  4537. d.index = index;
  4538. }
  4539. index++;
  4540. });
  4541. if (isNaN(d.startAngle)) {
  4542. d.startAngle = 0;
  4543. }
  4544. if (isNaN(d.endAngle)) {
  4545. d.endAngle = d.startAngle;
  4546. }
  4547. if ($$.isGaugeType(d.data)) {
  4548. gMin = config.gauge_min;
  4549. gMax = config.gauge_max;
  4550. gTic = (Math.PI * (config.gauge_fullCircle ? 2 : 1)) / (gMax - gMin);
  4551. gValue = d.value < gMin ? 0 : d.value < gMax ? d.value - gMin : (gMax - gMin);
  4552. d.startAngle = config.gauge_startingAngle;
  4553. d.endAngle = d.startAngle + gTic * gValue;
  4554. }
  4555. return found ? d : null;
  4556. };
  4557. c3_chart_internal_fn.getSvgArc = function () {
  4558. var $$ = this,
  4559. arc = $$.d3.svg.arc().outerRadius($$.radius).innerRadius($$.innerRadius),
  4560. newArc = function (d, withoutUpdate) {
  4561. var updated;
  4562. if (withoutUpdate) { return arc(d); } // for interpolate
  4563. updated = $$.updateAngle(d);
  4564. return updated ? arc(updated) : "M 0 0";
  4565. };
  4566. // TODO: extends all function
  4567. newArc.centroid = arc.centroid;
  4568. return newArc;
  4569. };
  4570. c3_chart_internal_fn.getSvgArcExpanded = function (rate) {
  4571. var $$ = this,
  4572. arc = $$.d3.svg.arc().outerRadius($$.radiusExpanded * (rate ? rate : 1)).innerRadius($$.innerRadius);
  4573. return function (d) {
  4574. var updated = $$.updateAngle(d);
  4575. return updated ? arc(updated) : "M 0 0";
  4576. };
  4577. };
  4578. c3_chart_internal_fn.getArc = function (d, withoutUpdate, force) {
  4579. return force || this.isArcType(d.data) ? this.svgArc(d, withoutUpdate) : "M 0 0";
  4580. };
  4581. c3_chart_internal_fn.transformForArcLabel = function (d) {
  4582. var $$ = this, config = $$.config,
  4583. updated = $$.updateAngle(d), c, x, y, h, ratio, translate = "";
  4584. if (updated && !$$.hasType('gauge')) {
  4585. c = this.svgArc.centroid(updated);
  4586. x = isNaN(c[0]) ? 0 : c[0];
  4587. y = isNaN(c[1]) ? 0 : c[1];
  4588. h = Math.sqrt(x * x + y * y);
  4589. if ($$.hasType('donut') && config.donut_label_ratio) {
  4590. ratio = isFunction(config.donut_label_ratio) ? config.donut_label_ratio(d, $$.radius, h) : config.donut_label_ratio;
  4591. } else if ($$.hasType('pie') && config.pie_label_ratio) {
  4592. ratio = isFunction(config.pie_label_ratio) ? config.pie_label_ratio(d, $$.radius, h) : config.pie_label_ratio;
  4593. } else {
  4594. ratio = $$.radius && h ? (36 / $$.radius > 0.375 ? 1.175 - 36 / $$.radius : 0.8) * $$.radius / h : 0;
  4595. }
  4596. translate = "translate(" + (x * ratio) + ',' + (y * ratio) + ")";
  4597. }
  4598. return translate;
  4599. };
  4600. c3_chart_internal_fn.getArcRatio = function (d) {
  4601. var $$ = this,
  4602. config = $$.config,
  4603. whole = Math.PI * ($$.hasType('gauge') && !config.gauge_fullCircle ? 1 : 2);
  4604. return d ? (d.endAngle - d.startAngle) / whole : null;
  4605. };
  4606. c3_chart_internal_fn.convertToArcData = function (d) {
  4607. return this.addName({
  4608. id: d.data.id,
  4609. value: d.value,
  4610. ratio: this.getArcRatio(d),
  4611. index: d.index
  4612. });
  4613. };
  4614. c3_chart_internal_fn.textForArcLabel = function (d) {
  4615. var $$ = this,
  4616. updated, value, ratio, id, format;
  4617. if (! $$.shouldShowArcLabel()) { return ""; }
  4618. updated = $$.updateAngle(d);
  4619. value = updated ? updated.value : null;
  4620. ratio = $$.getArcRatio(updated);
  4621. id = d.data.id;
  4622. if (! $$.hasType('gauge') && ! $$.meetsArcLabelThreshold(ratio)) { return ""; }
  4623. format = $$.getArcLabelFormat();
  4624. return format ? format(value, ratio, id) : $$.defaultArcValueFormat(value, ratio);
  4625. };
  4626. c3_chart_internal_fn.expandArc = function (targetIds) {
  4627. var $$ = this, interval;
  4628. // MEMO: avoid to cancel transition
  4629. if ($$.transiting) {
  4630. interval = window.setInterval(function () {
  4631. if (!$$.transiting) {
  4632. window.clearInterval(interval);
  4633. if ($$.legend.selectAll('.c3-legend-item-focused').size() > 0) {
  4634. $$.expandArc(targetIds);
  4635. }
  4636. }
  4637. }, 10);
  4638. return;
  4639. }
  4640. targetIds = $$.mapToTargetIds(targetIds);
  4641. $$.svg.selectAll($$.selectorTargets(targetIds, '.' + CLASS.chartArc)).each(function (d) {
  4642. if (! $$.shouldExpand(d.data.id)) { return; }
  4643. $$.d3.select(this).selectAll('path')
  4644. .transition().duration($$.expandDuration(d.data.id))
  4645. .attr("d", $$.svgArcExpanded)
  4646. .transition().duration($$.expandDuration(d.data.id) * 2)
  4647. .attr("d", $$.svgArcExpandedSub)
  4648. .each(function (d) {
  4649. if ($$.isDonutType(d.data)) {
  4650. // callback here
  4651. }
  4652. });
  4653. });
  4654. };
  4655. c3_chart_internal_fn.unexpandArc = function (targetIds) {
  4656. var $$ = this;
  4657. if ($$.transiting) { return; }
  4658. targetIds = $$.mapToTargetIds(targetIds);
  4659. $$.svg.selectAll($$.selectorTargets(targetIds, '.' + CLASS.chartArc)).selectAll('path')
  4660. .transition().duration(function(d) {
  4661. return $$.expandDuration(d.data.id);
  4662. })
  4663. .attr("d", $$.svgArc);
  4664. $$.svg.selectAll('.' + CLASS.arc)
  4665. .style("opacity", 1);
  4666. };
  4667. c3_chart_internal_fn.expandDuration = function (id) {
  4668. var $$ = this, config = $$.config;
  4669. if ($$.isDonutType(id)) {
  4670. return config.donut_expand_duration;
  4671. } else if ($$.isGaugeType(id)) {
  4672. return config.gauge_expand_duration;
  4673. } else if ($$.isPieType(id)) {
  4674. return config.pie_expand_duration;
  4675. } else {
  4676. return 50;
  4677. }
  4678. };
  4679. c3_chart_internal_fn.shouldExpand = function (id) {
  4680. var $$ = this, config = $$.config;
  4681. return ($$.isDonutType(id) && config.donut_expand) ||
  4682. ($$.isGaugeType(id) && config.gauge_expand) ||
  4683. ($$.isPieType(id) && config.pie_expand);
  4684. };
  4685. c3_chart_internal_fn.shouldShowArcLabel = function () {
  4686. var $$ = this, config = $$.config, shouldShow = true;
  4687. if ($$.hasType('donut')) {
  4688. shouldShow = config.donut_label_show;
  4689. } else if ($$.hasType('pie')) {
  4690. shouldShow = config.pie_label_show;
  4691. }
  4692. // when gauge, always true
  4693. return shouldShow;
  4694. };
  4695. c3_chart_internal_fn.meetsArcLabelThreshold = function (ratio) {
  4696. var $$ = this, config = $$.config,
  4697. threshold = $$.hasType('donut') ? config.donut_label_threshold : config.pie_label_threshold;
  4698. return ratio >= threshold;
  4699. };
  4700. c3_chart_internal_fn.getArcLabelFormat = function () {
  4701. var $$ = this, config = $$.config,
  4702. format = config.pie_label_format;
  4703. if ($$.hasType('gauge')) {
  4704. format = config.gauge_label_format;
  4705. } else if ($$.hasType('donut')) {
  4706. format = config.donut_label_format;
  4707. }
  4708. return format;
  4709. };
  4710. c3_chart_internal_fn.getArcTitle = function () {
  4711. var $$ = this;
  4712. return $$.hasType('donut') ? $$.config.donut_title : "";
  4713. };
  4714. c3_chart_internal_fn.updateTargetsForArc = function (targets) {
  4715. var $$ = this, main = $$.main,
  4716. mainPieUpdate, mainPieEnter,
  4717. classChartArc = $$.classChartArc.bind($$),
  4718. classArcs = $$.classArcs.bind($$),
  4719. classFocus = $$.classFocus.bind($$);
  4720. mainPieUpdate = main.select('.' + CLASS.chartArcs).selectAll('.' + CLASS.chartArc)
  4721. .data($$.pie(targets))
  4722. .attr("class", function (d) { return classChartArc(d) + classFocus(d.data); });
  4723. mainPieEnter = mainPieUpdate.enter().append("g")
  4724. .attr("class", classChartArc);
  4725. mainPieEnter.append('g')
  4726. .attr('class', classArcs);
  4727. mainPieEnter.append("text")
  4728. .attr("dy", $$.hasType('gauge') ? "-.1em" : ".35em")
  4729. .style("opacity", 0)
  4730. .style("text-anchor", "middle")
  4731. .style("pointer-events", "none");
  4732. // MEMO: can not keep same color..., but not bad to update color in redraw
  4733. //mainPieUpdate.exit().remove();
  4734. };
  4735. c3_chart_internal_fn.initArc = function () {
  4736. var $$ = this;
  4737. $$.arcs = $$.main.select('.' + CLASS.chart).append("g")
  4738. .attr("class", CLASS.chartArcs)
  4739. .attr("transform", $$.getTranslate('arc'));
  4740. $$.arcs.append('text')
  4741. .attr('class', CLASS.chartArcsTitle)
  4742. .style("text-anchor", "middle")
  4743. .text($$.getArcTitle());
  4744. };
  4745. c3_chart_internal_fn.redrawArc = function (duration, durationForExit, withTransform) {
  4746. var $$ = this, d3 = $$.d3, config = $$.config, main = $$.main,
  4747. mainArc;
  4748. mainArc = main.selectAll('.' + CLASS.arcs).selectAll('.' + CLASS.arc)
  4749. .data($$.arcData.bind($$));
  4750. mainArc.enter().append('path')
  4751. .attr("class", $$.classArc.bind($$))
  4752. .style("fill", function (d) { return $$.color(d.data); })
  4753. .style("cursor", function (d) { return config.interaction_enabled && config.data_selection_isselectable(d) ? "pointer" : null; })
  4754. .style("opacity", 0)
  4755. .each(function (d) {
  4756. if ($$.isGaugeType(d.data)) {
  4757. d.startAngle = d.endAngle = config.gauge_startingAngle;
  4758. }
  4759. this._current = d;
  4760. });
  4761. mainArc
  4762. .attr("transform", function (d) { return !$$.isGaugeType(d.data) && withTransform ? "scale(0)" : ""; })
  4763. .style("opacity", function (d) { return d === this._current ? 0 : 1; })
  4764. .on('mouseover', config.interaction_enabled ? function (d) {
  4765. var updated, arcData;
  4766. if ($$.transiting) { // skip while transiting
  4767. return;
  4768. }
  4769. updated = $$.updateAngle(d);
  4770. if (updated) {
  4771. arcData = $$.convertToArcData(updated);
  4772. // transitions
  4773. $$.expandArc(updated.data.id);
  4774. $$.api.focus(updated.data.id);
  4775. $$.toggleFocusLegend(updated.data.id, true);
  4776. $$.config.data_onmouseover(arcData, this);
  4777. }
  4778. } : null)
  4779. .on('mousemove', config.interaction_enabled ? function (d) {
  4780. var updated = $$.updateAngle(d), arcData, selectedData;
  4781. if (updated) {
  4782. arcData = $$.convertToArcData(updated),
  4783. selectedData = [arcData];
  4784. $$.showTooltip(selectedData, this);
  4785. }
  4786. } : null)
  4787. .on('mouseout', config.interaction_enabled ? function (d) {
  4788. var updated, arcData;
  4789. if ($$.transiting) { // skip while transiting
  4790. return;
  4791. }
  4792. updated = $$.updateAngle(d);
  4793. if (updated) {
  4794. arcData = $$.convertToArcData(updated);
  4795. // transitions
  4796. $$.unexpandArc(updated.data.id);
  4797. $$.api.revert();
  4798. $$.revertLegend();
  4799. $$.hideTooltip();
  4800. $$.config.data_onmouseout(arcData, this);
  4801. }
  4802. } : null)
  4803. .on('click', config.interaction_enabled ? function (d, i) {
  4804. var updated = $$.updateAngle(d), arcData;
  4805. if (updated) {
  4806. arcData = $$.convertToArcData(updated);
  4807. if ($$.toggleShape) {
  4808. $$.toggleShape(this, arcData, i);
  4809. }
  4810. $$.config.data_onclick.call($$.api, arcData, this);
  4811. }
  4812. } : null)
  4813. .each(function () { $$.transiting = true; })
  4814. .transition().duration(duration)
  4815. .attrTween("d", function (d) {
  4816. var updated = $$.updateAngle(d), interpolate;
  4817. if (! updated) {
  4818. return function () { return "M 0 0"; };
  4819. }
  4820. // if (this._current === d) {
  4821. // this._current = {
  4822. // startAngle: Math.PI*2,
  4823. // endAngle: Math.PI*2,
  4824. // };
  4825. // }
  4826. if (isNaN(this._current.startAngle)) {
  4827. this._current.startAngle = 0;
  4828. }
  4829. if (isNaN(this._current.endAngle)) {
  4830. this._current.endAngle = this._current.startAngle;
  4831. }
  4832. interpolate = d3.interpolate(this._current, updated);
  4833. this._current = interpolate(0);
  4834. return function (t) {
  4835. var interpolated = interpolate(t);
  4836. interpolated.data = d.data; // data.id will be updated by interporator
  4837. return $$.getArc(interpolated, true);
  4838. };
  4839. })
  4840. .attr("transform", withTransform ? "scale(1)" : "")
  4841. .style("fill", function (d) {
  4842. return $$.levelColor ? $$.levelColor(d.data.values[0].value) : $$.color(d.data.id);
  4843. }) // Where gauge reading color would receive customization.
  4844. .style("opacity", 1)
  4845. .call($$.endall, function () {
  4846. $$.transiting = false;
  4847. });
  4848. mainArc.exit().transition().duration(durationForExit)
  4849. .style('opacity', 0)
  4850. .remove();
  4851. main.selectAll('.' + CLASS.chartArc).select('text')
  4852. .style("opacity", 0)
  4853. .attr('class', function (d) { return $$.isGaugeType(d.data) ? CLASS.gaugeValue : ''; })
  4854. .text($$.textForArcLabel.bind($$))
  4855. .attr("transform", $$.transformForArcLabel.bind($$))
  4856. .style('font-size', function (d) { return $$.isGaugeType(d.data) ? Math.round($$.radius / 5) + 'px' : ''; })
  4857. .transition().duration(duration)
  4858. .style("opacity", function (d) { return $$.isTargetToShow(d.data.id) && $$.isArcType(d.data) ? 1 : 0; });
  4859. main.select('.' + CLASS.chartArcsTitle)
  4860. .style("opacity", $$.hasType('donut') || $$.hasType('gauge') ? 1 : 0);
  4861. if ($$.hasType('gauge')) {
  4862. $$.arcs.select('.' + CLASS.chartArcsBackground)
  4863. .attr("d", function () {
  4864. var d = {
  4865. data: [{value: config.gauge_max}],
  4866. startAngle: config.gauge_startingAngle,
  4867. endAngle: -1 * config.gauge_startingAngle
  4868. };
  4869. return $$.getArc(d, true, true);
  4870. });
  4871. $$.arcs.select('.' + CLASS.chartArcsGaugeUnit)
  4872. .attr("dy", ".75em")
  4873. .text(config.gauge_label_show ? config.gauge_units : '');
  4874. $$.arcs.select('.' + CLASS.chartArcsGaugeMin)
  4875. .attr("dx", -1 * ($$.innerRadius + (($$.radius - $$.innerRadius) / (config.gauge_fullCircle ? 1 : 2))) + "px")
  4876. .attr("dy", "1.2em")
  4877. .text(config.gauge_label_show ? config.gauge_min : '');
  4878. $$.arcs.select('.' + CLASS.chartArcsGaugeMax)
  4879. .attr("dx", $$.innerRadius + (($$.radius - $$.innerRadius) / (config.gauge_fullCircle ? 1 : 2)) + "px")
  4880. .attr("dy", "1.2em")
  4881. .text(config.gauge_label_show ? config.gauge_max : '');
  4882. }
  4883. };
  4884. c3_chart_internal_fn.initGauge = function () {
  4885. var arcs = this.arcs;
  4886. if (this.hasType('gauge')) {
  4887. arcs.append('path')
  4888. .attr("class", CLASS.chartArcsBackground);
  4889. arcs.append("text")
  4890. .attr("class", CLASS.chartArcsGaugeUnit)
  4891. .style("text-anchor", "middle")
  4892. .style("pointer-events", "none");
  4893. arcs.append("text")
  4894. .attr("class", CLASS.chartArcsGaugeMin)
  4895. .style("text-anchor", "middle")
  4896. .style("pointer-events", "none");
  4897. arcs.append("text")
  4898. .attr("class", CLASS.chartArcsGaugeMax)
  4899. .style("text-anchor", "middle")
  4900. .style("pointer-events", "none");
  4901. }
  4902. };
  4903. c3_chart_internal_fn.getGaugeLabelHeight = function () {
  4904. return this.config.gauge_label_show ? 20 : 0;
  4905. };
  4906. c3_chart_internal_fn.initRegion = function () {
  4907. var $$ = this;
  4908. $$.region = $$.main.append('g')
  4909. .attr("clip-path", $$.clipPath)
  4910. .attr("class", CLASS.regions);
  4911. };
  4912. c3_chart_internal_fn.updateRegion = function (duration) {
  4913. var $$ = this, config = $$.config;
  4914. // hide if arc type
  4915. $$.region.style('visibility', $$.hasArcType() ? 'hidden' : 'visible');
  4916. $$.mainRegion = $$.main.select('.' + CLASS.regions).selectAll('.' + CLASS.region)
  4917. .data(config.regions);
  4918. $$.mainRegion.enter().append('g')
  4919. .append('rect')
  4920. .style("fill-opacity", 0);
  4921. $$.mainRegion
  4922. .attr('class', $$.classRegion.bind($$));
  4923. $$.mainRegion.exit().transition().duration(duration)
  4924. .style("opacity", 0)
  4925. .remove();
  4926. };
  4927. c3_chart_internal_fn.redrawRegion = function (withTransition) {
  4928. var $$ = this,
  4929. regions = $$.mainRegion.selectAll('rect').each(function () {
  4930. // data is binded to g and it's not transferred to rect (child node) automatically,
  4931. // then data of each rect has to be updated manually.
  4932. // TODO: there should be more efficient way to solve this?
  4933. var parentData = $$.d3.select(this.parentNode).datum();
  4934. $$.d3.select(this).datum(parentData);
  4935. }),
  4936. x = $$.regionX.bind($$),
  4937. y = $$.regionY.bind($$),
  4938. w = $$.regionWidth.bind($$),
  4939. h = $$.regionHeight.bind($$);
  4940. return [
  4941. (withTransition ? regions.transition() : regions)
  4942. .attr("x", x)
  4943. .attr("y", y)
  4944. .attr("width", w)
  4945. .attr("height", h)
  4946. .style("fill-opacity", function (d) { return isValue(d.opacity) ? d.opacity : 0.1; })
  4947. ];
  4948. };
  4949. c3_chart_internal_fn.regionX = function (d) {
  4950. var $$ = this, config = $$.config,
  4951. xPos, yScale = d.axis === 'y' ? $$.y : $$.y2;
  4952. if (d.axis === 'y' || d.axis === 'y2') {
  4953. xPos = config.axis_rotated ? ('start' in d ? yScale(d.start) : 0) : 0;
  4954. } else {
  4955. xPos = config.axis_rotated ? 0 : ('start' in d ? $$.x($$.isTimeSeries() ? $$.parseDate(d.start) : d.start) : 0);
  4956. }
  4957. return xPos;
  4958. };
  4959. c3_chart_internal_fn.regionY = function (d) {
  4960. var $$ = this, config = $$.config,
  4961. yPos, yScale = d.axis === 'y' ? $$.y : $$.y2;
  4962. if (d.axis === 'y' || d.axis === 'y2') {
  4963. yPos = config.axis_rotated ? 0 : ('end' in d ? yScale(d.end) : 0);
  4964. } else {
  4965. yPos = config.axis_rotated ? ('start' in d ? $$.x($$.isTimeSeries() ? $$.parseDate(d.start) : d.start) : 0) : 0;
  4966. }
  4967. return yPos;
  4968. };
  4969. c3_chart_internal_fn.regionWidth = function (d) {
  4970. var $$ = this, config = $$.config,
  4971. start = $$.regionX(d), end, yScale = d.axis === 'y' ? $$.y : $$.y2;
  4972. if (d.axis === 'y' || d.axis === 'y2') {
  4973. end = config.axis_rotated ? ('end' in d ? yScale(d.end) : $$.width) : $$.width;
  4974. } else {
  4975. end = config.axis_rotated ? $$.width : ('end' in d ? $$.x($$.isTimeSeries() ? $$.parseDate(d.end) : d.end) : $$.width);
  4976. }
  4977. return end < start ? 0 : end - start;
  4978. };
  4979. c3_chart_internal_fn.regionHeight = function (d) {
  4980. var $$ = this, config = $$.config,
  4981. start = this.regionY(d), end, yScale = d.axis === 'y' ? $$.y : $$.y2;
  4982. if (d.axis === 'y' || d.axis === 'y2') {
  4983. end = config.axis_rotated ? $$.height : ('start' in d ? yScale(d.start) : $$.height);
  4984. } else {
  4985. end = config.axis_rotated ? ('end' in d ? $$.x($$.isTimeSeries() ? $$.parseDate(d.end) : d.end) : $$.height) : $$.height;
  4986. }
  4987. return end < start ? 0 : end - start;
  4988. };
  4989. c3_chart_internal_fn.isRegionOnX = function (d) {
  4990. return !d.axis || d.axis === 'x';
  4991. };
  4992. c3_chart_internal_fn.drag = function (mouse) {
  4993. var $$ = this, config = $$.config, main = $$.main, d3 = $$.d3;
  4994. var sx, sy, mx, my, minX, maxX, minY, maxY;
  4995. if ($$.hasArcType()) { return; }
  4996. if (! config.data_selection_enabled) { return; } // do nothing if not selectable
  4997. if (config.zoom_enabled && ! $$.zoom.altDomain) { return; } // skip if zoomable because of conflict drag dehavior
  4998. if (!config.data_selection_multiple) { return; } // skip when single selection because drag is used for multiple selection
  4999. sx = $$.dragStart[0];
  5000. sy = $$.dragStart[1];
  5001. mx = mouse[0];
  5002. my = mouse[1];
  5003. minX = Math.min(sx, mx);
  5004. maxX = Math.max(sx, mx);
  5005. minY = (config.data_selection_grouped) ? $$.margin.top : Math.min(sy, my);
  5006. maxY = (config.data_selection_grouped) ? $$.height : Math.max(sy, my);
  5007. main.select('.' + CLASS.dragarea)
  5008. .attr('x', minX)
  5009. .attr('y', minY)
  5010. .attr('width', maxX - minX)
  5011. .attr('height', maxY - minY);
  5012. // TODO: binary search when multiple xs
  5013. main.selectAll('.' + CLASS.shapes).selectAll('.' + CLASS.shape)
  5014. .filter(function (d) { return config.data_selection_isselectable(d); })
  5015. .each(function (d, i) {
  5016. var shape = d3.select(this),
  5017. isSelected = shape.classed(CLASS.SELECTED),
  5018. isIncluded = shape.classed(CLASS.INCLUDED),
  5019. _x, _y, _w, _h, toggle, isWithin = false, box;
  5020. if (shape.classed(CLASS.circle)) {
  5021. _x = shape.attr("cx") * 1;
  5022. _y = shape.attr("cy") * 1;
  5023. toggle = $$.togglePoint;
  5024. isWithin = minX < _x && _x < maxX && minY < _y && _y < maxY;
  5025. }
  5026. else if (shape.classed(CLASS.bar)) {
  5027. box = getPathBox(this);
  5028. _x = box.x;
  5029. _y = box.y;
  5030. _w = box.width;
  5031. _h = box.height;
  5032. toggle = $$.togglePath;
  5033. isWithin = !(maxX < _x || _x + _w < minX) && !(maxY < _y || _y + _h < minY);
  5034. } else {
  5035. // line/area selection not supported yet
  5036. return;
  5037. }
  5038. if (isWithin ^ isIncluded) {
  5039. shape.classed(CLASS.INCLUDED, !isIncluded);
  5040. // TODO: included/unincluded callback here
  5041. shape.classed(CLASS.SELECTED, !isSelected);
  5042. toggle.call($$, !isSelected, shape, d, i);
  5043. }
  5044. });
  5045. };
  5046. c3_chart_internal_fn.dragstart = function (mouse) {
  5047. var $$ = this, config = $$.config;
  5048. if ($$.hasArcType()) { return; }
  5049. if (! config.data_selection_enabled) { return; } // do nothing if not selectable
  5050. $$.dragStart = mouse;
  5051. $$.main.select('.' + CLASS.chart).append('rect')
  5052. .attr('class', CLASS.dragarea)
  5053. .style('opacity', 0.1);
  5054. $$.dragging = true;
  5055. };
  5056. c3_chart_internal_fn.dragend = function () {
  5057. var $$ = this, config = $$.config;
  5058. if ($$.hasArcType()) { return; }
  5059. if (! config.data_selection_enabled) { return; } // do nothing if not selectable
  5060. $$.main.select('.' + CLASS.dragarea)
  5061. .transition().duration(100)
  5062. .style('opacity', 0)
  5063. .remove();
  5064. $$.main.selectAll('.' + CLASS.shape)
  5065. .classed(CLASS.INCLUDED, false);
  5066. $$.dragging = false;
  5067. };
  5068. c3_chart_internal_fn.selectPoint = function (target, d, i) {
  5069. var $$ = this, config = $$.config,
  5070. cx = (config.axis_rotated ? $$.circleY : $$.circleX).bind($$),
  5071. cy = (config.axis_rotated ? $$.circleX : $$.circleY).bind($$),
  5072. r = $$.pointSelectR.bind($$);
  5073. config.data_onselected.call($$.api, d, target.node());
  5074. // add selected-circle on low layer g
  5075. $$.main.select('.' + CLASS.selectedCircles + $$.getTargetSelectorSuffix(d.id)).selectAll('.' + CLASS.selectedCircle + '-' + i)
  5076. .data([d])
  5077. .enter().append('circle')
  5078. .attr("class", function () { return $$.generateClass(CLASS.selectedCircle, i); })
  5079. .attr("cx", cx)
  5080. .attr("cy", cy)
  5081. .attr("stroke", function () { return $$.color(d); })
  5082. .attr("r", function (d) { return $$.pointSelectR(d) * 1.4; })
  5083. .transition().duration(100)
  5084. .attr("r", r);
  5085. };
  5086. c3_chart_internal_fn.unselectPoint = function (target, d, i) {
  5087. var $$ = this;
  5088. $$.config.data_onunselected.call($$.api, d, target.node());
  5089. // remove selected-circle from low layer g
  5090. $$.main.select('.' + CLASS.selectedCircles + $$.getTargetSelectorSuffix(d.id)).selectAll('.' + CLASS.selectedCircle + '-' + i)
  5091. .transition().duration(100).attr('r', 0)
  5092. .remove();
  5093. };
  5094. c3_chart_internal_fn.togglePoint = function (selected, target, d, i) {
  5095. selected ? this.selectPoint(target, d, i) : this.unselectPoint(target, d, i);
  5096. };
  5097. c3_chart_internal_fn.selectPath = function (target, d) {
  5098. var $$ = this;
  5099. $$.config.data_onselected.call($$, d, target.node());
  5100. if ($$.config.interaction_brighten) {
  5101. target.transition().duration(100)
  5102. .style("fill", function () { return $$.d3.rgb($$.color(d)).brighter(0.75); });
  5103. }
  5104. };
  5105. c3_chart_internal_fn.unselectPath = function (target, d) {
  5106. var $$ = this;
  5107. $$.config.data_onunselected.call($$, d, target.node());
  5108. if ($$.config.interaction_brighten) {
  5109. target.transition().duration(100)
  5110. .style("fill", function () { return $$.color(d); });
  5111. }
  5112. };
  5113. c3_chart_internal_fn.togglePath = function (selected, target, d, i) {
  5114. selected ? this.selectPath(target, d, i) : this.unselectPath(target, d, i);
  5115. };
  5116. c3_chart_internal_fn.getToggle = function (that, d) {
  5117. var $$ = this, toggle;
  5118. if (that.nodeName === 'circle') {
  5119. if ($$.isStepType(d)) {
  5120. // circle is hidden in step chart, so treat as within the click area
  5121. toggle = function () {}; // TODO: how to select step chart?
  5122. } else {
  5123. toggle = $$.togglePoint;
  5124. }
  5125. }
  5126. else if (that.nodeName === 'path') {
  5127. toggle = $$.togglePath;
  5128. }
  5129. return toggle;
  5130. };
  5131. c3_chart_internal_fn.toggleShape = function (that, d, i) {
  5132. var $$ = this, d3 = $$.d3, config = $$.config,
  5133. shape = d3.select(that), isSelected = shape.classed(CLASS.SELECTED),
  5134. toggle = $$.getToggle(that, d).bind($$);
  5135. if (config.data_selection_enabled && config.data_selection_isselectable(d)) {
  5136. if (!config.data_selection_multiple) {
  5137. $$.main.selectAll('.' + CLASS.shapes + (config.data_selection_grouped ? $$.getTargetSelectorSuffix(d.id) : "")).selectAll('.' + CLASS.shape).each(function (d, i) {
  5138. var shape = d3.select(this);
  5139. if (shape.classed(CLASS.SELECTED)) { toggle(false, shape.classed(CLASS.SELECTED, false), d, i); }
  5140. });
  5141. }
  5142. shape.classed(CLASS.SELECTED, !isSelected);
  5143. toggle(!isSelected, shape, d, i);
  5144. }
  5145. };
  5146. c3_chart_internal_fn.initBrush = function () {
  5147. var $$ = this, d3 = $$.d3;
  5148. $$.brush = d3.svg.brush().on("brush", function () { $$.redrawForBrush(); });
  5149. $$.brush.update = function () {
  5150. if ($$.context) { $$.context.select('.' + CLASS.brush).call(this); }
  5151. return this;
  5152. };
  5153. $$.brush.scale = function (scale) {
  5154. return $$.config.axis_rotated ? this.y(scale) : this.x(scale);
  5155. };
  5156. };
  5157. c3_chart_internal_fn.initSubchart = function () {
  5158. var $$ = this, config = $$.config,
  5159. context = $$.context = $$.svg.append("g").attr("transform", $$.getTranslate('context')),
  5160. visibility = config.subchart_show ? 'visible' : 'hidden';
  5161. context.style('visibility', visibility);
  5162. // Define g for chart area
  5163. context.append('g')
  5164. .attr("clip-path", $$.clipPathForSubchart)
  5165. .attr('class', CLASS.chart);
  5166. // Define g for bar chart area
  5167. context.select('.' + CLASS.chart).append("g")
  5168. .attr("class", CLASS.chartBars);
  5169. // Define g for line chart area
  5170. context.select('.' + CLASS.chart).append("g")
  5171. .attr("class", CLASS.chartLines);
  5172. // Add extent rect for Brush
  5173. context.append("g")
  5174. .attr("clip-path", $$.clipPath)
  5175. .attr("class", CLASS.brush)
  5176. .call($$.brush);
  5177. // ATTENTION: This must be called AFTER chart added
  5178. // Add Axis
  5179. $$.axes.subx = context.append("g")
  5180. .attr("class", CLASS.axisX)
  5181. .attr("transform", $$.getTranslate('subx'))
  5182. .attr("clip-path", config.axis_rotated ? "" : $$.clipPathForXAxis)
  5183. .style("visibility", config.subchart_axis_x_show ? visibility : 'hidden');
  5184. };
  5185. c3_chart_internal_fn.updateTargetsForSubchart = function (targets) {
  5186. var $$ = this, context = $$.context, config = $$.config,
  5187. contextLineEnter, contextLineUpdate, contextBarEnter, contextBarUpdate,
  5188. classChartBar = $$.classChartBar.bind($$),
  5189. classBars = $$.classBars.bind($$),
  5190. classChartLine = $$.classChartLine.bind($$),
  5191. classLines = $$.classLines.bind($$),
  5192. classAreas = $$.classAreas.bind($$);
  5193. if (config.subchart_show) {
  5194. //-- Bar --//
  5195. contextBarUpdate = context.select('.' + CLASS.chartBars).selectAll('.' + CLASS.chartBar)
  5196. .data(targets)
  5197. .attr('class', classChartBar);
  5198. contextBarEnter = contextBarUpdate.enter().append('g')
  5199. .style('opacity', 0)
  5200. .attr('class', classChartBar);
  5201. // Bars for each data
  5202. contextBarEnter.append('g')
  5203. .attr("class", classBars);
  5204. //-- Line --//
  5205. contextLineUpdate = context.select('.' + CLASS.chartLines).selectAll('.' + CLASS.chartLine)
  5206. .data(targets)
  5207. .attr('class', classChartLine);
  5208. contextLineEnter = contextLineUpdate.enter().append('g')
  5209. .style('opacity', 0)
  5210. .attr('class', classChartLine);
  5211. // Lines for each data
  5212. contextLineEnter.append("g")
  5213. .attr("class", classLines);
  5214. // Area
  5215. contextLineEnter.append("g")
  5216. .attr("class", classAreas);
  5217. //-- Brush --//
  5218. context.selectAll('.' + CLASS.brush + ' rect')
  5219. .attr(config.axis_rotated ? "width" : "height", config.axis_rotated ? $$.width2 : $$.height2);
  5220. }
  5221. };
  5222. c3_chart_internal_fn.updateBarForSubchart = function (durationForExit) {
  5223. var $$ = this;
  5224. $$.contextBar = $$.context.selectAll('.' + CLASS.bars).selectAll('.' + CLASS.bar)
  5225. .data($$.barData.bind($$));
  5226. $$.contextBar.enter().append('path')
  5227. .attr("class", $$.classBar.bind($$))
  5228. .style("stroke", 'none')
  5229. .style("fill", $$.color);
  5230. $$.contextBar
  5231. .style("opacity", $$.initialOpacity.bind($$));
  5232. $$.contextBar.exit().transition().duration(durationForExit)
  5233. .style('opacity', 0)
  5234. .remove();
  5235. };
  5236. c3_chart_internal_fn.redrawBarForSubchart = function (drawBarOnSub, withTransition, duration) {
  5237. (withTransition ? this.contextBar.transition(Math.random().toString()).duration(duration) : this.contextBar)
  5238. .attr('d', drawBarOnSub)
  5239. .style('opacity', 1);
  5240. };
  5241. c3_chart_internal_fn.updateLineForSubchart = function (durationForExit) {
  5242. var $$ = this;
  5243. $$.contextLine = $$.context.selectAll('.' + CLASS.lines).selectAll('.' + CLASS.line)
  5244. .data($$.lineData.bind($$));
  5245. $$.contextLine.enter().append('path')
  5246. .attr('class', $$.classLine.bind($$))
  5247. .style('stroke', $$.color);
  5248. $$.contextLine
  5249. .style("opacity", $$.initialOpacity.bind($$));
  5250. $$.contextLine.exit().transition().duration(durationForExit)
  5251. .style('opacity', 0)
  5252. .remove();
  5253. };
  5254. c3_chart_internal_fn.redrawLineForSubchart = function (drawLineOnSub, withTransition, duration) {
  5255. (withTransition ? this.contextLine.transition(Math.random().toString()).duration(duration) : this.contextLine)
  5256. .attr("d", drawLineOnSub)
  5257. .style('opacity', 1);
  5258. };
  5259. c3_chart_internal_fn.updateAreaForSubchart = function (durationForExit) {
  5260. var $$ = this, d3 = $$.d3;
  5261. $$.contextArea = $$.context.selectAll('.' + CLASS.areas).selectAll('.' + CLASS.area)
  5262. .data($$.lineData.bind($$));
  5263. $$.contextArea.enter().append('path')
  5264. .attr("class", $$.classArea.bind($$))
  5265. .style("fill", $$.color)
  5266. .style("opacity", function () { $$.orgAreaOpacity = +d3.select(this).style('opacity'); return 0; });
  5267. $$.contextArea
  5268. .style("opacity", 0);
  5269. $$.contextArea.exit().transition().duration(durationForExit)
  5270. .style('opacity', 0)
  5271. .remove();
  5272. };
  5273. c3_chart_internal_fn.redrawAreaForSubchart = function (drawAreaOnSub, withTransition, duration) {
  5274. (withTransition ? this.contextArea.transition(Math.random().toString()).duration(duration) : this.contextArea)
  5275. .attr("d", drawAreaOnSub)
  5276. .style("fill", this.color)
  5277. .style("opacity", this.orgAreaOpacity);
  5278. };
  5279. c3_chart_internal_fn.redrawSubchart = function (withSubchart, transitions, duration, durationForExit, areaIndices, barIndices, lineIndices) {
  5280. var $$ = this, d3 = $$.d3, config = $$.config,
  5281. drawAreaOnSub, drawBarOnSub, drawLineOnSub;
  5282. $$.context.style('visibility', config.subchart_show ? 'visible' : 'hidden');
  5283. // subchart
  5284. if (config.subchart_show) {
  5285. // reflect main chart to extent on subchart if zoomed
  5286. if (d3.event && d3.event.type === 'zoom') {
  5287. $$.brush.extent($$.x.orgDomain()).update();
  5288. }
  5289. // update subchart elements if needed
  5290. if (withSubchart) {
  5291. // extent rect
  5292. if (!$$.brush.empty()) {
  5293. $$.brush.extent($$.x.orgDomain()).update();
  5294. }
  5295. // setup drawer - MEMO: this must be called after axis updated
  5296. drawAreaOnSub = $$.generateDrawArea(areaIndices, true);
  5297. drawBarOnSub = $$.generateDrawBar(barIndices, true);
  5298. drawLineOnSub = $$.generateDrawLine(lineIndices, true);
  5299. $$.updateBarForSubchart(duration);
  5300. $$.updateLineForSubchart(duration);
  5301. $$.updateAreaForSubchart(duration);
  5302. $$.redrawBarForSubchart(drawBarOnSub, duration, duration);
  5303. $$.redrawLineForSubchart(drawLineOnSub, duration, duration);
  5304. $$.redrawAreaForSubchart(drawAreaOnSub, duration, duration);
  5305. }
  5306. }
  5307. };
  5308. c3_chart_internal_fn.redrawForBrush = function () {
  5309. var $$ = this, x = $$.x;
  5310. $$.redraw({
  5311. withTransition: false,
  5312. withY: $$.config.zoom_rescale,
  5313. withSubchart: false,
  5314. withUpdateXDomain: true,
  5315. withDimension: false
  5316. });
  5317. $$.config.subchart_onbrush.call($$.api, x.orgDomain());
  5318. };
  5319. c3_chart_internal_fn.transformContext = function (withTransition, transitions) {
  5320. var $$ = this, subXAxis;
  5321. if (transitions && transitions.axisSubX) {
  5322. subXAxis = transitions.axisSubX;
  5323. } else {
  5324. subXAxis = $$.context.select('.' + CLASS.axisX);
  5325. if (withTransition) { subXAxis = subXAxis.transition(); }
  5326. }
  5327. $$.context.attr("transform", $$.getTranslate('context'));
  5328. subXAxis.attr("transform", $$.getTranslate('subx'));
  5329. };
  5330. c3_chart_internal_fn.getDefaultExtent = function () {
  5331. var $$ = this, config = $$.config,
  5332. extent = isFunction(config.axis_x_extent) ? config.axis_x_extent($$.getXDomain($$.data.targets)) : config.axis_x_extent;
  5333. if ($$.isTimeSeries()) {
  5334. extent = [$$.parseDate(extent[0]), $$.parseDate(extent[1])];
  5335. }
  5336. return extent;
  5337. };
  5338. c3_chart_internal_fn.initZoom = function () {
  5339. var $$ = this, d3 = $$.d3, config = $$.config, startEvent;
  5340. $$.zoom = d3.behavior.zoom()
  5341. .on("zoomstart", function () {
  5342. startEvent = d3.event.sourceEvent;
  5343. $$.zoom.altDomain = d3.event.sourceEvent.altKey ? $$.x.orgDomain() : null;
  5344. config.zoom_onzoomstart.call($$.api, d3.event.sourceEvent);
  5345. })
  5346. .on("zoom", function () {
  5347. $$.redrawForZoom.call($$);
  5348. })
  5349. .on('zoomend', function () {
  5350. var event = d3.event.sourceEvent;
  5351. // if click, do nothing. otherwise, click interaction will be canceled.
  5352. if (event && startEvent.clientX === event.clientX && startEvent.clientY === event.clientY) {
  5353. return;
  5354. }
  5355. $$.redrawEventRect();
  5356. $$.updateZoom();
  5357. config.zoom_onzoomend.call($$.api, $$.x.orgDomain());
  5358. });
  5359. $$.zoom.scale = function (scale) {
  5360. return config.axis_rotated ? this.y(scale) : this.x(scale);
  5361. };
  5362. $$.zoom.orgScaleExtent = function () {
  5363. var extent = config.zoom_extent ? config.zoom_extent : [1, 10];
  5364. return [extent[0], Math.max($$.getMaxDataCount() / extent[1], extent[1])];
  5365. };
  5366. $$.zoom.updateScaleExtent = function () {
  5367. var ratio = diffDomain($$.x.orgDomain()) / diffDomain($$.getZoomDomain()),
  5368. extent = this.orgScaleExtent();
  5369. this.scaleExtent([extent[0] * ratio, extent[1] * ratio]);
  5370. return this;
  5371. };
  5372. };
  5373. c3_chart_internal_fn.getZoomDomain = function () {
  5374. var $$ = this, config = $$.config, d3 = $$.d3,
  5375. min = d3.min([$$.orgXDomain[0], config.zoom_x_min]),
  5376. max = d3.max([$$.orgXDomain[1], config.zoom_x_max]);
  5377. return [min, max];
  5378. };
  5379. c3_chart_internal_fn.updateZoom = function () {
  5380. var $$ = this, z = $$.config.zoom_enabled ? $$.zoom : function () {};
  5381. $$.main.select('.' + CLASS.zoomRect).call(z).on("dblclick.zoom", null);
  5382. $$.main.selectAll('.' + CLASS.eventRect).call(z).on("dblclick.zoom", null);
  5383. };
  5384. c3_chart_internal_fn.redrawForZoom = function () {
  5385. var $$ = this, d3 = $$.d3, config = $$.config, zoom = $$.zoom, x = $$.x;
  5386. if (!config.zoom_enabled) {
  5387. return;
  5388. }
  5389. if ($$.filterTargetsToShow($$.data.targets).length === 0) {
  5390. return;
  5391. }
  5392. if (d3.event.sourceEvent.type === 'mousemove' && zoom.altDomain) {
  5393. x.domain(zoom.altDomain);
  5394. zoom.scale(x).updateScaleExtent();
  5395. return;
  5396. }
  5397. if ($$.isCategorized() && x.orgDomain()[0] === $$.orgXDomain[0]) {
  5398. x.domain([$$.orgXDomain[0] - 1e-10, x.orgDomain()[1]]);
  5399. }
  5400. $$.redraw({
  5401. withTransition: false,
  5402. withY: config.zoom_rescale,
  5403. withSubchart: false,
  5404. withEventRect: false,
  5405. withDimension: false
  5406. });
  5407. if (d3.event.sourceEvent.type === 'mousemove') {
  5408. $$.cancelClick = true;
  5409. }
  5410. config.zoom_onzoom.call($$.api, x.orgDomain());
  5411. };
  5412. c3_chart_internal_fn.generateColor = function () {
  5413. var $$ = this, config = $$.config, d3 = $$.d3,
  5414. colors = config.data_colors,
  5415. pattern = notEmpty(config.color_pattern) ? config.color_pattern : d3.scale.category10().range(),
  5416. callback = config.data_color,
  5417. ids = [];
  5418. return function (d) {
  5419. var id = d.id || (d.data && d.data.id) || d, color;
  5420. // if callback function is provided
  5421. if (colors[id] instanceof Function) {
  5422. color = colors[id](d);
  5423. }
  5424. // if specified, choose that color
  5425. else if (colors[id]) {
  5426. color = colors[id];
  5427. }
  5428. // if not specified, choose from pattern
  5429. else {
  5430. if (ids.indexOf(id) < 0) { ids.push(id); }
  5431. color = pattern[ids.indexOf(id) % pattern.length];
  5432. colors[id] = color;
  5433. }
  5434. return callback instanceof Function ? callback(color, d) : color;
  5435. };
  5436. };
  5437. c3_chart_internal_fn.generateLevelColor = function () {
  5438. var $$ = this, config = $$.config,
  5439. colors = config.color_pattern,
  5440. threshold = config.color_threshold,
  5441. asValue = threshold.unit === 'value',
  5442. values = threshold.values && threshold.values.length ? threshold.values : [],
  5443. max = threshold.max || 100;
  5444. return notEmpty(config.color_threshold) ? function (value) {
  5445. var i, v, color = colors[colors.length - 1];
  5446. for (i = 0; i < values.length; i++) {
  5447. v = asValue ? value : (value * 100 / max);
  5448. if (v < values[i]) {
  5449. color = colors[i];
  5450. break;
  5451. }
  5452. }
  5453. return color;
  5454. } : null;
  5455. };
  5456. c3_chart_internal_fn.getYFormat = function (forArc) {
  5457. var $$ = this,
  5458. formatForY = forArc && !$$.hasType('gauge') ? $$.defaultArcValueFormat : $$.yFormat,
  5459. formatForY2 = forArc && !$$.hasType('gauge') ? $$.defaultArcValueFormat : $$.y2Format;
  5460. return function (v, ratio, id) {
  5461. var format = $$.axis.getId(id) === 'y2' ? formatForY2 : formatForY;
  5462. return format.call($$, v, ratio);
  5463. };
  5464. };
  5465. c3_chart_internal_fn.yFormat = function (v) {
  5466. var $$ = this, config = $$.config,
  5467. format = config.axis_y_tick_format ? config.axis_y_tick_format : $$.defaultValueFormat;
  5468. return format(v);
  5469. };
  5470. c3_chart_internal_fn.y2Format = function (v) {
  5471. var $$ = this, config = $$.config,
  5472. format = config.axis_y2_tick_format ? config.axis_y2_tick_format : $$.defaultValueFormat;
  5473. return format(v);
  5474. };
  5475. c3_chart_internal_fn.defaultValueFormat = function (v) {
  5476. return isValue(v) ? +v : "";
  5477. };
  5478. c3_chart_internal_fn.defaultArcValueFormat = function (v, ratio) {
  5479. return (ratio * 100).toFixed(1) + '%';
  5480. };
  5481. c3_chart_internal_fn.dataLabelFormat = function (targetId) {
  5482. var $$ = this, data_labels = $$.config.data_labels,
  5483. format, defaultFormat = function (v) { return isValue(v) ? +v : ""; };
  5484. // find format according to axis id
  5485. if (typeof data_labels.format === 'function') {
  5486. format = data_labels.format;
  5487. } else if (typeof data_labels.format === 'object') {
  5488. if (data_labels.format[targetId]) {
  5489. format = data_labels.format[targetId] === true ? defaultFormat : data_labels.format[targetId];
  5490. } else {
  5491. format = function () { return ''; };
  5492. }
  5493. } else {
  5494. format = defaultFormat;
  5495. }
  5496. return format;
  5497. };
  5498. c3_chart_internal_fn.hasCaches = function (ids) {
  5499. for (var i = 0; i < ids.length; i++) {
  5500. if (! (ids[i] in this.cache)) { return false; }
  5501. }
  5502. return true;
  5503. };
  5504. c3_chart_internal_fn.addCache = function (id, target) {
  5505. this.cache[id] = this.cloneTarget(target);
  5506. };
  5507. c3_chart_internal_fn.getCaches = function (ids) {
  5508. var targets = [], i;
  5509. for (i = 0; i < ids.length; i++) {
  5510. if (ids[i] in this.cache) { targets.push(this.cloneTarget(this.cache[ids[i]])); }
  5511. }
  5512. return targets;
  5513. };
  5514. var CLASS = c3_chart_internal_fn.CLASS = {
  5515. target: 'c3-target',
  5516. chart: 'c3-chart',
  5517. chartLine: 'c3-chart-line',
  5518. chartLines: 'c3-chart-lines',
  5519. chartBar: 'c3-chart-bar',
  5520. chartBars: 'c3-chart-bars',
  5521. chartText: 'c3-chart-text',
  5522. chartTexts: 'c3-chart-texts',
  5523. chartArc: 'c3-chart-arc',
  5524. chartArcs: 'c3-chart-arcs',
  5525. chartArcsTitle: 'c3-chart-arcs-title',
  5526. chartArcsBackground: 'c3-chart-arcs-background',
  5527. chartArcsGaugeUnit: 'c3-chart-arcs-gauge-unit',
  5528. chartArcsGaugeMax: 'c3-chart-arcs-gauge-max',
  5529. chartArcsGaugeMin: 'c3-chart-arcs-gauge-min',
  5530. selectedCircle: 'c3-selected-circle',
  5531. selectedCircles: 'c3-selected-circles',
  5532. eventRect: 'c3-event-rect',
  5533. eventRects: 'c3-event-rects',
  5534. eventRectsSingle: 'c3-event-rects-single',
  5535. eventRectsMultiple: 'c3-event-rects-multiple',
  5536. zoomRect: 'c3-zoom-rect',
  5537. brush: 'c3-brush',
  5538. focused: 'c3-focused',
  5539. defocused: 'c3-defocused',
  5540. region: 'c3-region',
  5541. regions: 'c3-regions',
  5542. title: 'c3-title',
  5543. tooltipContainer: 'c3-tooltip-container',
  5544. tooltip: 'c3-tooltip',
  5545. tooltipName: 'c3-tooltip-name',
  5546. shape: 'c3-shape',
  5547. shapes: 'c3-shapes',
  5548. line: 'c3-line',
  5549. lines: 'c3-lines',
  5550. bar: 'c3-bar',
  5551. bars: 'c3-bars',
  5552. circle: 'c3-circle',
  5553. circles: 'c3-circles',
  5554. arc: 'c3-arc',
  5555. arcs: 'c3-arcs',
  5556. area: 'c3-area',
  5557. areas: 'c3-areas',
  5558. empty: 'c3-empty',
  5559. text: 'c3-text',
  5560. texts: 'c3-texts',
  5561. gaugeValue: 'c3-gauge-value',
  5562. grid: 'c3-grid',
  5563. gridLines: 'c3-grid-lines',
  5564. xgrid: 'c3-xgrid',
  5565. xgrids: 'c3-xgrids',
  5566. xgridLine: 'c3-xgrid-line',
  5567. xgridLines: 'c3-xgrid-lines',
  5568. xgridFocus: 'c3-xgrid-focus',
  5569. ygrid: 'c3-ygrid',
  5570. ygrids: 'c3-ygrids',
  5571. ygridLine: 'c3-ygrid-line',
  5572. ygridLines: 'c3-ygrid-lines',
  5573. axis: 'c3-axis',
  5574. axisX: 'c3-axis-x',
  5575. axisXLabel: 'c3-axis-x-label',
  5576. axisY: 'c3-axis-y',
  5577. axisYLabel: 'c3-axis-y-label',
  5578. axisY2: 'c3-axis-y2',
  5579. axisY2Label: 'c3-axis-y2-label',
  5580. legendBackground: 'c3-legend-background',
  5581. legendItem: 'c3-legend-item',
  5582. legendItemEvent: 'c3-legend-item-event',
  5583. legendItemTile: 'c3-legend-item-tile',
  5584. legendItemHidden: 'c3-legend-item-hidden',
  5585. legendItemFocused: 'c3-legend-item-focused',
  5586. dragarea: 'c3-dragarea',
  5587. EXPANDED: '_expanded_',
  5588. SELECTED: '_selected_',
  5589. INCLUDED: '_included_'
  5590. };
  5591. c3_chart_internal_fn.generateClass = function (prefix, targetId) {
  5592. return " " + prefix + " " + prefix + this.getTargetSelectorSuffix(targetId);
  5593. };
  5594. c3_chart_internal_fn.classText = function (d) {
  5595. return this.generateClass(CLASS.text, d.index);
  5596. };
  5597. c3_chart_internal_fn.classTexts = function (d) {
  5598. return this.generateClass(CLASS.texts, d.id);
  5599. };
  5600. c3_chart_internal_fn.classShape = function (d) {
  5601. return this.generateClass(CLASS.shape, d.index);
  5602. };
  5603. c3_chart_internal_fn.classShapes = function (d) {
  5604. return this.generateClass(CLASS.shapes, d.id);
  5605. };
  5606. c3_chart_internal_fn.classLine = function (d) {
  5607. return this.classShape(d) + this.generateClass(CLASS.line, d.id);
  5608. };
  5609. c3_chart_internal_fn.classLines = function (d) {
  5610. return this.classShapes(d) + this.generateClass(CLASS.lines, d.id);
  5611. };
  5612. c3_chart_internal_fn.classCircle = function (d) {
  5613. return this.classShape(d) + this.generateClass(CLASS.circle, d.index);
  5614. };
  5615. c3_chart_internal_fn.classCircles = function (d) {
  5616. return this.classShapes(d) + this.generateClass(CLASS.circles, d.id);
  5617. };
  5618. c3_chart_internal_fn.classBar = function (d) {
  5619. return this.classShape(d) + this.generateClass(CLASS.bar, d.index);
  5620. };
  5621. c3_chart_internal_fn.classBars = function (d) {
  5622. return this.classShapes(d) + this.generateClass(CLASS.bars, d.id);
  5623. };
  5624. c3_chart_internal_fn.classArc = function (d) {
  5625. return this.classShape(d.data) + this.generateClass(CLASS.arc, d.data.id);
  5626. };
  5627. c3_chart_internal_fn.classArcs = function (d) {
  5628. return this.classShapes(d.data) + this.generateClass(CLASS.arcs, d.data.id);
  5629. };
  5630. c3_chart_internal_fn.classArea = function (d) {
  5631. return this.classShape(d) + this.generateClass(CLASS.area, d.id);
  5632. };
  5633. c3_chart_internal_fn.classAreas = function (d) {
  5634. return this.classShapes(d) + this.generateClass(CLASS.areas, d.id);
  5635. };
  5636. c3_chart_internal_fn.classRegion = function (d, i) {
  5637. return this.generateClass(CLASS.region, i) + ' ' + ('class' in d ? d['class'] : '');
  5638. };
  5639. c3_chart_internal_fn.classEvent = function (d) {
  5640. return this.generateClass(CLASS.eventRect, d.index);
  5641. };
  5642. c3_chart_internal_fn.classTarget = function (id) {
  5643. var $$ = this;
  5644. var additionalClassSuffix = $$.config.data_classes[id], additionalClass = '';
  5645. if (additionalClassSuffix) {
  5646. additionalClass = ' ' + CLASS.target + '-' + additionalClassSuffix;
  5647. }
  5648. return $$.generateClass(CLASS.target, id) + additionalClass;
  5649. };
  5650. c3_chart_internal_fn.classFocus = function (d) {
  5651. return this.classFocused(d) + this.classDefocused(d);
  5652. };
  5653. c3_chart_internal_fn.classFocused = function (d) {
  5654. return ' ' + (this.focusedTargetIds.indexOf(d.id) >= 0 ? CLASS.focused : '');
  5655. };
  5656. c3_chart_internal_fn.classDefocused = function (d) {
  5657. return ' ' + (this.defocusedTargetIds.indexOf(d.id) >= 0 ? CLASS.defocused : '');
  5658. };
  5659. c3_chart_internal_fn.classChartText = function (d) {
  5660. return CLASS.chartText + this.classTarget(d.id);
  5661. };
  5662. c3_chart_internal_fn.classChartLine = function (d) {
  5663. return CLASS.chartLine + this.classTarget(d.id);
  5664. };
  5665. c3_chart_internal_fn.classChartBar = function (d) {
  5666. return CLASS.chartBar + this.classTarget(d.id);
  5667. };
  5668. c3_chart_internal_fn.classChartArc = function (d) {
  5669. return CLASS.chartArc + this.classTarget(d.data.id);
  5670. };
  5671. c3_chart_internal_fn.getTargetSelectorSuffix = function (targetId) {
  5672. return targetId || targetId === 0 ? ('-' + targetId).replace(/[\s?!@#$%^&*()_=+,.<>'":;\[\]\/|~`{}\\]/g, '-') : '';
  5673. };
  5674. c3_chart_internal_fn.selectorTarget = function (id, prefix) {
  5675. return (prefix || '') + '.' + CLASS.target + this.getTargetSelectorSuffix(id);
  5676. };
  5677. c3_chart_internal_fn.selectorTargets = function (ids, prefix) {
  5678. var $$ = this;
  5679. ids = ids || [];
  5680. return ids.length ? ids.map(function (id) { return $$.selectorTarget(id, prefix); }) : null;
  5681. };
  5682. c3_chart_internal_fn.selectorLegend = function (id) {
  5683. return '.' + CLASS.legendItem + this.getTargetSelectorSuffix(id);
  5684. };
  5685. c3_chart_internal_fn.selectorLegends = function (ids) {
  5686. var $$ = this;
  5687. return ids && ids.length ? ids.map(function (id) { return $$.selectorLegend(id); }) : null;
  5688. };
  5689. var isValue = c3_chart_internal_fn.isValue = function (v) {
  5690. return v || v === 0;
  5691. },
  5692. isFunction = c3_chart_internal_fn.isFunction = function (o) {
  5693. return typeof o === 'function';
  5694. },
  5695. isString = c3_chart_internal_fn.isString = function (o) {
  5696. return typeof o === 'string';
  5697. },
  5698. isUndefined = c3_chart_internal_fn.isUndefined = function (v) {
  5699. return typeof v === 'undefined';
  5700. },
  5701. isDefined = c3_chart_internal_fn.isDefined = function (v) {
  5702. return typeof v !== 'undefined';
  5703. },
  5704. ceil10 = c3_chart_internal_fn.ceil10 = function (v) {
  5705. return Math.ceil(v / 10) * 10;
  5706. },
  5707. asHalfPixel = c3_chart_internal_fn.asHalfPixel = function (n) {
  5708. return Math.ceil(n) + 0.5;
  5709. },
  5710. diffDomain = c3_chart_internal_fn.diffDomain = function (d) {
  5711. return d[1] - d[0];
  5712. },
  5713. isEmpty = c3_chart_internal_fn.isEmpty = function (o) {
  5714. return typeof o === 'undefined' || o === null || (isString(o) && o.length === 0) || (typeof o === 'object' && Object.keys(o).length === 0);
  5715. },
  5716. notEmpty = c3_chart_internal_fn.notEmpty = function (o) {
  5717. return !c3_chart_internal_fn.isEmpty(o);
  5718. },
  5719. getOption = c3_chart_internal_fn.getOption = function (options, key, defaultValue) {
  5720. return isDefined(options[key]) ? options[key] : defaultValue;
  5721. },
  5722. hasValue = c3_chart_internal_fn.hasValue = function (dict, value) {
  5723. var found = false;
  5724. Object.keys(dict).forEach(function (key) {
  5725. if (dict[key] === value) { found = true; }
  5726. });
  5727. return found;
  5728. },
  5729. sanitise = c3_chart_internal_fn.sanitise = function (str) {
  5730. return typeof str === 'string' ? str.replace(/</g, '&lt;').replace(/>/g, '&gt;') : str;
  5731. },
  5732. getPathBox = c3_chart_internal_fn.getPathBox = function (path) {
  5733. var box = path.getBoundingClientRect(),
  5734. items = [path.pathSegList.getItem(0), path.pathSegList.getItem(1)],
  5735. minX = items[0].x, minY = Math.min(items[0].y, items[1].y);
  5736. return {x: minX, y: minY, width: box.width, height: box.height};
  5737. };
  5738. c3_chart_fn.focus = function (targetIds) {
  5739. var $$ = this.internal, candidates;
  5740. targetIds = $$.mapToTargetIds(targetIds);
  5741. candidates = $$.svg.selectAll($$.selectorTargets(targetIds.filter($$.isTargetToShow, $$))),
  5742. this.revert();
  5743. this.defocus();
  5744. candidates.classed(CLASS.focused, true).classed(CLASS.defocused, false);
  5745. if ($$.hasArcType()) {
  5746. $$.expandArc(targetIds);
  5747. }
  5748. $$.toggleFocusLegend(targetIds, true);
  5749. $$.focusedTargetIds = targetIds;
  5750. $$.defocusedTargetIds = $$.defocusedTargetIds.filter(function (id) {
  5751. return targetIds.indexOf(id) < 0;
  5752. });
  5753. };
  5754. c3_chart_fn.defocus = function (targetIds) {
  5755. var $$ = this.internal, candidates;
  5756. targetIds = $$.mapToTargetIds(targetIds);
  5757. candidates = $$.svg.selectAll($$.selectorTargets(targetIds.filter($$.isTargetToShow, $$))),
  5758. candidates.classed(CLASS.focused, false).classed(CLASS.defocused, true);
  5759. if ($$.hasArcType()) {
  5760. $$.unexpandArc(targetIds);
  5761. }
  5762. $$.toggleFocusLegend(targetIds, false);
  5763. $$.focusedTargetIds = $$.focusedTargetIds.filter(function (id) {
  5764. return targetIds.indexOf(id) < 0;
  5765. });
  5766. $$.defocusedTargetIds = targetIds;
  5767. };
  5768. c3_chart_fn.revert = function (targetIds) {
  5769. var $$ = this.internal, candidates;
  5770. targetIds = $$.mapToTargetIds(targetIds);
  5771. candidates = $$.svg.selectAll($$.selectorTargets(targetIds)); // should be for all targets
  5772. candidates.classed(CLASS.focused, false).classed(CLASS.defocused, false);
  5773. if ($$.hasArcType()) {
  5774. $$.unexpandArc(targetIds);
  5775. }
  5776. if ($$.config.legend_show) {
  5777. $$.showLegend(targetIds.filter($$.isLegendToShow.bind($$)));
  5778. $$.legend.selectAll($$.selectorLegends(targetIds))
  5779. .filter(function () {
  5780. return $$.d3.select(this).classed(CLASS.legendItemFocused);
  5781. })
  5782. .classed(CLASS.legendItemFocused, false);
  5783. }
  5784. $$.focusedTargetIds = [];
  5785. $$.defocusedTargetIds = [];
  5786. };
  5787. c3_chart_fn.show = function (targetIds, options) {
  5788. var $$ = this.internal, targets;
  5789. targetIds = $$.mapToTargetIds(targetIds);
  5790. options = options || {};
  5791. $$.removeHiddenTargetIds(targetIds);
  5792. targets = $$.svg.selectAll($$.selectorTargets(targetIds));
  5793. targets.transition()
  5794. .style('opacity', 1, 'important')
  5795. .call($$.endall, function () {
  5796. targets.style('opacity', null).style('opacity', 1);
  5797. });
  5798. if (options.withLegend) {
  5799. $$.showLegend(targetIds);
  5800. }
  5801. $$.redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true, withLegend: true});
  5802. };
  5803. c3_chart_fn.hide = function (targetIds, options) {
  5804. var $$ = this.internal, targets;
  5805. targetIds = $$.mapToTargetIds(targetIds);
  5806. options = options || {};
  5807. $$.addHiddenTargetIds(targetIds);
  5808. targets = $$.svg.selectAll($$.selectorTargets(targetIds));
  5809. targets.transition()
  5810. .style('opacity', 0, 'important')
  5811. .call($$.endall, function () {
  5812. targets.style('opacity', null).style('opacity', 0);
  5813. });
  5814. if (options.withLegend) {
  5815. $$.hideLegend(targetIds);
  5816. }
  5817. $$.redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true, withLegend: true});
  5818. };
  5819. c3_chart_fn.toggle = function (targetIds, options) {
  5820. var that = this, $$ = this.internal;
  5821. $$.mapToTargetIds(targetIds).forEach(function (targetId) {
  5822. $$.isTargetToShow(targetId) ? that.hide(targetId, options) : that.show(targetId, options);
  5823. });
  5824. };
  5825. c3_chart_fn.zoom = function (domain) {
  5826. var $$ = this.internal;
  5827. if (domain) {
  5828. if ($$.isTimeSeries()) {
  5829. domain = domain.map(function (x) { return $$.parseDate(x); });
  5830. }
  5831. $$.brush.extent(domain);
  5832. $$.redraw({withUpdateXDomain: true, withY: $$.config.zoom_rescale});
  5833. $$.config.zoom_onzoom.call(this, $$.x.orgDomain());
  5834. }
  5835. return $$.brush.extent();
  5836. };
  5837. c3_chart_fn.zoom.enable = function (enabled) {
  5838. var $$ = this.internal;
  5839. $$.config.zoom_enabled = enabled;
  5840. $$.updateAndRedraw();
  5841. };
  5842. c3_chart_fn.unzoom = function () {
  5843. var $$ = this.internal;
  5844. $$.brush.clear().update();
  5845. $$.redraw({withUpdateXDomain: true});
  5846. };
  5847. c3_chart_fn.zoom.max = function (max) {
  5848. var $$ = this.internal, config = $$.config, d3 = $$.d3;
  5849. if (max === 0 || max) {
  5850. config.zoom_x_max = d3.max([$$.orgXDomain[1], max]);
  5851. }
  5852. else {
  5853. return config.zoom_x_max;
  5854. }
  5855. };
  5856. c3_chart_fn.zoom.min = function (min) {
  5857. var $$ = this.internal, config = $$.config, d3 = $$.d3;
  5858. if (min === 0 || min) {
  5859. config.zoom_x_min = d3.min([$$.orgXDomain[0], min]);
  5860. }
  5861. else {
  5862. return config.zoom_x_min;
  5863. }
  5864. };
  5865. c3_chart_fn.zoom.range = function (range) {
  5866. if (arguments.length) {
  5867. if (isDefined(range.max)) { this.domain.max(range.max); }
  5868. if (isDefined(range.min)) { this.domain.min(range.min); }
  5869. } else {
  5870. return {
  5871. max: this.domain.max(),
  5872. min: this.domain.min()
  5873. };
  5874. }
  5875. };
  5876. c3_chart_fn.load = function (args) {
  5877. var $$ = this.internal, config = $$.config;
  5878. // update xs if specified
  5879. if (args.xs) {
  5880. $$.addXs(args.xs);
  5881. }
  5882. // update names if exists
  5883. if ('names' in args) {
  5884. c3_chart_fn.data.names.bind(this)(args.names);
  5885. }
  5886. // update classes if exists
  5887. if ('classes' in args) {
  5888. Object.keys(args.classes).forEach(function (id) {
  5889. config.data_classes[id] = args.classes[id];
  5890. });
  5891. }
  5892. // update categories if exists
  5893. if ('categories' in args && $$.isCategorized()) {
  5894. config.axis_x_categories = args.categories;
  5895. }
  5896. // update axes if exists
  5897. if ('axes' in args) {
  5898. Object.keys(args.axes).forEach(function (id) {
  5899. config.data_axes[id] = args.axes[id];
  5900. });
  5901. }
  5902. // update colors if exists
  5903. if ('colors' in args) {
  5904. Object.keys(args.colors).forEach(function (id) {
  5905. config.data_colors[id] = args.colors[id];
  5906. });
  5907. }
  5908. // use cache if exists
  5909. if ('cacheIds' in args && $$.hasCaches(args.cacheIds)) {
  5910. $$.load($$.getCaches(args.cacheIds), args.done);
  5911. return;
  5912. }
  5913. // unload if needed
  5914. if ('unload' in args) {
  5915. // TODO: do not unload if target will load (included in url/rows/columns)
  5916. $$.unload($$.mapToTargetIds((typeof args.unload === 'boolean' && args.unload) ? null : args.unload), function () {
  5917. $$.loadFromArgs(args);
  5918. });
  5919. } else {
  5920. $$.loadFromArgs(args);
  5921. }
  5922. };
  5923. c3_chart_fn.unload = function (args) {
  5924. var $$ = this.internal;
  5925. args = args || {};
  5926. if (args instanceof Array) {
  5927. args = {ids: args};
  5928. } else if (typeof args === 'string') {
  5929. args = {ids: [args]};
  5930. }
  5931. $$.unload($$.mapToTargetIds(args.ids), function () {
  5932. $$.redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true, withLegend: true});
  5933. if (args.done) { args.done(); }
  5934. });
  5935. };
  5936. c3_chart_fn.flow = function (args) {
  5937. var $$ = this.internal,
  5938. targets, data, notfoundIds = [], orgDataCount = $$.getMaxDataCount(),
  5939. dataCount, domain, baseTarget, baseValue, length = 0, tail = 0, diff, to;
  5940. if (args.json) {
  5941. data = $$.convertJsonToData(args.json, args.keys);
  5942. }
  5943. else if (args.rows) {
  5944. data = $$.convertRowsToData(args.rows);
  5945. }
  5946. else if (args.columns) {
  5947. data = $$.convertColumnsToData(args.columns);
  5948. }
  5949. else {
  5950. return;
  5951. }
  5952. targets = $$.convertDataToTargets(data, true);
  5953. // Update/Add data
  5954. $$.data.targets.forEach(function (t) {
  5955. var found = false, i, j;
  5956. for (i = 0; i < targets.length; i++) {
  5957. if (t.id === targets[i].id) {
  5958. found = true;
  5959. if (t.values[t.values.length - 1]) {
  5960. tail = t.values[t.values.length - 1].index + 1;
  5961. }
  5962. length = targets[i].values.length;
  5963. for (j = 0; j < length; j++) {
  5964. targets[i].values[j].index = tail + j;
  5965. if (!$$.isTimeSeries()) {
  5966. targets[i].values[j].x = tail + j;
  5967. }
  5968. }
  5969. t.values = t.values.concat(targets[i].values);
  5970. targets.splice(i, 1);
  5971. break;
  5972. }
  5973. }
  5974. if (!found) { notfoundIds.push(t.id); }
  5975. });
  5976. // Append null for not found targets
  5977. $$.data.targets.forEach(function (t) {
  5978. var i, j;
  5979. for (i = 0; i < notfoundIds.length; i++) {
  5980. if (t.id === notfoundIds[i]) {
  5981. tail = t.values[t.values.length - 1].index + 1;
  5982. for (j = 0; j < length; j++) {
  5983. t.values.push({
  5984. id: t.id,
  5985. index: tail + j,
  5986. x: $$.isTimeSeries() ? $$.getOtherTargetX(tail + j) : tail + j,
  5987. value: null
  5988. });
  5989. }
  5990. }
  5991. }
  5992. });
  5993. // Generate null values for new target
  5994. if ($$.data.targets.length) {
  5995. targets.forEach(function (t) {
  5996. var i, missing = [];
  5997. for (i = $$.data.targets[0].values[0].index; i < tail; i++) {
  5998. missing.push({
  5999. id: t.id,
  6000. index: i,
  6001. x: $$.isTimeSeries() ? $$.getOtherTargetX(i) : i,
  6002. value: null
  6003. });
  6004. }
  6005. t.values.forEach(function (v) {
  6006. v.index += tail;
  6007. if (!$$.isTimeSeries()) {
  6008. v.x += tail;
  6009. }
  6010. });
  6011. t.values = missing.concat(t.values);
  6012. });
  6013. }
  6014. $$.data.targets = $$.data.targets.concat(targets); // add remained
  6015. // check data count because behavior needs to change when it's only one
  6016. dataCount = $$.getMaxDataCount();
  6017. baseTarget = $$.data.targets[0];
  6018. baseValue = baseTarget.values[0];
  6019. // Update length to flow if needed
  6020. if (isDefined(args.to)) {
  6021. length = 0;
  6022. to = $$.isTimeSeries() ? $$.parseDate(args.to) : args.to;
  6023. baseTarget.values.forEach(function (v) {
  6024. if (v.x < to) { length++; }
  6025. });
  6026. } else if (isDefined(args.length)) {
  6027. length = args.length;
  6028. }
  6029. // If only one data, update the domain to flow from left edge of the chart
  6030. if (!orgDataCount) {
  6031. if ($$.isTimeSeries()) {
  6032. if (baseTarget.values.length > 1) {
  6033. diff = baseTarget.values[baseTarget.values.length - 1].x - baseValue.x;
  6034. } else {
  6035. diff = baseValue.x - $$.getXDomain($$.data.targets)[0];
  6036. }
  6037. } else {
  6038. diff = 1;
  6039. }
  6040. domain = [baseValue.x - diff, baseValue.x];
  6041. $$.updateXDomain(null, true, true, false, domain);
  6042. } else if (orgDataCount === 1) {
  6043. if ($$.isTimeSeries()) {
  6044. diff = (baseTarget.values[baseTarget.values.length - 1].x - baseValue.x) / 2;
  6045. domain = [new Date(+baseValue.x - diff), new Date(+baseValue.x + diff)];
  6046. $$.updateXDomain(null, true, true, false, domain);
  6047. }
  6048. }
  6049. // Set targets
  6050. $$.updateTargets($$.data.targets);
  6051. // Redraw with new targets
  6052. $$.redraw({
  6053. flow: {
  6054. index: baseValue.index,
  6055. length: length,
  6056. duration: isValue(args.duration) ? args.duration : $$.config.transition_duration,
  6057. done: args.done,
  6058. orgDataCount: orgDataCount,
  6059. },
  6060. withLegend: true,
  6061. withTransition: orgDataCount > 1,
  6062. withTrimXDomain: false,
  6063. withUpdateXAxis: true,
  6064. });
  6065. };
  6066. c3_chart_internal_fn.generateFlow = function (args) {
  6067. var $$ = this, config = $$.config, d3 = $$.d3;
  6068. return function () {
  6069. var targets = args.targets,
  6070. flow = args.flow,
  6071. drawBar = args.drawBar,
  6072. drawLine = args.drawLine,
  6073. drawArea = args.drawArea,
  6074. cx = args.cx,
  6075. cy = args.cy,
  6076. xv = args.xv,
  6077. xForText = args.xForText,
  6078. yForText = args.yForText,
  6079. duration = args.duration;
  6080. var translateX, scaleX = 1, transform,
  6081. flowIndex = flow.index,
  6082. flowLength = flow.length,
  6083. flowStart = $$.getValueOnIndex($$.data.targets[0].values, flowIndex),
  6084. flowEnd = $$.getValueOnIndex($$.data.targets[0].values, flowIndex + flowLength),
  6085. orgDomain = $$.x.domain(), domain,
  6086. durationForFlow = flow.duration || duration,
  6087. done = flow.done || function () {},
  6088. wait = $$.generateWait();
  6089. var xgrid = $$.xgrid || d3.selectAll([]),
  6090. xgridLines = $$.xgridLines || d3.selectAll([]),
  6091. mainRegion = $$.mainRegion || d3.selectAll([]),
  6092. mainText = $$.mainText || d3.selectAll([]),
  6093. mainBar = $$.mainBar || d3.selectAll([]),
  6094. mainLine = $$.mainLine || d3.selectAll([]),
  6095. mainArea = $$.mainArea || d3.selectAll([]),
  6096. mainCircle = $$.mainCircle || d3.selectAll([]);
  6097. // set flag
  6098. $$.flowing = true;
  6099. // remove head data after rendered
  6100. $$.data.targets.forEach(function (d) {
  6101. d.values.splice(0, flowLength);
  6102. });
  6103. // update x domain to generate axis elements for flow
  6104. domain = $$.updateXDomain(targets, true, true);
  6105. // update elements related to x scale
  6106. if ($$.updateXGrid) { $$.updateXGrid(true); }
  6107. // generate transform to flow
  6108. if (!flow.orgDataCount) { // if empty
  6109. if ($$.data.targets[0].values.length !== 1) {
  6110. translateX = $$.x(orgDomain[0]) - $$.x(domain[0]);
  6111. } else {
  6112. if ($$.isTimeSeries()) {
  6113. flowStart = $$.getValueOnIndex($$.data.targets[0].values, 0);
  6114. flowEnd = $$.getValueOnIndex($$.data.targets[0].values, $$.data.targets[0].values.length - 1);
  6115. translateX = $$.x(flowStart.x) - $$.x(flowEnd.x);
  6116. } else {
  6117. translateX = diffDomain(domain) / 2;
  6118. }
  6119. }
  6120. } else if (flow.orgDataCount === 1 || (flowStart && flowStart.x) === (flowEnd && flowEnd.x)) {
  6121. translateX = $$.x(orgDomain[0]) - $$.x(domain[0]);
  6122. } else {
  6123. if ($$.isTimeSeries()) {
  6124. translateX = ($$.x(orgDomain[0]) - $$.x(domain[0]));
  6125. } else {
  6126. translateX = ($$.x(flowStart.x) - $$.x(flowEnd.x));
  6127. }
  6128. }
  6129. scaleX = (diffDomain(orgDomain) / diffDomain(domain));
  6130. transform = 'translate(' + translateX + ',0) scale(' + scaleX + ',1)';
  6131. $$.hideXGridFocus();
  6132. d3.transition().ease('linear').duration(durationForFlow).each(function () {
  6133. wait.add($$.axes.x.transition().call($$.xAxis));
  6134. wait.add(mainBar.transition().attr('transform', transform));
  6135. wait.add(mainLine.transition().attr('transform', transform));
  6136. wait.add(mainArea.transition().attr('transform', transform));
  6137. wait.add(mainCircle.transition().attr('transform', transform));
  6138. wait.add(mainText.transition().attr('transform', transform));
  6139. wait.add(mainRegion.filter($$.isRegionOnX).transition().attr('transform', transform));
  6140. wait.add(xgrid.transition().attr('transform', transform));
  6141. wait.add(xgridLines.transition().attr('transform', transform));
  6142. })
  6143. .call(wait, function () {
  6144. var i, shapes = [], texts = [], eventRects = [];
  6145. // remove flowed elements
  6146. if (flowLength) {
  6147. for (i = 0; i < flowLength; i++) {
  6148. shapes.push('.' + CLASS.shape + '-' + (flowIndex + i));
  6149. texts.push('.' + CLASS.text + '-' + (flowIndex + i));
  6150. eventRects.push('.' + CLASS.eventRect + '-' + (flowIndex + i));
  6151. }
  6152. $$.svg.selectAll('.' + CLASS.shapes).selectAll(shapes).remove();
  6153. $$.svg.selectAll('.' + CLASS.texts).selectAll(texts).remove();
  6154. $$.svg.selectAll('.' + CLASS.eventRects).selectAll(eventRects).remove();
  6155. $$.svg.select('.' + CLASS.xgrid).remove();
  6156. }
  6157. // draw again for removing flowed elements and reverting attr
  6158. xgrid
  6159. .attr('transform', null)
  6160. .attr($$.xgridAttr);
  6161. xgridLines
  6162. .attr('transform', null);
  6163. xgridLines.select('line')
  6164. .attr("x1", config.axis_rotated ? 0 : xv)
  6165. .attr("x2", config.axis_rotated ? $$.width : xv);
  6166. xgridLines.select('text')
  6167. .attr("x", config.axis_rotated ? $$.width : 0)
  6168. .attr("y", xv);
  6169. mainBar
  6170. .attr('transform', null)
  6171. .attr("d", drawBar);
  6172. mainLine
  6173. .attr('transform', null)
  6174. .attr("d", drawLine);
  6175. mainArea
  6176. .attr('transform', null)
  6177. .attr("d", drawArea);
  6178. mainCircle
  6179. .attr('transform', null)
  6180. .attr("cx", cx)
  6181. .attr("cy", cy);
  6182. mainText
  6183. .attr('transform', null)
  6184. .attr('x', xForText)
  6185. .attr('y', yForText)
  6186. .style('fill-opacity', $$.opacityForText.bind($$));
  6187. mainRegion
  6188. .attr('transform', null);
  6189. mainRegion.select('rect').filter($$.isRegionOnX)
  6190. .attr("x", $$.regionX.bind($$))
  6191. .attr("width", $$.regionWidth.bind($$));
  6192. if (config.interaction_enabled) {
  6193. $$.redrawEventRect();
  6194. }
  6195. // callback for end of flow
  6196. done();
  6197. $$.flowing = false;
  6198. });
  6199. };
  6200. };
  6201. c3_chart_fn.selected = function (targetId) {
  6202. var $$ = this.internal, d3 = $$.d3;
  6203. return d3.merge(
  6204. $$.main.selectAll('.' + CLASS.shapes + $$.getTargetSelectorSuffix(targetId)).selectAll('.' + CLASS.shape)
  6205. .filter(function () { return d3.select(this).classed(CLASS.SELECTED); })
  6206. .map(function (d) { return d.map(function (d) { var data = d.__data__; return data.data ? data.data : data; }); })
  6207. );
  6208. };
  6209. c3_chart_fn.select = function (ids, indices, resetOther) {
  6210. var $$ = this.internal, d3 = $$.d3, config = $$.config;
  6211. if (! config.data_selection_enabled) { return; }
  6212. $$.main.selectAll('.' + CLASS.shapes).selectAll('.' + CLASS.shape).each(function (d, i) {
  6213. var shape = d3.select(this), id = d.data ? d.data.id : d.id,
  6214. toggle = $$.getToggle(this, d).bind($$),
  6215. isTargetId = config.data_selection_grouped || !ids || ids.indexOf(id) >= 0,
  6216. isTargetIndex = !indices || indices.indexOf(i) >= 0,
  6217. isSelected = shape.classed(CLASS.SELECTED);
  6218. // line/area selection not supported yet
  6219. if (shape.classed(CLASS.line) || shape.classed(CLASS.area)) {
  6220. return;
  6221. }
  6222. if (isTargetId && isTargetIndex) {
  6223. if (config.data_selection_isselectable(d) && !isSelected) {
  6224. toggle(true, shape.classed(CLASS.SELECTED, true), d, i);
  6225. }
  6226. } else if (isDefined(resetOther) && resetOther) {
  6227. if (isSelected) {
  6228. toggle(false, shape.classed(CLASS.SELECTED, false), d, i);
  6229. }
  6230. }
  6231. });
  6232. };
  6233. c3_chart_fn.unselect = function (ids, indices) {
  6234. var $$ = this.internal, d3 = $$.d3, config = $$.config;
  6235. if (! config.data_selection_enabled) { return; }
  6236. $$.main.selectAll('.' + CLASS.shapes).selectAll('.' + CLASS.shape).each(function (d, i) {
  6237. var shape = d3.select(this), id = d.data ? d.data.id : d.id,
  6238. toggle = $$.getToggle(this, d).bind($$),
  6239. isTargetId = config.data_selection_grouped || !ids || ids.indexOf(id) >= 0,
  6240. isTargetIndex = !indices || indices.indexOf(i) >= 0,
  6241. isSelected = shape.classed(CLASS.SELECTED);
  6242. // line/area selection not supported yet
  6243. if (shape.classed(CLASS.line) || shape.classed(CLASS.area)) {
  6244. return;
  6245. }
  6246. if (isTargetId && isTargetIndex) {
  6247. if (config.data_selection_isselectable(d)) {
  6248. if (isSelected) {
  6249. toggle(false, shape.classed(CLASS.SELECTED, false), d, i);
  6250. }
  6251. }
  6252. }
  6253. });
  6254. };
  6255. c3_chart_fn.transform = function (type, targetIds) {
  6256. var $$ = this.internal,
  6257. options = ['pie', 'donut'].indexOf(type) >= 0 ? {withTransform: true} : null;
  6258. $$.transformTo(targetIds, type, options);
  6259. };
  6260. c3_chart_internal_fn.transformTo = function (targetIds, type, optionsForRedraw) {
  6261. var $$ = this,
  6262. withTransitionForAxis = !$$.hasArcType(),
  6263. options = optionsForRedraw || {withTransitionForAxis: withTransitionForAxis};
  6264. options.withTransitionForTransform = false;
  6265. $$.transiting = false;
  6266. $$.setTargetType(targetIds, type);
  6267. $$.updateTargets($$.data.targets); // this is needed when transforming to arc
  6268. $$.updateAndRedraw(options);
  6269. };
  6270. c3_chart_fn.groups = function (groups) {
  6271. var $$ = this.internal, config = $$.config;
  6272. if (isUndefined(groups)) { return config.data_groups; }
  6273. config.data_groups = groups;
  6274. $$.redraw();
  6275. return config.data_groups;
  6276. };
  6277. c3_chart_fn.xgrids = function (grids) {
  6278. var $$ = this.internal, config = $$.config;
  6279. if (! grids) { return config.grid_x_lines; }
  6280. config.grid_x_lines = grids;
  6281. $$.redrawWithoutRescale();
  6282. return config.grid_x_lines;
  6283. };
  6284. c3_chart_fn.xgrids.add = function (grids) {
  6285. var $$ = this.internal;
  6286. return this.xgrids($$.config.grid_x_lines.concat(grids ? grids : []));
  6287. };
  6288. c3_chart_fn.xgrids.remove = function (params) { // TODO: multiple
  6289. var $$ = this.internal;
  6290. $$.removeGridLines(params, true);
  6291. };
  6292. c3_chart_fn.ygrids = function (grids) {
  6293. var $$ = this.internal, config = $$.config;
  6294. if (! grids) { return config.grid_y_lines; }
  6295. config.grid_y_lines = grids;
  6296. $$.redrawWithoutRescale();
  6297. return config.grid_y_lines;
  6298. };
  6299. c3_chart_fn.ygrids.add = function (grids) {
  6300. var $$ = this.internal;
  6301. return this.ygrids($$.config.grid_y_lines.concat(grids ? grids : []));
  6302. };
  6303. c3_chart_fn.ygrids.remove = function (params) { // TODO: multiple
  6304. var $$ = this.internal;
  6305. $$.removeGridLines(params, false);
  6306. };
  6307. c3_chart_fn.regions = function (regions) {
  6308. var $$ = this.internal, config = $$.config;
  6309. if (!regions) { return config.regions; }
  6310. config.regions = regions;
  6311. $$.redrawWithoutRescale();
  6312. return config.regions;
  6313. };
  6314. c3_chart_fn.regions.add = function (regions) {
  6315. var $$ = this.internal, config = $$.config;
  6316. if (!regions) { return config.regions; }
  6317. config.regions = config.regions.concat(regions);
  6318. $$.redrawWithoutRescale();
  6319. return config.regions;
  6320. };
  6321. c3_chart_fn.regions.remove = function (options) {
  6322. var $$ = this.internal, config = $$.config,
  6323. duration, classes, regions;
  6324. options = options || {};
  6325. duration = $$.getOption(options, "duration", config.transition_duration);
  6326. classes = $$.getOption(options, "classes", [CLASS.region]);
  6327. regions = $$.main.select('.' + CLASS.regions).selectAll(classes.map(function (c) { return '.' + c; }));
  6328. (duration ? regions.transition().duration(duration) : regions)
  6329. .style('opacity', 0)
  6330. .remove();
  6331. config.regions = config.regions.filter(function (region) {
  6332. var found = false;
  6333. if (!region['class']) {
  6334. return true;
  6335. }
  6336. region['class'].split(' ').forEach(function (c) {
  6337. if (classes.indexOf(c) >= 0) { found = true; }
  6338. });
  6339. return !found;
  6340. });
  6341. return config.regions;
  6342. };
  6343. c3_chart_fn.data = function (targetIds) {
  6344. var targets = this.internal.data.targets;
  6345. return typeof targetIds === 'undefined' ? targets : targets.filter(function (t) {
  6346. return [].concat(targetIds).indexOf(t.id) >= 0;
  6347. });
  6348. };
  6349. c3_chart_fn.data.shown = function (targetIds) {
  6350. return this.internal.filterTargetsToShow(this.data(targetIds));
  6351. };
  6352. c3_chart_fn.data.values = function (targetId) {
  6353. var targets, values = null;
  6354. if (targetId) {
  6355. targets = this.data(targetId);
  6356. values = targets[0] ? targets[0].values.map(function (d) { return d.value; }) : null;
  6357. }
  6358. return values;
  6359. };
  6360. c3_chart_fn.data.names = function (names) {
  6361. this.internal.clearLegendItemTextBoxCache();
  6362. return this.internal.updateDataAttributes('names', names);
  6363. };
  6364. c3_chart_fn.data.colors = function (colors) {
  6365. return this.internal.updateDataAttributes('colors', colors);
  6366. };
  6367. c3_chart_fn.data.axes = function (axes) {
  6368. return this.internal.updateDataAttributes('axes', axes);
  6369. };
  6370. c3_chart_fn.category = function (i, category) {
  6371. var $$ = this.internal, config = $$.config;
  6372. if (arguments.length > 1) {
  6373. config.axis_x_categories[i] = category;
  6374. $$.redraw();
  6375. }
  6376. return config.axis_x_categories[i];
  6377. };
  6378. c3_chart_fn.categories = function (categories) {
  6379. var $$ = this.internal, config = $$.config;
  6380. if (!arguments.length) { return config.axis_x_categories; }
  6381. config.axis_x_categories = categories;
  6382. $$.redraw();
  6383. return config.axis_x_categories;
  6384. };
  6385. // TODO: fix
  6386. c3_chart_fn.color = function (id) {
  6387. var $$ = this.internal;
  6388. return $$.color(id); // more patterns
  6389. };
  6390. c3_chart_fn.x = function (x) {
  6391. var $$ = this.internal;
  6392. if (arguments.length) {
  6393. $$.updateTargetX($$.data.targets, x);
  6394. $$.redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true});
  6395. }
  6396. return $$.data.xs;
  6397. };
  6398. c3_chart_fn.xs = function (xs) {
  6399. var $$ = this.internal;
  6400. if (arguments.length) {
  6401. $$.updateTargetXs($$.data.targets, xs);
  6402. $$.redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true});
  6403. }
  6404. return $$.data.xs;
  6405. };
  6406. c3_chart_fn.axis = function () {};
  6407. c3_chart_fn.axis.labels = function (labels) {
  6408. var $$ = this.internal;
  6409. if (arguments.length) {
  6410. Object.keys(labels).forEach(function (axisId) {
  6411. $$.axis.setLabelText(axisId, labels[axisId]);
  6412. });
  6413. $$.axis.updateLabels();
  6414. }
  6415. // TODO: return some values?
  6416. };
  6417. c3_chart_fn.axis.max = function (max) {
  6418. var $$ = this.internal, config = $$.config;
  6419. if (arguments.length) {
  6420. if (typeof max === 'object') {
  6421. if (isValue(max.x)) { config.axis_x_max = max.x; }
  6422. if (isValue(max.y)) { config.axis_y_max = max.y; }
  6423. if (isValue(max.y2)) { config.axis_y2_max = max.y2; }
  6424. } else {
  6425. config.axis_y_max = config.axis_y2_max = max;
  6426. }
  6427. $$.redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true});
  6428. } else {
  6429. return {
  6430. x: config.axis_x_max,
  6431. y: config.axis_y_max,
  6432. y2: config.axis_y2_max
  6433. };
  6434. }
  6435. };
  6436. c3_chart_fn.axis.min = function (min) {
  6437. var $$ = this.internal, config = $$.config;
  6438. if (arguments.length) {
  6439. if (typeof min === 'object') {
  6440. if (isValue(min.x)) { config.axis_x_min = min.x; }
  6441. if (isValue(min.y)) { config.axis_y_min = min.y; }
  6442. if (isValue(min.y2)) { config.axis_y2_min = min.y2; }
  6443. } else {
  6444. config.axis_y_min = config.axis_y2_min = min;
  6445. }
  6446. $$.redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true});
  6447. } else {
  6448. return {
  6449. x: config.axis_x_min,
  6450. y: config.axis_y_min,
  6451. y2: config.axis_y2_min
  6452. };
  6453. }
  6454. };
  6455. c3_chart_fn.axis.range = function (range) {
  6456. if (arguments.length) {
  6457. if (isDefined(range.max)) { this.axis.max(range.max); }
  6458. if (isDefined(range.min)) { this.axis.min(range.min); }
  6459. } else {
  6460. return {
  6461. max: this.axis.max(),
  6462. min: this.axis.min()
  6463. };
  6464. }
  6465. };
  6466. c3_chart_fn.legend = function () {};
  6467. c3_chart_fn.legend.show = function (targetIds) {
  6468. var $$ = this.internal;
  6469. $$.showLegend($$.mapToTargetIds(targetIds));
  6470. $$.updateAndRedraw({withLegend: true});
  6471. };
  6472. c3_chart_fn.legend.hide = function (targetIds) {
  6473. var $$ = this.internal;
  6474. $$.hideLegend($$.mapToTargetIds(targetIds));
  6475. $$.updateAndRedraw({withLegend: true});
  6476. };
  6477. c3_chart_fn.resize = function (size) {
  6478. var $$ = this.internal, config = $$.config;
  6479. config.size_width = size ? size.width : null;
  6480. config.size_height = size ? size.height : null;
  6481. this.flush();
  6482. };
  6483. c3_chart_fn.flush = function () {
  6484. var $$ = this.internal;
  6485. $$.updateAndRedraw({withLegend: true, withTransition: false, withTransitionForTransform: false});
  6486. };
  6487. c3_chart_fn.destroy = function () {
  6488. var $$ = this.internal;
  6489. window.clearInterval($$.intervalForObserveInserted);
  6490. if ($$.resizeTimeout !== undefined) {
  6491. window.clearTimeout($$.resizeTimeout);
  6492. }
  6493. if (window.detachEvent) {
  6494. window.detachEvent('onresize', $$.resizeFunction);
  6495. } else if (window.removeEventListener) {
  6496. window.removeEventListener('resize', $$.resizeFunction);
  6497. } else {
  6498. var wrapper = window.onresize;
  6499. // check if no one else removed our wrapper and remove our resizeFunction from it
  6500. if (wrapper && wrapper.add && wrapper.remove) {
  6501. wrapper.remove($$.resizeFunction);
  6502. }
  6503. }
  6504. $$.selectChart.classed('c3', false).html("");
  6505. // MEMO: this is needed because the reference of some elements will not be released, then memory leak will happen.
  6506. Object.keys($$).forEach(function (key) {
  6507. $$[key] = null;
  6508. });
  6509. return null;
  6510. };
  6511. c3_chart_fn.tooltip = function () {};
  6512. c3_chart_fn.tooltip.show = function (args) {
  6513. var $$ = this.internal, index, mouse;
  6514. // determine mouse position on the chart
  6515. if (args.mouse) {
  6516. mouse = args.mouse;
  6517. }
  6518. // determine focus data
  6519. if (args.data) {
  6520. if ($$.isMultipleX()) {
  6521. // if multiple xs, target point will be determined by mouse
  6522. mouse = [$$.x(args.data.x), $$.getYScale(args.data.id)(args.data.value)];
  6523. index = null;
  6524. } else {
  6525. // TODO: when tooltip_grouped = false
  6526. index = isValue(args.data.index) ? args.data.index : $$.getIndexByX(args.data.x);
  6527. }
  6528. }
  6529. else if (typeof args.x !== 'undefined') {
  6530. index = $$.getIndexByX(args.x);
  6531. }
  6532. else if (typeof args.index !== 'undefined') {
  6533. index = args.index;
  6534. }
  6535. // emulate mouse events to show
  6536. $$.dispatchEvent('mouseover', index, mouse);
  6537. $$.dispatchEvent('mousemove', index, mouse);
  6538. $$.config.tooltip_onshow.call($$, args.data);
  6539. };
  6540. c3_chart_fn.tooltip.hide = function () {
  6541. // TODO: get target data by checking the state of focus
  6542. this.internal.dispatchEvent('mouseout', 0);
  6543. this.internal.config.tooltip_onhide.call(this);
  6544. };
  6545. // Features:
  6546. // 1. category axis
  6547. // 2. ceil values of translate/x/y to int for half pixel antialiasing
  6548. // 3. multiline tick text
  6549. var tickTextCharSize;
  6550. function c3_axis(d3, params) {
  6551. var scale = d3.scale.linear(), orient = "bottom", innerTickSize = 6, outerTickSize, tickPadding = 3, tickValues = null, tickFormat, tickArguments;
  6552. var tickOffset = 0, tickCulling = true, tickCentered;
  6553. params = params || {};
  6554. outerTickSize = params.withOuterTick ? 6 : 0;
  6555. function axisX(selection, x) {
  6556. selection.attr("transform", function (d) {
  6557. return "translate(" + Math.ceil(x(d) + tickOffset) + ", 0)";
  6558. });
  6559. }
  6560. function axisY(selection, y) {
  6561. selection.attr("transform", function (d) {
  6562. return "translate(0," + Math.ceil(y(d)) + ")";
  6563. });
  6564. }
  6565. function scaleExtent(domain) {
  6566. var start = domain[0], stop = domain[domain.length - 1];
  6567. return start < stop ? [ start, stop ] : [ stop, start ];
  6568. }
  6569. function generateTicks(scale) {
  6570. var i, domain, ticks = [];
  6571. if (scale.ticks) {
  6572. return scale.ticks.apply(scale, tickArguments);
  6573. }
  6574. domain = scale.domain();
  6575. for (i = Math.ceil(domain[0]); i < domain[1]; i++) {
  6576. ticks.push(i);
  6577. }
  6578. if (ticks.length > 0 && ticks[0] > 0) {
  6579. ticks.unshift(ticks[0] - (ticks[1] - ticks[0]));
  6580. }
  6581. return ticks;
  6582. }
  6583. function copyScale() {
  6584. var newScale = scale.copy(), domain;
  6585. if (params.isCategory) {
  6586. domain = scale.domain();
  6587. newScale.domain([domain[0], domain[1] - 1]);
  6588. }
  6589. return newScale;
  6590. }
  6591. function textFormatted(v) {
  6592. var formatted = tickFormat ? tickFormat(v) : v;
  6593. return typeof formatted !== 'undefined' ? formatted : '';
  6594. }
  6595. function getSizeFor1Char(tick) {
  6596. if (tickTextCharSize) {
  6597. return tickTextCharSize;
  6598. }
  6599. var size = {
  6600. h: 11.5,
  6601. w: 5.5
  6602. };
  6603. tick.select('text').text(textFormatted).each(function (d) {
  6604. var box = this.getBoundingClientRect(),
  6605. text = textFormatted(d),
  6606. h = box.height,
  6607. w = text ? (box.width / text.length) : undefined;
  6608. if (h && w) {
  6609. size.h = h;
  6610. size.w = w;
  6611. }
  6612. }).text('');
  6613. tickTextCharSize = size;
  6614. return size;
  6615. }
  6616. function transitionise(selection) {
  6617. return params.withoutTransition ? selection : d3.transition(selection);
  6618. }
  6619. function axis(g) {
  6620. g.each(function () {
  6621. var g = axis.g = d3.select(this);
  6622. var scale0 = this.__chart__ || scale, scale1 = this.__chart__ = copyScale();
  6623. var ticks = tickValues ? tickValues : generateTicks(scale1),
  6624. tick = g.selectAll(".tick").data(ticks, scale1),
  6625. tickEnter = tick.enter().insert("g", ".domain").attr("class", "tick").style("opacity", 1e-6),
  6626. // MEMO: No exit transition. The reason is this transition affects max tick width calculation because old tick will be included in the ticks.
  6627. tickExit = tick.exit().remove(),
  6628. tickUpdate = transitionise(tick).style("opacity", 1),
  6629. tickTransform, tickX, tickY;
  6630. var range = scale.rangeExtent ? scale.rangeExtent() : scaleExtent(scale.range()),
  6631. path = g.selectAll(".domain").data([ 0 ]),
  6632. pathUpdate = (path.enter().append("path").attr("class", "domain"), transitionise(path));
  6633. tickEnter.append("line");
  6634. tickEnter.append("text");
  6635. var lineEnter = tickEnter.select("line"),
  6636. lineUpdate = tickUpdate.select("line"),
  6637. textEnter = tickEnter.select("text"),
  6638. textUpdate = tickUpdate.select("text");
  6639. if (params.isCategory) {
  6640. tickOffset = Math.ceil((scale1(1) - scale1(0)) / 2);
  6641. tickX = tickCentered ? 0 : tickOffset;
  6642. tickY = tickCentered ? tickOffset : 0;
  6643. } else {
  6644. tickOffset = tickX = 0;
  6645. }
  6646. var text, tspan, sizeFor1Char = getSizeFor1Char(g.select('.tick')), counts = [];
  6647. var tickLength = Math.max(innerTickSize, 0) + tickPadding,
  6648. isVertical = orient === 'left' || orient === 'right';
  6649. // this should be called only when category axis
  6650. function splitTickText(d, maxWidth) {
  6651. var tickText = textFormatted(d),
  6652. subtext, spaceIndex, textWidth, splitted = [];
  6653. if (Object.prototype.toString.call(tickText) === "[object Array]") {
  6654. return tickText;
  6655. }
  6656. if (!maxWidth || maxWidth <= 0) {
  6657. maxWidth = isVertical ? 95 : params.isCategory ? (Math.ceil(scale1(ticks[1]) - scale1(ticks[0])) - 12) : 110;
  6658. }
  6659. function split(splitted, text) {
  6660. spaceIndex = undefined;
  6661. for (var i = 1; i < text.length; i++) {
  6662. if (text.charAt(i) === ' ') {
  6663. spaceIndex = i;
  6664. }
  6665. subtext = text.substr(0, i + 1);
  6666. textWidth = sizeFor1Char.w * subtext.length;
  6667. // if text width gets over tick width, split by space index or crrent index
  6668. if (maxWidth < textWidth) {
  6669. return split(
  6670. splitted.concat(text.substr(0, spaceIndex ? spaceIndex : i)),
  6671. text.slice(spaceIndex ? spaceIndex + 1 : i)
  6672. );
  6673. }
  6674. }
  6675. return splitted.concat(text);
  6676. }
  6677. return split(splitted, tickText + "");
  6678. }
  6679. function tspanDy(d, i) {
  6680. var dy = sizeFor1Char.h;
  6681. if (i === 0) {
  6682. if (orient === 'left' || orient === 'right') {
  6683. dy = -((counts[d.index] - 1) * (sizeFor1Char.h / 2) - 3);
  6684. } else {
  6685. dy = ".71em";
  6686. }
  6687. }
  6688. return dy;
  6689. }
  6690. function tickSize(d) {
  6691. var tickPosition = scale(d) + (tickCentered ? 0 : tickOffset);
  6692. return range[0] < tickPosition && tickPosition < range[1] ? innerTickSize : 0;
  6693. }
  6694. text = tick.select("text");
  6695. tspan = text.selectAll('tspan')
  6696. .data(function (d, i) {
  6697. var splitted = params.tickMultiline ? splitTickText(d, params.tickWidth) : [].concat(textFormatted(d));
  6698. counts[i] = splitted.length;
  6699. return splitted.map(function (s) {
  6700. return { index: i, splitted: s };
  6701. });
  6702. });
  6703. tspan.enter().append('tspan');
  6704. tspan.exit().remove();
  6705. tspan.text(function (d) { return d.splitted; });
  6706. var rotate = params.tickTextRotate;
  6707. function textAnchorForText(rotate) {
  6708. if (!rotate) {
  6709. return 'middle';
  6710. }
  6711. return rotate > 0 ? "start" : "end";
  6712. }
  6713. function textTransform(rotate) {
  6714. if (!rotate) {
  6715. return '';
  6716. }
  6717. return "rotate(" + rotate + ")";
  6718. }
  6719. function dxForText(rotate) {
  6720. if (!rotate) {
  6721. return 0;
  6722. }
  6723. return 8 * Math.sin(Math.PI * (rotate / 180));
  6724. }
  6725. function yForText(rotate) {
  6726. if (!rotate) {
  6727. return tickLength;
  6728. }
  6729. return 11.5 - 2.5 * (rotate / 15) * (rotate > 0 ? 1 : -1);
  6730. }
  6731. switch (orient) {
  6732. case "bottom":
  6733. {
  6734. tickTransform = axisX;
  6735. lineEnter.attr("y2", innerTickSize);
  6736. textEnter.attr("y", tickLength);
  6737. lineUpdate.attr("x1", tickX).attr("x2", tickX).attr("y2", tickSize);
  6738. textUpdate.attr("x", 0).attr("y", yForText(rotate))
  6739. .style("text-anchor", textAnchorForText(rotate))
  6740. .attr("transform", textTransform(rotate));
  6741. tspan.attr('x', 0).attr("dy", tspanDy).attr('dx', dxForText(rotate));
  6742. pathUpdate.attr("d", "M" + range[0] + "," + outerTickSize + "V0H" + range[1] + "V" + outerTickSize);
  6743. break;
  6744. }
  6745. case "top":
  6746. {
  6747. // TODO: rotated tick text
  6748. tickTransform = axisX;
  6749. lineEnter.attr("y2", -innerTickSize);
  6750. textEnter.attr("y", -tickLength);
  6751. lineUpdate.attr("x2", 0).attr("y2", -innerTickSize);
  6752. textUpdate.attr("x", 0).attr("y", -tickLength);
  6753. text.style("text-anchor", "middle");
  6754. tspan.attr('x', 0).attr("dy", "0em");
  6755. pathUpdate.attr("d", "M" + range[0] + "," + -outerTickSize + "V0H" + range[1] + "V" + -outerTickSize);
  6756. break;
  6757. }
  6758. case "left":
  6759. {
  6760. tickTransform = axisY;
  6761. lineEnter.attr("x2", -innerTickSize);
  6762. textEnter.attr("x", -tickLength);
  6763. lineUpdate.attr("x2", -innerTickSize).attr("y1", tickY).attr("y2", tickY);
  6764. textUpdate.attr("x", -tickLength).attr("y", tickOffset);
  6765. text.style("text-anchor", "end");
  6766. tspan.attr('x', -tickLength).attr("dy", tspanDy);
  6767. pathUpdate.attr("d", "M" + -outerTickSize + "," + range[0] + "H0V" + range[1] + "H" + -outerTickSize);
  6768. break;
  6769. }
  6770. case "right":
  6771. {
  6772. tickTransform = axisY;
  6773. lineEnter.attr("x2", innerTickSize);
  6774. textEnter.attr("x", tickLength);
  6775. lineUpdate.attr("x2", innerTickSize).attr("y2", 0);
  6776. textUpdate.attr("x", tickLength).attr("y", 0);
  6777. text.style("text-anchor", "start");
  6778. tspan.attr('x', tickLength).attr("dy", tspanDy);
  6779. pathUpdate.attr("d", "M" + outerTickSize + "," + range[0] + "H0V" + range[1] + "H" + outerTickSize);
  6780. break;
  6781. }
  6782. }
  6783. if (scale1.rangeBand) {
  6784. var x = scale1, dx = x.rangeBand() / 2;
  6785. scale0 = scale1 = function (d) {
  6786. return x(d) + dx;
  6787. };
  6788. } else if (scale0.rangeBand) {
  6789. scale0 = scale1;
  6790. } else {
  6791. tickExit.call(tickTransform, scale1);
  6792. }
  6793. tickEnter.call(tickTransform, scale0);
  6794. tickUpdate.call(tickTransform, scale1);
  6795. });
  6796. }
  6797. axis.scale = function (x) {
  6798. if (!arguments.length) { return scale; }
  6799. scale = x;
  6800. return axis;
  6801. };
  6802. axis.orient = function (x) {
  6803. if (!arguments.length) { return orient; }
  6804. orient = x in {top: 1, right: 1, bottom: 1, left: 1} ? x + "" : "bottom";
  6805. return axis;
  6806. };
  6807. axis.tickFormat = function (format) {
  6808. if (!arguments.length) { return tickFormat; }
  6809. tickFormat = format;
  6810. return axis;
  6811. };
  6812. axis.tickCentered = function (isCentered) {
  6813. if (!arguments.length) { return tickCentered; }
  6814. tickCentered = isCentered;
  6815. return axis;
  6816. };
  6817. axis.tickOffset = function () {
  6818. return tickOffset;
  6819. };
  6820. axis.tickInterval = function () {
  6821. var interval, length;
  6822. if (params.isCategory) {
  6823. interval = tickOffset * 2;
  6824. }
  6825. else {
  6826. length = axis.g.select('path.domain').node().getTotalLength() - outerTickSize * 2;
  6827. interval = length / axis.g.selectAll('line').size();
  6828. }
  6829. return interval === Infinity ? 0 : interval;
  6830. };
  6831. axis.ticks = function () {
  6832. if (!arguments.length) { return tickArguments; }
  6833. tickArguments = arguments;
  6834. return axis;
  6835. };
  6836. axis.tickCulling = function (culling) {
  6837. if (!arguments.length) { return tickCulling; }
  6838. tickCulling = culling;
  6839. return axis;
  6840. };
  6841. axis.tickValues = function (x) {
  6842. if (typeof x === 'function') {
  6843. tickValues = function () {
  6844. return x(scale.domain());
  6845. };
  6846. }
  6847. else {
  6848. if (!arguments.length) { return tickValues; }
  6849. tickValues = x;
  6850. }
  6851. return axis;
  6852. };
  6853. return axis;
  6854. }
  6855. c3_chart_internal_fn.isSafari = function () {
  6856. var ua = window.navigator.userAgent;
  6857. return ua.indexOf('Safari') >= 0 && ua.indexOf('Chrome') < 0;
  6858. };
  6859. c3_chart_internal_fn.isChrome = function () {
  6860. var ua = window.navigator.userAgent;
  6861. return ua.indexOf('Chrome') >= 0;
  6862. };
  6863. /* jshint ignore:start */
  6864. // PhantomJS doesn't have support for Function.prototype.bind, which has caused confusion. Use
  6865. // this polyfill to avoid the confusion.
  6866. // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind#Polyfill
  6867. if (!Function.prototype.bind) {
  6868. Function.prototype.bind = function(oThis) {
  6869. if (typeof this !== 'function') {
  6870. // closest thing possible to the ECMAScript 5
  6871. // internal IsCallable function
  6872. throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
  6873. }
  6874. var aArgs = Array.prototype.slice.call(arguments, 1),
  6875. fToBind = this,
  6876. fNOP = function() {},
  6877. fBound = function() {
  6878. return fToBind.apply(this instanceof fNOP ? this : oThis, aArgs.concat(Array.prototype.slice.call(arguments)));
  6879. };
  6880. fNOP.prototype = this.prototype;
  6881. fBound.prototype = new fNOP();
  6882. return fBound;
  6883. };
  6884. }
  6885. //SVGPathSeg API polyfill
  6886. //https://github.com/progers/pathseg
  6887. //
  6888. //This is a drop-in replacement for the SVGPathSeg and SVGPathSegList APIs that were removed from
  6889. //SVG2 (https://lists.w3.org/Archives/Public/www-svg/2015Jun/0044.html), including the latest spec
  6890. //changes which were implemented in Firefox 43 and Chrome 46.
  6891. //Chrome 48 removes these APIs, so this polyfill is required.
  6892. (function() { "use strict";
  6893. if (!("SVGPathSeg" in window)) {
  6894. // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathSeg
  6895. window.SVGPathSeg = function(type, typeAsLetter, owningPathSegList) {
  6896. this.pathSegType = type;
  6897. this.pathSegTypeAsLetter = typeAsLetter;
  6898. this._owningPathSegList = owningPathSegList;
  6899. }
  6900. SVGPathSeg.PATHSEG_UNKNOWN = 0;
  6901. SVGPathSeg.PATHSEG_CLOSEPATH = 1;
  6902. SVGPathSeg.PATHSEG_MOVETO_ABS = 2;
  6903. SVGPathSeg.PATHSEG_MOVETO_REL = 3;
  6904. SVGPathSeg.PATHSEG_LINETO_ABS = 4;
  6905. SVGPathSeg.PATHSEG_LINETO_REL = 5;
  6906. SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS = 6;
  6907. SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL = 7;
  6908. SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS = 8;
  6909. SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL = 9;
  6910. SVGPathSeg.PATHSEG_ARC_ABS = 10;
  6911. SVGPathSeg.PATHSEG_ARC_REL = 11;
  6912. SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS = 12;
  6913. SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL = 13;
  6914. SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS = 14;
  6915. SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL = 15;
  6916. SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS = 16;
  6917. SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL = 17;
  6918. SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS = 18;
  6919. SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL = 19;
  6920. // Notify owning PathSegList on any changes so they can be synchronized back to the path element.
  6921. SVGPathSeg.prototype._segmentChanged = function() {
  6922. if (this._owningPathSegList)
  6923. this._owningPathSegList.segmentChanged(this);
  6924. }
  6925. window.SVGPathSegClosePath = function(owningPathSegList) {
  6926. SVGPathSeg.call(this, SVGPathSeg.PATHSEG_CLOSEPATH, "z", owningPathSegList);
  6927. }
  6928. SVGPathSegClosePath.prototype = Object.create(SVGPathSeg.prototype);
  6929. SVGPathSegClosePath.prototype.toString = function() { return "[object SVGPathSegClosePath]"; }
  6930. SVGPathSegClosePath.prototype._asPathString = function() { return this.pathSegTypeAsLetter; }
  6931. SVGPathSegClosePath.prototype.clone = function() { return new SVGPathSegClosePath(undefined); }
  6932. window.SVGPathSegMovetoAbs = function(owningPathSegList, x, y) {
  6933. SVGPathSeg.call(this, SVGPathSeg.PATHSEG_MOVETO_ABS, "M", owningPathSegList);
  6934. this._x = x;
  6935. this._y = y;
  6936. }
  6937. SVGPathSegMovetoAbs.prototype = Object.create(SVGPathSeg.prototype);
  6938. SVGPathSegMovetoAbs.prototype.toString = function() { return "[object SVGPathSegMovetoAbs]"; }
  6939. SVGPathSegMovetoAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x + " " + this._y; }
  6940. SVGPathSegMovetoAbs.prototype.clone = function() { return new SVGPathSegMovetoAbs(undefined, this._x, this._y); }
  6941. Object.defineProperty(SVGPathSegMovetoAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
  6942. Object.defineProperty(SVGPathSegMovetoAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
  6943. window.SVGPathSegMovetoRel = function(owningPathSegList, x, y) {
  6944. SVGPathSeg.call(this, SVGPathSeg.PATHSEG_MOVETO_REL, "m", owningPathSegList);
  6945. this._x = x;
  6946. this._y = y;
  6947. }
  6948. SVGPathSegMovetoRel.prototype = Object.create(SVGPathSeg.prototype);
  6949. SVGPathSegMovetoRel.prototype.toString = function() { return "[object SVGPathSegMovetoRel]"; }
  6950. SVGPathSegMovetoRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x + " " + this._y; }
  6951. SVGPathSegMovetoRel.prototype.clone = function() { return new SVGPathSegMovetoRel(undefined, this._x, this._y); }
  6952. Object.defineProperty(SVGPathSegMovetoRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
  6953. Object.defineProperty(SVGPathSegMovetoRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
  6954. window.SVGPathSegLinetoAbs = function(owningPathSegList, x, y) {
  6955. SVGPathSeg.call(this, SVGPathSeg.PATHSEG_LINETO_ABS, "L", owningPathSegList);
  6956. this._x = x;
  6957. this._y = y;
  6958. }
  6959. SVGPathSegLinetoAbs.prototype = Object.create(SVGPathSeg.prototype);
  6960. SVGPathSegLinetoAbs.prototype.toString = function() { return "[object SVGPathSegLinetoAbs]"; }
  6961. SVGPathSegLinetoAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x + " " + this._y; }
  6962. SVGPathSegLinetoAbs.prototype.clone = function() { return new SVGPathSegLinetoAbs(undefined, this._x, this._y); }
  6963. Object.defineProperty(SVGPathSegLinetoAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
  6964. Object.defineProperty(SVGPathSegLinetoAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
  6965. window.SVGPathSegLinetoRel = function(owningPathSegList, x, y) {
  6966. SVGPathSeg.call(this, SVGPathSeg.PATHSEG_LINETO_REL, "l", owningPathSegList);
  6967. this._x = x;
  6968. this._y = y;
  6969. }
  6970. SVGPathSegLinetoRel.prototype = Object.create(SVGPathSeg.prototype);
  6971. SVGPathSegLinetoRel.prototype.toString = function() { return "[object SVGPathSegLinetoRel]"; }
  6972. SVGPathSegLinetoRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x + " " + this._y; }
  6973. SVGPathSegLinetoRel.prototype.clone = function() { return new SVGPathSegLinetoRel(undefined, this._x, this._y); }
  6974. Object.defineProperty(SVGPathSegLinetoRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
  6975. Object.defineProperty(SVGPathSegLinetoRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
  6976. window.SVGPathSegCurvetoCubicAbs = function(owningPathSegList, x, y, x1, y1, x2, y2) {
  6977. SVGPathSeg.call(this, SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS, "C", owningPathSegList);
  6978. this._x = x;
  6979. this._y = y;
  6980. this._x1 = x1;
  6981. this._y1 = y1;
  6982. this._x2 = x2;
  6983. this._y2 = y2;
  6984. }
  6985. SVGPathSegCurvetoCubicAbs.prototype = Object.create(SVGPathSeg.prototype);
  6986. SVGPathSegCurvetoCubicAbs.prototype.toString = function() { return "[object SVGPathSegCurvetoCubicAbs]"; }
  6987. SVGPathSegCurvetoCubicAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x1 + " " + this._y1 + " " + this._x2 + " " + this._y2 + " " + this._x + " " + this._y; }
  6988. SVGPathSegCurvetoCubicAbs.prototype.clone = function() { return new SVGPathSegCurvetoCubicAbs(undefined, this._x, this._y, this._x1, this._y1, this._x2, this._y2); }
  6989. Object.defineProperty(SVGPathSegCurvetoCubicAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
  6990. Object.defineProperty(SVGPathSegCurvetoCubicAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
  6991. Object.defineProperty(SVGPathSegCurvetoCubicAbs.prototype, "x1", { get: function() { return this._x1; }, set: function(x1) { this._x1 = x1; this._segmentChanged(); }, enumerable: true });
  6992. Object.defineProperty(SVGPathSegCurvetoCubicAbs.prototype, "y1", { get: function() { return this._y1; }, set: function(y1) { this._y1 = y1; this._segmentChanged(); }, enumerable: true });
  6993. Object.defineProperty(SVGPathSegCurvetoCubicAbs.prototype, "x2", { get: function() { return this._x2; }, set: function(x2) { this._x2 = x2; this._segmentChanged(); }, enumerable: true });
  6994. Object.defineProperty(SVGPathSegCurvetoCubicAbs.prototype, "y2", { get: function() { return this._y2; }, set: function(y2) { this._y2 = y2; this._segmentChanged(); }, enumerable: true });
  6995. window.SVGPathSegCurvetoCubicRel = function(owningPathSegList, x, y, x1, y1, x2, y2) {
  6996. SVGPathSeg.call(this, SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL, "c", owningPathSegList);
  6997. this._x = x;
  6998. this._y = y;
  6999. this._x1 = x1;
  7000. this._y1 = y1;
  7001. this._x2 = x2;
  7002. this._y2 = y2;
  7003. }
  7004. SVGPathSegCurvetoCubicRel.prototype = Object.create(SVGPathSeg.prototype);
  7005. SVGPathSegCurvetoCubicRel.prototype.toString = function() { return "[object SVGPathSegCurvetoCubicRel]"; }
  7006. SVGPathSegCurvetoCubicRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x1 + " " + this._y1 + " " + this._x2 + " " + this._y2 + " " + this._x + " " + this._y; }
  7007. SVGPathSegCurvetoCubicRel.prototype.clone = function() { return new SVGPathSegCurvetoCubicRel(undefined, this._x, this._y, this._x1, this._y1, this._x2, this._y2); }
  7008. Object.defineProperty(SVGPathSegCurvetoCubicRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
  7009. Object.defineProperty(SVGPathSegCurvetoCubicRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
  7010. Object.defineProperty(SVGPathSegCurvetoCubicRel.prototype, "x1", { get: function() { return this._x1; }, set: function(x1) { this._x1 = x1; this._segmentChanged(); }, enumerable: true });
  7011. Object.defineProperty(SVGPathSegCurvetoCubicRel.prototype, "y1", { get: function() { return this._y1; }, set: function(y1) { this._y1 = y1; this._segmentChanged(); }, enumerable: true });
  7012. Object.defineProperty(SVGPathSegCurvetoCubicRel.prototype, "x2", { get: function() { return this._x2; }, set: function(x2) { this._x2 = x2; this._segmentChanged(); }, enumerable: true });
  7013. Object.defineProperty(SVGPathSegCurvetoCubicRel.prototype, "y2", { get: function() { return this._y2; }, set: function(y2) { this._y2 = y2; this._segmentChanged(); }, enumerable: true });
  7014. window.SVGPathSegCurvetoQuadraticAbs = function(owningPathSegList, x, y, x1, y1) {
  7015. SVGPathSeg.call(this, SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS, "Q", owningPathSegList);
  7016. this._x = x;
  7017. this._y = y;
  7018. this._x1 = x1;
  7019. this._y1 = y1;
  7020. }
  7021. SVGPathSegCurvetoQuadraticAbs.prototype = Object.create(SVGPathSeg.prototype);
  7022. SVGPathSegCurvetoQuadraticAbs.prototype.toString = function() { return "[object SVGPathSegCurvetoQuadraticAbs]"; }
  7023. SVGPathSegCurvetoQuadraticAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x1 + " " + this._y1 + " " + this._x + " " + this._y; }
  7024. SVGPathSegCurvetoQuadraticAbs.prototype.clone = function() { return new SVGPathSegCurvetoQuadraticAbs(undefined, this._x, this._y, this._x1, this._y1); }
  7025. Object.defineProperty(SVGPathSegCurvetoQuadraticAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
  7026. Object.defineProperty(SVGPathSegCurvetoQuadraticAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
  7027. Object.defineProperty(SVGPathSegCurvetoQuadraticAbs.prototype, "x1", { get: function() { return this._x1; }, set: function(x1) { this._x1 = x1; this._segmentChanged(); }, enumerable: true });
  7028. Object.defineProperty(SVGPathSegCurvetoQuadraticAbs.prototype, "y1", { get: function() { return this._y1; }, set: function(y1) { this._y1 = y1; this._segmentChanged(); }, enumerable: true });
  7029. window.SVGPathSegCurvetoQuadraticRel = function(owningPathSegList, x, y, x1, y1) {
  7030. SVGPathSeg.call(this, SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL, "q", owningPathSegList);
  7031. this._x = x;
  7032. this._y = y;
  7033. this._x1 = x1;
  7034. this._y1 = y1;
  7035. }
  7036. SVGPathSegCurvetoQuadraticRel.prototype = Object.create(SVGPathSeg.prototype);
  7037. SVGPathSegCurvetoQuadraticRel.prototype.toString = function() { return "[object SVGPathSegCurvetoQuadraticRel]"; }
  7038. SVGPathSegCurvetoQuadraticRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x1 + " " + this._y1 + " " + this._x + " " + this._y; }
  7039. SVGPathSegCurvetoQuadraticRel.prototype.clone = function() { return new SVGPathSegCurvetoQuadraticRel(undefined, this._x, this._y, this._x1, this._y1); }
  7040. Object.defineProperty(SVGPathSegCurvetoQuadraticRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
  7041. Object.defineProperty(SVGPathSegCurvetoQuadraticRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
  7042. Object.defineProperty(SVGPathSegCurvetoQuadraticRel.prototype, "x1", { get: function() { return this._x1; }, set: function(x1) { this._x1 = x1; this._segmentChanged(); }, enumerable: true });
  7043. Object.defineProperty(SVGPathSegCurvetoQuadraticRel.prototype, "y1", { get: function() { return this._y1; }, set: function(y1) { this._y1 = y1; this._segmentChanged(); }, enumerable: true });
  7044. window.SVGPathSegArcAbs = function(owningPathSegList, x, y, r1, r2, angle, largeArcFlag, sweepFlag) {
  7045. SVGPathSeg.call(this, SVGPathSeg.PATHSEG_ARC_ABS, "A", owningPathSegList);
  7046. this._x = x;
  7047. this._y = y;
  7048. this._r1 = r1;
  7049. this._r2 = r2;
  7050. this._angle = angle;
  7051. this._largeArcFlag = largeArcFlag;
  7052. this._sweepFlag = sweepFlag;
  7053. }
  7054. SVGPathSegArcAbs.prototype = Object.create(SVGPathSeg.prototype);
  7055. SVGPathSegArcAbs.prototype.toString = function() { return "[object SVGPathSegArcAbs]"; }
  7056. SVGPathSegArcAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._r1 + " " + this._r2 + " " + this._angle + " " + (this._largeArcFlag ? "1" : "0") + " " + (this._sweepFlag ? "1" : "0") + " " + this._x + " " + this._y; }
  7057. SVGPathSegArcAbs.prototype.clone = function() { return new SVGPathSegArcAbs(undefined, this._x, this._y, this._r1, this._r2, this._angle, this._largeArcFlag, this._sweepFlag); }
  7058. Object.defineProperty(SVGPathSegArcAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
  7059. Object.defineProperty(SVGPathSegArcAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
  7060. Object.defineProperty(SVGPathSegArcAbs.prototype, "r1", { get: function() { return this._r1; }, set: function(r1) { this._r1 = r1; this._segmentChanged(); }, enumerable: true });
  7061. Object.defineProperty(SVGPathSegArcAbs.prototype, "r2", { get: function() { return this._r2; }, set: function(r2) { this._r2 = r2; this._segmentChanged(); }, enumerable: true });
  7062. Object.defineProperty(SVGPathSegArcAbs.prototype, "angle", { get: function() { return this._angle; }, set: function(angle) { this._angle = angle; this._segmentChanged(); }, enumerable: true });
  7063. Object.defineProperty(SVGPathSegArcAbs.prototype, "largeArcFlag", { get: function() { return this._largeArcFlag; }, set: function(largeArcFlag) { this._largeArcFlag = largeArcFlag; this._segmentChanged(); }, enumerable: true });
  7064. Object.defineProperty(SVGPathSegArcAbs.prototype, "sweepFlag", { get: function() { return this._sweepFlag; }, set: function(sweepFlag) { this._sweepFlag = sweepFlag; this._segmentChanged(); }, enumerable: true });
  7065. window.SVGPathSegArcRel = function(owningPathSegList, x, y, r1, r2, angle, largeArcFlag, sweepFlag) {
  7066. SVGPathSeg.call(this, SVGPathSeg.PATHSEG_ARC_REL, "a", owningPathSegList);
  7067. this._x = x;
  7068. this._y = y;
  7069. this._r1 = r1;
  7070. this._r2 = r2;
  7071. this._angle = angle;
  7072. this._largeArcFlag = largeArcFlag;
  7073. this._sweepFlag = sweepFlag;
  7074. }
  7075. SVGPathSegArcRel.prototype = Object.create(SVGPathSeg.prototype);
  7076. SVGPathSegArcRel.prototype.toString = function() { return "[object SVGPathSegArcRel]"; }
  7077. SVGPathSegArcRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._r1 + " " + this._r2 + " " + this._angle + " " + (this._largeArcFlag ? "1" : "0") + " " + (this._sweepFlag ? "1" : "0") + " " + this._x + " " + this._y; }
  7078. SVGPathSegArcRel.prototype.clone = function() { return new SVGPathSegArcRel(undefined, this._x, this._y, this._r1, this._r2, this._angle, this._largeArcFlag, this._sweepFlag); }
  7079. Object.defineProperty(SVGPathSegArcRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
  7080. Object.defineProperty(SVGPathSegArcRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
  7081. Object.defineProperty(SVGPathSegArcRel.prototype, "r1", { get: function() { return this._r1; }, set: function(r1) { this._r1 = r1; this._segmentChanged(); }, enumerable: true });
  7082. Object.defineProperty(SVGPathSegArcRel.prototype, "r2", { get: function() { return this._r2; }, set: function(r2) { this._r2 = r2; this._segmentChanged(); }, enumerable: true });
  7083. Object.defineProperty(SVGPathSegArcRel.prototype, "angle", { get: function() { return this._angle; }, set: function(angle) { this._angle = angle; this._segmentChanged(); }, enumerable: true });
  7084. Object.defineProperty(SVGPathSegArcRel.prototype, "largeArcFlag", { get: function() { return this._largeArcFlag; }, set: function(largeArcFlag) { this._largeArcFlag = largeArcFlag; this._segmentChanged(); }, enumerable: true });
  7085. Object.defineProperty(SVGPathSegArcRel.prototype, "sweepFlag", { get: function() { return this._sweepFlag; }, set: function(sweepFlag) { this._sweepFlag = sweepFlag; this._segmentChanged(); }, enumerable: true });
  7086. window.SVGPathSegLinetoHorizontalAbs = function(owningPathSegList, x) {
  7087. SVGPathSeg.call(this, SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS, "H", owningPathSegList);
  7088. this._x = x;
  7089. }
  7090. SVGPathSegLinetoHorizontalAbs.prototype = Object.create(SVGPathSeg.prototype);
  7091. SVGPathSegLinetoHorizontalAbs.prototype.toString = function() { return "[object SVGPathSegLinetoHorizontalAbs]"; }
  7092. SVGPathSegLinetoHorizontalAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x; }
  7093. SVGPathSegLinetoHorizontalAbs.prototype.clone = function() { return new SVGPathSegLinetoHorizontalAbs(undefined, this._x); }
  7094. Object.defineProperty(SVGPathSegLinetoHorizontalAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
  7095. window.SVGPathSegLinetoHorizontalRel = function(owningPathSegList, x) {
  7096. SVGPathSeg.call(this, SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL, "h", owningPathSegList);
  7097. this._x = x;
  7098. }
  7099. SVGPathSegLinetoHorizontalRel.prototype = Object.create(SVGPathSeg.prototype);
  7100. SVGPathSegLinetoHorizontalRel.prototype.toString = function() { return "[object SVGPathSegLinetoHorizontalRel]"; }
  7101. SVGPathSegLinetoHorizontalRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x; }
  7102. SVGPathSegLinetoHorizontalRel.prototype.clone = function() { return new SVGPathSegLinetoHorizontalRel(undefined, this._x); }
  7103. Object.defineProperty(SVGPathSegLinetoHorizontalRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
  7104. window.SVGPathSegLinetoVerticalAbs = function(owningPathSegList, y) {
  7105. SVGPathSeg.call(this, SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS, "V", owningPathSegList);
  7106. this._y = y;
  7107. }
  7108. SVGPathSegLinetoVerticalAbs.prototype = Object.create(SVGPathSeg.prototype);
  7109. SVGPathSegLinetoVerticalAbs.prototype.toString = function() { return "[object SVGPathSegLinetoVerticalAbs]"; }
  7110. SVGPathSegLinetoVerticalAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._y; }
  7111. SVGPathSegLinetoVerticalAbs.prototype.clone = function() { return new SVGPathSegLinetoVerticalAbs(undefined, this._y); }
  7112. Object.defineProperty(SVGPathSegLinetoVerticalAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
  7113. window.SVGPathSegLinetoVerticalRel = function(owningPathSegList, y) {
  7114. SVGPathSeg.call(this, SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL, "v", owningPathSegList);
  7115. this._y = y;
  7116. }
  7117. SVGPathSegLinetoVerticalRel.prototype = Object.create(SVGPathSeg.prototype);
  7118. SVGPathSegLinetoVerticalRel.prototype.toString = function() { return "[object SVGPathSegLinetoVerticalRel]"; }
  7119. SVGPathSegLinetoVerticalRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._y; }
  7120. SVGPathSegLinetoVerticalRel.prototype.clone = function() { return new SVGPathSegLinetoVerticalRel(undefined, this._y); }
  7121. Object.defineProperty(SVGPathSegLinetoVerticalRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
  7122. window.SVGPathSegCurvetoCubicSmoothAbs = function(owningPathSegList, x, y, x2, y2) {
  7123. SVGPathSeg.call(this, SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS, "S", owningPathSegList);
  7124. this._x = x;
  7125. this._y = y;
  7126. this._x2 = x2;
  7127. this._y2 = y2;
  7128. }
  7129. SVGPathSegCurvetoCubicSmoothAbs.prototype = Object.create(SVGPathSeg.prototype);
  7130. SVGPathSegCurvetoCubicSmoothAbs.prototype.toString = function() { return "[object SVGPathSegCurvetoCubicSmoothAbs]"; }
  7131. SVGPathSegCurvetoCubicSmoothAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x2 + " " + this._y2 + " " + this._x + " " + this._y; }
  7132. SVGPathSegCurvetoCubicSmoothAbs.prototype.clone = function() { return new SVGPathSegCurvetoCubicSmoothAbs(undefined, this._x, this._y, this._x2, this._y2); }
  7133. Object.defineProperty(SVGPathSegCurvetoCubicSmoothAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
  7134. Object.defineProperty(SVGPathSegCurvetoCubicSmoothAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
  7135. Object.defineProperty(SVGPathSegCurvetoCubicSmoothAbs.prototype, "x2", { get: function() { return this._x2; }, set: function(x2) { this._x2 = x2; this._segmentChanged(); }, enumerable: true });
  7136. Object.defineProperty(SVGPathSegCurvetoCubicSmoothAbs.prototype, "y2", { get: function() { return this._y2; }, set: function(y2) { this._y2 = y2; this._segmentChanged(); }, enumerable: true });
  7137. window.SVGPathSegCurvetoCubicSmoothRel = function(owningPathSegList, x, y, x2, y2) {
  7138. SVGPathSeg.call(this, SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL, "s", owningPathSegList);
  7139. this._x = x;
  7140. this._y = y;
  7141. this._x2 = x2;
  7142. this._y2 = y2;
  7143. }
  7144. SVGPathSegCurvetoCubicSmoothRel.prototype = Object.create(SVGPathSeg.prototype);
  7145. SVGPathSegCurvetoCubicSmoothRel.prototype.toString = function() { return "[object SVGPathSegCurvetoCubicSmoothRel]"; }
  7146. SVGPathSegCurvetoCubicSmoothRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x2 + " " + this._y2 + " " + this._x + " " + this._y; }
  7147. SVGPathSegCurvetoCubicSmoothRel.prototype.clone = function() { return new SVGPathSegCurvetoCubicSmoothRel(undefined, this._x, this._y, this._x2, this._y2); }
  7148. Object.defineProperty(SVGPathSegCurvetoCubicSmoothRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
  7149. Object.defineProperty(SVGPathSegCurvetoCubicSmoothRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
  7150. Object.defineProperty(SVGPathSegCurvetoCubicSmoothRel.prototype, "x2", { get: function() { return this._x2; }, set: function(x2) { this._x2 = x2; this._segmentChanged(); }, enumerable: true });
  7151. Object.defineProperty(SVGPathSegCurvetoCubicSmoothRel.prototype, "y2", { get: function() { return this._y2; }, set: function(y2) { this._y2 = y2; this._segmentChanged(); }, enumerable: true });
  7152. window.SVGPathSegCurvetoQuadraticSmoothAbs = function(owningPathSegList, x, y) {
  7153. SVGPathSeg.call(this, SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS, "T", owningPathSegList);
  7154. this._x = x;
  7155. this._y = y;
  7156. }
  7157. SVGPathSegCurvetoQuadraticSmoothAbs.prototype = Object.create(SVGPathSeg.prototype);
  7158. SVGPathSegCurvetoQuadraticSmoothAbs.prototype.toString = function() { return "[object SVGPathSegCurvetoQuadraticSmoothAbs]"; }
  7159. SVGPathSegCurvetoQuadraticSmoothAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x + " " + this._y; }
  7160. SVGPathSegCurvetoQuadraticSmoothAbs.prototype.clone = function() { return new SVGPathSegCurvetoQuadraticSmoothAbs(undefined, this._x, this._y); }
  7161. Object.defineProperty(SVGPathSegCurvetoQuadraticSmoothAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
  7162. Object.defineProperty(SVGPathSegCurvetoQuadraticSmoothAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
  7163. window.SVGPathSegCurvetoQuadraticSmoothRel = function(owningPathSegList, x, y) {
  7164. SVGPathSeg.call(this, SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL, "t", owningPathSegList);
  7165. this._x = x;
  7166. this._y = y;
  7167. }
  7168. SVGPathSegCurvetoQuadraticSmoothRel.prototype = Object.create(SVGPathSeg.prototype);
  7169. SVGPathSegCurvetoQuadraticSmoothRel.prototype.toString = function() { return "[object SVGPathSegCurvetoQuadraticSmoothRel]"; }
  7170. SVGPathSegCurvetoQuadraticSmoothRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x + " " + this._y; }
  7171. SVGPathSegCurvetoQuadraticSmoothRel.prototype.clone = function() { return new SVGPathSegCurvetoQuadraticSmoothRel(undefined, this._x, this._y); }
  7172. Object.defineProperty(SVGPathSegCurvetoQuadraticSmoothRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
  7173. Object.defineProperty(SVGPathSegCurvetoQuadraticSmoothRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
  7174. // Add createSVGPathSeg* functions to SVGPathElement.
  7175. // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathElement.
  7176. SVGPathElement.prototype.createSVGPathSegClosePath = function() { return new SVGPathSegClosePath(undefined); }
  7177. SVGPathElement.prototype.createSVGPathSegMovetoAbs = function(x, y) { return new SVGPathSegMovetoAbs(undefined, x, y); }
  7178. SVGPathElement.prototype.createSVGPathSegMovetoRel = function(x, y) { return new SVGPathSegMovetoRel(undefined, x, y); }
  7179. SVGPathElement.prototype.createSVGPathSegLinetoAbs = function(x, y) { return new SVGPathSegLinetoAbs(undefined, x, y); }
  7180. SVGPathElement.prototype.createSVGPathSegLinetoRel = function(x, y) { return new SVGPathSegLinetoRel(undefined, x, y); }
  7181. SVGPathElement.prototype.createSVGPathSegCurvetoCubicAbs = function(x, y, x1, y1, x2, y2) { return new SVGPathSegCurvetoCubicAbs(undefined, x, y, x1, y1, x2, y2); }
  7182. SVGPathElement.prototype.createSVGPathSegCurvetoCubicRel = function(x, y, x1, y1, x2, y2) { return new SVGPathSegCurvetoCubicRel(undefined, x, y, x1, y1, x2, y2); }
  7183. SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticAbs = function(x, y, x1, y1) { return new SVGPathSegCurvetoQuadraticAbs(undefined, x, y, x1, y1); }
  7184. SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticRel = function(x, y, x1, y1) { return new SVGPathSegCurvetoQuadraticRel(undefined, x, y, x1, y1); }
  7185. SVGPathElement.prototype.createSVGPathSegArcAbs = function(x, y, r1, r2, angle, largeArcFlag, sweepFlag) { return new SVGPathSegArcAbs(undefined, x, y, r1, r2, angle, largeArcFlag, sweepFlag); }
  7186. SVGPathElement.prototype.createSVGPathSegArcRel = function(x, y, r1, r2, angle, largeArcFlag, sweepFlag) { return new SVGPathSegArcRel(undefined, x, y, r1, r2, angle, largeArcFlag, sweepFlag); }
  7187. SVGPathElement.prototype.createSVGPathSegLinetoHorizontalAbs = function(x) { return new SVGPathSegLinetoHorizontalAbs(undefined, x); }
  7188. SVGPathElement.prototype.createSVGPathSegLinetoHorizontalRel = function(x) { return new SVGPathSegLinetoHorizontalRel(undefined, x); }
  7189. SVGPathElement.prototype.createSVGPathSegLinetoVerticalAbs = function(y) { return new SVGPathSegLinetoVerticalAbs(undefined, y); }
  7190. SVGPathElement.prototype.createSVGPathSegLinetoVerticalRel = function(y) { return new SVGPathSegLinetoVerticalRel(undefined, y); }
  7191. SVGPathElement.prototype.createSVGPathSegCurvetoCubicSmoothAbs = function(x, y, x2, y2) { return new SVGPathSegCurvetoCubicSmoothAbs(undefined, x, y, x2, y2); }
  7192. SVGPathElement.prototype.createSVGPathSegCurvetoCubicSmoothRel = function(x, y, x2, y2) { return new SVGPathSegCurvetoCubicSmoothRel(undefined, x, y, x2, y2); }
  7193. SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticSmoothAbs = function(x, y) { return new SVGPathSegCurvetoQuadraticSmoothAbs(undefined, x, y); }
  7194. SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticSmoothRel = function(x, y) { return new SVGPathSegCurvetoQuadraticSmoothRel(undefined, x, y); }
  7195. }
  7196. if (!("SVGPathSegList" in window)) {
  7197. // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathSegList
  7198. window.SVGPathSegList = function(pathElement) {
  7199. this._pathElement = pathElement;
  7200. this._list = this._parsePath(this._pathElement.getAttribute("d"));
  7201. // Use a MutationObserver to catch changes to the path's "d" attribute.
  7202. this._mutationObserverConfig = { "attributes": true, "attributeFilter": ["d"] };
  7203. this._pathElementMutationObserver = new MutationObserver(this._updateListFromPathMutations.bind(this));
  7204. this._pathElementMutationObserver.observe(this._pathElement, this._mutationObserverConfig);
  7205. }
  7206. Object.defineProperty(SVGPathSegList.prototype, "numberOfItems", {
  7207. get: function() {
  7208. this._checkPathSynchronizedToList();
  7209. return this._list.length;
  7210. },
  7211. enumerable: true
  7212. });
  7213. // Add the pathSegList accessors to SVGPathElement.
  7214. // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGAnimatedPathData
  7215. Object.defineProperty(SVGPathElement.prototype, "pathSegList", {
  7216. get: function() {
  7217. if (!this._pathSegList)
  7218. this._pathSegList = new SVGPathSegList(this);
  7219. return this._pathSegList;
  7220. },
  7221. enumerable: true
  7222. });
  7223. // FIXME: The following are not implemented and simply return SVGPathElement.pathSegList.
  7224. Object.defineProperty(SVGPathElement.prototype, "normalizedPathSegList", { get: function() { return this.pathSegList; }, enumerable: true });
  7225. Object.defineProperty(SVGPathElement.prototype, "animatedPathSegList", { get: function() { return this.pathSegList; }, enumerable: true });
  7226. Object.defineProperty(SVGPathElement.prototype, "animatedNormalizedPathSegList", { get: function() { return this.pathSegList; }, enumerable: true });
  7227. // Process any pending mutations to the path element and update the list as needed.
  7228. // This should be the first call of all public functions and is needed because
  7229. // MutationObservers are not synchronous so we can have pending asynchronous mutations.
  7230. SVGPathSegList.prototype._checkPathSynchronizedToList = function() {
  7231. this._updateListFromPathMutations(this._pathElementMutationObserver.takeRecords());
  7232. }
  7233. SVGPathSegList.prototype._updateListFromPathMutations = function(mutationRecords) {
  7234. if (!this._pathElement)
  7235. return;
  7236. var hasPathMutations = false;
  7237. mutationRecords.forEach(function(record) {
  7238. if (record.attributeName == "d")
  7239. hasPathMutations = true;
  7240. });
  7241. if (hasPathMutations)
  7242. this._list = this._parsePath(this._pathElement.getAttribute("d"));
  7243. }
  7244. // Serialize the list and update the path's 'd' attribute.
  7245. SVGPathSegList.prototype._writeListToPath = function() {
  7246. this._pathElementMutationObserver.disconnect();
  7247. this._pathElement.setAttribute("d", SVGPathSegList._pathSegArrayAsString(this._list));
  7248. this._pathElementMutationObserver.observe(this._pathElement, this._mutationObserverConfig);
  7249. }
  7250. // When a path segment changes the list needs to be synchronized back to the path element.
  7251. SVGPathSegList.prototype.segmentChanged = function(pathSeg) {
  7252. this._writeListToPath();
  7253. }
  7254. SVGPathSegList.prototype.clear = function() {
  7255. this._checkPathSynchronizedToList();
  7256. this._list.forEach(function(pathSeg) {
  7257. pathSeg._owningPathSegList = null;
  7258. });
  7259. this._list = [];
  7260. this._writeListToPath();
  7261. }
  7262. SVGPathSegList.prototype.initialize = function(newItem) {
  7263. this._checkPathSynchronizedToList();
  7264. this._list = [newItem];
  7265. newItem._owningPathSegList = this;
  7266. this._writeListToPath();
  7267. return newItem;
  7268. }
  7269. SVGPathSegList.prototype._checkValidIndex = function(index) {
  7270. if (isNaN(index) || index < 0 || index >= this.numberOfItems)
  7271. throw "INDEX_SIZE_ERR";
  7272. }
  7273. SVGPathSegList.prototype.getItem = function(index) {
  7274. this._checkPathSynchronizedToList();
  7275. this._checkValidIndex(index);
  7276. return this._list[index];
  7277. }
  7278. SVGPathSegList.prototype.insertItemBefore = function(newItem, index) {
  7279. this._checkPathSynchronizedToList();
  7280. // Spec: If the index is greater than or equal to numberOfItems, then the new item is appended to the end of the list.
  7281. if (index > this.numberOfItems)
  7282. index = this.numberOfItems;
  7283. if (newItem._owningPathSegList) {
  7284. // SVG2 spec says to make a copy.
  7285. newItem = newItem.clone();
  7286. }
  7287. this._list.splice(index, 0, newItem);
  7288. newItem._owningPathSegList = this;
  7289. this._writeListToPath();
  7290. return newItem;
  7291. }
  7292. SVGPathSegList.prototype.replaceItem = function(newItem, index) {
  7293. this._checkPathSynchronizedToList();
  7294. if (newItem._owningPathSegList) {
  7295. // SVG2 spec says to make a copy.
  7296. newItem = newItem.clone();
  7297. }
  7298. this._checkValidIndex(index);
  7299. this._list[index] = newItem;
  7300. newItem._owningPathSegList = this;
  7301. this._writeListToPath();
  7302. return newItem;
  7303. }
  7304. SVGPathSegList.prototype.removeItem = function(index) {
  7305. this._checkPathSynchronizedToList();
  7306. this._checkValidIndex(index);
  7307. var item = this._list[index];
  7308. this._list.splice(index, 1);
  7309. this._writeListToPath();
  7310. return item;
  7311. }
  7312. SVGPathSegList.prototype.appendItem = function(newItem) {
  7313. this._checkPathSynchronizedToList();
  7314. if (newItem._owningPathSegList) {
  7315. // SVG2 spec says to make a copy.
  7316. newItem = newItem.clone();
  7317. }
  7318. this._list.push(newItem);
  7319. newItem._owningPathSegList = this;
  7320. // TODO: Optimize this to just append to the existing attribute.
  7321. this._writeListToPath();
  7322. return newItem;
  7323. }
  7324. SVGPathSegList._pathSegArrayAsString = function(pathSegArray) {
  7325. var string = "";
  7326. var first = true;
  7327. pathSegArray.forEach(function(pathSeg) {
  7328. if (first) {
  7329. first = false;
  7330. string += pathSeg._asPathString();
  7331. } else {
  7332. string += " " + pathSeg._asPathString();
  7333. }
  7334. });
  7335. return string;
  7336. }
  7337. // This closely follows SVGPathParser::parsePath from Source/core/svg/SVGPathParser.cpp.
  7338. SVGPathSegList.prototype._parsePath = function(string) {
  7339. if (!string || string.length == 0)
  7340. return [];
  7341. var owningPathSegList = this;
  7342. var Builder = function() {
  7343. this.pathSegList = [];
  7344. }
  7345. Builder.prototype.appendSegment = function(pathSeg) {
  7346. this.pathSegList.push(pathSeg);
  7347. }
  7348. var Source = function(string) {
  7349. this._string = string;
  7350. this._currentIndex = 0;
  7351. this._endIndex = this._string.length;
  7352. this._previousCommand = SVGPathSeg.PATHSEG_UNKNOWN;
  7353. this._skipOptionalSpaces();
  7354. }
  7355. Source.prototype._isCurrentSpace = function() {
  7356. var character = this._string[this._currentIndex];
  7357. return character <= " " && (character == " " || character == "\n" || character == "\t" || character == "\r" || character == "\f");
  7358. }
  7359. Source.prototype._skipOptionalSpaces = function() {
  7360. while (this._currentIndex < this._endIndex && this._isCurrentSpace())
  7361. this._currentIndex++;
  7362. return this._currentIndex < this._endIndex;
  7363. }
  7364. Source.prototype._skipOptionalSpacesOrDelimiter = function() {
  7365. if (this._currentIndex < this._endIndex && !this._isCurrentSpace() && this._string.charAt(this._currentIndex) != ",")
  7366. return false;
  7367. if (this._skipOptionalSpaces()) {
  7368. if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) == ",") {
  7369. this._currentIndex++;
  7370. this._skipOptionalSpaces();
  7371. }
  7372. }
  7373. return this._currentIndex < this._endIndex;
  7374. }
  7375. Source.prototype.hasMoreData = function() {
  7376. return this._currentIndex < this._endIndex;
  7377. }
  7378. Source.prototype.peekSegmentType = function() {
  7379. var lookahead = this._string[this._currentIndex];
  7380. return this._pathSegTypeFromChar(lookahead);
  7381. }
  7382. Source.prototype._pathSegTypeFromChar = function(lookahead) {
  7383. switch (lookahead) {
  7384. case "Z":
  7385. case "z":
  7386. return SVGPathSeg.PATHSEG_CLOSEPATH;
  7387. case "M":
  7388. return SVGPathSeg.PATHSEG_MOVETO_ABS;
  7389. case "m":
  7390. return SVGPathSeg.PATHSEG_MOVETO_REL;
  7391. case "L":
  7392. return SVGPathSeg.PATHSEG_LINETO_ABS;
  7393. case "l":
  7394. return SVGPathSeg.PATHSEG_LINETO_REL;
  7395. case "C":
  7396. return SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS;
  7397. case "c":
  7398. return SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL;
  7399. case "Q":
  7400. return SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS;
  7401. case "q":
  7402. return SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL;
  7403. case "A":
  7404. return SVGPathSeg.PATHSEG_ARC_ABS;
  7405. case "a":
  7406. return SVGPathSeg.PATHSEG_ARC_REL;
  7407. case "H":
  7408. return SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS;
  7409. case "h":
  7410. return SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL;
  7411. case "V":
  7412. return SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS;
  7413. case "v":
  7414. return SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL;
  7415. case "S":
  7416. return SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS;
  7417. case "s":
  7418. return SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL;
  7419. case "T":
  7420. return SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS;
  7421. case "t":
  7422. return SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL;
  7423. default:
  7424. return SVGPathSeg.PATHSEG_UNKNOWN;
  7425. }
  7426. }
  7427. Source.prototype._nextCommandHelper = function(lookahead, previousCommand) {
  7428. // Check for remaining coordinates in the current command.
  7429. if ((lookahead == "+" || lookahead == "-" || lookahead == "." || (lookahead >= "0" && lookahead <= "9")) && previousCommand != SVGPathSeg.PATHSEG_CLOSEPATH) {
  7430. if (previousCommand == SVGPathSeg.PATHSEG_MOVETO_ABS)
  7431. return SVGPathSeg.PATHSEG_LINETO_ABS;
  7432. if (previousCommand == SVGPathSeg.PATHSEG_MOVETO_REL)
  7433. return SVGPathSeg.PATHSEG_LINETO_REL;
  7434. return previousCommand;
  7435. }
  7436. return SVGPathSeg.PATHSEG_UNKNOWN;
  7437. }
  7438. Source.prototype.initialCommandIsMoveTo = function() {
  7439. // If the path is empty it is still valid, so return true.
  7440. if (!this.hasMoreData())
  7441. return true;
  7442. var command = this.peekSegmentType();
  7443. // Path must start with moveTo.
  7444. return command == SVGPathSeg.PATHSEG_MOVETO_ABS || command == SVGPathSeg.PATHSEG_MOVETO_REL;
  7445. }
  7446. // Parse a number from an SVG path. This very closely follows genericParseNumber(...) from Source/core/svg/SVGParserUtilities.cpp.
  7447. // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-PathDataBNF
  7448. Source.prototype._parseNumber = function() {
  7449. var exponent = 0;
  7450. var integer = 0;
  7451. var frac = 1;
  7452. var decimal = 0;
  7453. var sign = 1;
  7454. var expsign = 1;
  7455. var startIndex = this._currentIndex;
  7456. this._skipOptionalSpaces();
  7457. // Read the sign.
  7458. if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) == "+")
  7459. this._currentIndex++;
  7460. else if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) == "-") {
  7461. this._currentIndex++;
  7462. sign = -1;
  7463. }
  7464. if (this._currentIndex == this._endIndex || ((this._string.charAt(this._currentIndex) < "0" || this._string.charAt(this._currentIndex) > "9") && this._string.charAt(this._currentIndex) != "."))
  7465. // The first character of a number must be one of [0-9+-.].
  7466. return undefined;
  7467. // Read the integer part, build right-to-left.
  7468. var startIntPartIndex = this._currentIndex;
  7469. while (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) >= "0" && this._string.charAt(this._currentIndex) <= "9")
  7470. this._currentIndex++; // Advance to first non-digit.
  7471. if (this._currentIndex != startIntPartIndex) {
  7472. var scanIntPartIndex = this._currentIndex - 1;
  7473. var multiplier = 1;
  7474. while (scanIntPartIndex >= startIntPartIndex) {
  7475. integer += multiplier * (this._string.charAt(scanIntPartIndex--) - "0");
  7476. multiplier *= 10;
  7477. }
  7478. }
  7479. // Read the decimals.
  7480. if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) == ".") {
  7481. this._currentIndex++;
  7482. // There must be a least one digit following the .
  7483. if (this._currentIndex >= this._endIndex || this._string.charAt(this._currentIndex) < "0" || this._string.charAt(this._currentIndex) > "9")
  7484. return undefined;
  7485. while (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) >= "0" && this._string.charAt(this._currentIndex) <= "9")
  7486. decimal += (this._string.charAt(this._currentIndex++) - "0") * (frac *= 0.1);
  7487. }
  7488. // Read the exponent part.
  7489. if (this._currentIndex != startIndex && this._currentIndex + 1 < this._endIndex && (this._string.charAt(this._currentIndex) == "e" || this._string.charAt(this._currentIndex) == "E") && (this._string.charAt(this._currentIndex + 1) != "x" && this._string.charAt(this._currentIndex + 1) != "m")) {
  7490. this._currentIndex++;
  7491. // Read the sign of the exponent.
  7492. if (this._string.charAt(this._currentIndex) == "+") {
  7493. this._currentIndex++;
  7494. } else if (this._string.charAt(this._currentIndex) == "-") {
  7495. this._currentIndex++;
  7496. expsign = -1;
  7497. }
  7498. // There must be an exponent.
  7499. if (this._currentIndex >= this._endIndex || this._string.charAt(this._currentIndex) < "0" || this._string.charAt(this._currentIndex) > "9")
  7500. return undefined;
  7501. while (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) >= "0" && this._string.charAt(this._currentIndex) <= "9") {
  7502. exponent *= 10;
  7503. exponent += (this._string.charAt(this._currentIndex) - "0");
  7504. this._currentIndex++;
  7505. }
  7506. }
  7507. var number = integer + decimal;
  7508. number *= sign;
  7509. if (exponent)
  7510. number *= Math.pow(10, expsign * exponent);
  7511. if (startIndex == this._currentIndex)
  7512. return undefined;
  7513. this._skipOptionalSpacesOrDelimiter();
  7514. return number;
  7515. }
  7516. Source.prototype._parseArcFlag = function() {
  7517. if (this._currentIndex >= this._endIndex)
  7518. return undefined;
  7519. var flag = false;
  7520. var flagChar = this._string.charAt(this._currentIndex++);
  7521. if (flagChar == "0")
  7522. flag = false;
  7523. else if (flagChar == "1")
  7524. flag = true;
  7525. else
  7526. return undefined;
  7527. this._skipOptionalSpacesOrDelimiter();
  7528. return flag;
  7529. }
  7530. Source.prototype.parseSegment = function() {
  7531. var lookahead = this._string[this._currentIndex];
  7532. var command = this._pathSegTypeFromChar(lookahead);
  7533. if (command == SVGPathSeg.PATHSEG_UNKNOWN) {
  7534. // Possibly an implicit command. Not allowed if this is the first command.
  7535. if (this._previousCommand == SVGPathSeg.PATHSEG_UNKNOWN)
  7536. return null;
  7537. command = this._nextCommandHelper(lookahead, this._previousCommand);
  7538. if (command == SVGPathSeg.PATHSEG_UNKNOWN)
  7539. return null;
  7540. } else {
  7541. this._currentIndex++;
  7542. }
  7543. this._previousCommand = command;
  7544. switch (command) {
  7545. case SVGPathSeg.PATHSEG_MOVETO_REL:
  7546. return new SVGPathSegMovetoRel(owningPathSegList, this._parseNumber(), this._parseNumber());
  7547. case SVGPathSeg.PATHSEG_MOVETO_ABS:
  7548. return new SVGPathSegMovetoAbs(owningPathSegList, this._parseNumber(), this._parseNumber());
  7549. case SVGPathSeg.PATHSEG_LINETO_REL:
  7550. return new SVGPathSegLinetoRel(owningPathSegList, this._parseNumber(), this._parseNumber());
  7551. case SVGPathSeg.PATHSEG_LINETO_ABS:
  7552. return new SVGPathSegLinetoAbs(owningPathSegList, this._parseNumber(), this._parseNumber());
  7553. case SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL:
  7554. return new SVGPathSegLinetoHorizontalRel(owningPathSegList, this._parseNumber());
  7555. case SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS:
  7556. return new SVGPathSegLinetoHorizontalAbs(owningPathSegList, this._parseNumber());
  7557. case SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL:
  7558. return new SVGPathSegLinetoVerticalRel(owningPathSegList, this._parseNumber());
  7559. case SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS:
  7560. return new SVGPathSegLinetoVerticalAbs(owningPathSegList, this._parseNumber());
  7561. case SVGPathSeg.PATHSEG_CLOSEPATH:
  7562. this._skipOptionalSpaces();
  7563. return new SVGPathSegClosePath(owningPathSegList);
  7564. case SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL:
  7565. var points = {x1: this._parseNumber(), y1: this._parseNumber(), x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
  7566. return new SVGPathSegCurvetoCubicRel(owningPathSegList, points.x, points.y, points.x1, points.y1, points.x2, points.y2);
  7567. case SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS:
  7568. var points = {x1: this._parseNumber(), y1: this._parseNumber(), x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
  7569. return new SVGPathSegCurvetoCubicAbs(owningPathSegList, points.x, points.y, points.x1, points.y1, points.x2, points.y2);
  7570. case SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL:
  7571. var points = {x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
  7572. return new SVGPathSegCurvetoCubicSmoothRel(owningPathSegList, points.x, points.y, points.x2, points.y2);
  7573. case SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS:
  7574. var points = {x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
  7575. return new SVGPathSegCurvetoCubicSmoothAbs(owningPathSegList, points.x, points.y, points.x2, points.y2);
  7576. case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL:
  7577. var points = {x1: this._parseNumber(), y1: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
  7578. return new SVGPathSegCurvetoQuadraticRel(owningPathSegList, points.x, points.y, points.x1, points.y1);
  7579. case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS:
  7580. var points = {x1: this._parseNumber(), y1: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
  7581. return new SVGPathSegCurvetoQuadraticAbs(owningPathSegList, points.x, points.y, points.x1, points.y1);
  7582. case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL:
  7583. return new SVGPathSegCurvetoQuadraticSmoothRel(owningPathSegList, this._parseNumber(), this._parseNumber());
  7584. case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS:
  7585. return new SVGPathSegCurvetoQuadraticSmoothAbs(owningPathSegList, this._parseNumber(), this._parseNumber());
  7586. case SVGPathSeg.PATHSEG_ARC_REL:
  7587. var points = {x1: this._parseNumber(), y1: this._parseNumber(), arcAngle: this._parseNumber(), arcLarge: this._parseArcFlag(), arcSweep: this._parseArcFlag(), x: this._parseNumber(), y: this._parseNumber()};
  7588. return new SVGPathSegArcRel(owningPathSegList, points.x, points.y, points.x1, points.y1, points.arcAngle, points.arcLarge, points.arcSweep);
  7589. case SVGPathSeg.PATHSEG_ARC_ABS:
  7590. var points = {x1: this._parseNumber(), y1: this._parseNumber(), arcAngle: this._parseNumber(), arcLarge: this._parseArcFlag(), arcSweep: this._parseArcFlag(), x: this._parseNumber(), y: this._parseNumber()};
  7591. return new SVGPathSegArcAbs(owningPathSegList, points.x, points.y, points.x1, points.y1, points.arcAngle, points.arcLarge, points.arcSweep);
  7592. default:
  7593. throw "Unknown path seg type."
  7594. }
  7595. }
  7596. var builder = new Builder();
  7597. var source = new Source(string);
  7598. if (!source.initialCommandIsMoveTo())
  7599. return [];
  7600. while (source.hasMoreData()) {
  7601. var pathSeg = source.parseSegment();
  7602. if (!pathSeg)
  7603. return [];
  7604. builder.appendSegment(pathSeg);
  7605. }
  7606. return builder.pathSegList;
  7607. }
  7608. }
  7609. }());
  7610. /* jshint ignore:end */
  7611. if (typeof define === 'function' && define.amd) {
  7612. define("c3", ["d3"], function () { return c3; });
  7613. } else if ('undefined' !== typeof exports && 'undefined' !== typeof module) {
  7614. module.exports = c3;
  7615. } else {
  7616. window.c3 = c3;
  7617. }
  7618. })(window);