c3.js 432 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272112731127411275112761127711278112791128011281112821128311284112851128611287112881128911290112911129211293112941129511296112971129811299113001130111302113031130411305113061130711308113091131011311113121131311314113151131611317113181131911320
  1. /* @license C3.js v0.7.20 | (c) C3 Team and other contributors | http://c3js.org/ */
  2. (function (global, factory) {
  3. typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
  4. typeof define === 'function' && define.amd ? define(factory) :
  5. (global = global || self, global.c3 = factory());
  6. }(this, (function () { 'use strict';
  7. function ChartInternal(api) {
  8. var $$ = this;
  9. // Note: This part will be replaced by rollup-plugin-modify
  10. // When bundling esm output. Beware of changing this line.
  11. // TODO: Maybe we should check that the modification by rollup-plugin-modify
  12. // is valid during unit tests.
  13. $$.d3 = window.d3
  14. ? window.d3
  15. : typeof require !== 'undefined'
  16. ? require('d3')
  17. : undefined;
  18. $$.api = api;
  19. $$.config = $$.getDefaultConfig();
  20. $$.data = {};
  21. $$.cache = {};
  22. $$.axes = {};
  23. }
  24. /**
  25. * The Chart class
  26. *
  27. * The methods of this class is the public APIs of the chart object.
  28. */
  29. function Chart(config) {
  30. this.internal = new ChartInternal(this);
  31. this.internal.loadConfig(config);
  32. this.internal.beforeInit(config);
  33. this.internal.init();
  34. this.internal.afterInit(config);
  35. (function bindThis(fn, target, argThis) {
  36. Object.keys(fn).forEach(function (key) {
  37. target[key] = fn[key].bind(argThis);
  38. if (Object.keys(fn[key]).length > 0) {
  39. bindThis(fn[key], target[key], argThis);
  40. }
  41. });
  42. })(Chart.prototype, this, this);
  43. }
  44. var asHalfPixel = function (n) {
  45. return Math.ceil(n) + 0.5;
  46. };
  47. var ceil10 = function (v) {
  48. return Math.ceil(v / 10) * 10;
  49. };
  50. var diffDomain = function (d) {
  51. return d[1] - d[0];
  52. };
  53. var getOption = function (options, key, defaultValue) {
  54. return isDefined(options[key]) ? options[key] : defaultValue;
  55. };
  56. var getPathBox = function (path) {
  57. var box = getBBox(path), items = [path.pathSegList.getItem(0), path.pathSegList.getItem(1)], minX = items[0].x, minY = Math.min(items[0].y, items[1].y);
  58. return { x: minX, y: minY, width: box.width, height: box.height };
  59. };
  60. var getBBox = function (element) {
  61. try {
  62. return element.getBBox();
  63. }
  64. catch (ignore) {
  65. // Firefox will throw an exception if getBBox() is called whereas the
  66. // element is rendered with display:none
  67. // See https://github.com/c3js/c3/issues/2692
  68. // The previous code was using `getBoundingClientRect` which was returning
  69. // everything at 0 in this case so let's reproduce this behavior here.
  70. return { x: 0, y: 0, width: 0, height: 0 };
  71. }
  72. };
  73. var hasValue = function (dict, value) {
  74. var found = false;
  75. Object.keys(dict).forEach(function (key) {
  76. if (dict[key] === value) {
  77. found = true;
  78. }
  79. });
  80. return found;
  81. };
  82. var isArray = function (o) {
  83. return Array.isArray(o);
  84. };
  85. var isDefined = function (v) {
  86. return typeof v !== 'undefined';
  87. };
  88. var isEmpty = function (o) {
  89. return (typeof o === 'undefined' ||
  90. o === null ||
  91. (isString(o) && o.length === 0) ||
  92. (typeof o === 'object' && Object.keys(o).length === 0));
  93. };
  94. var isFunction = function (o) {
  95. return typeof o === 'function';
  96. };
  97. var isNumber = function (o) {
  98. return typeof o === 'number';
  99. };
  100. var isString = function (o) {
  101. return typeof o === 'string';
  102. };
  103. var isUndefined = function (v) {
  104. return typeof v === 'undefined';
  105. };
  106. var isValue = function (v) {
  107. return v || v === 0;
  108. };
  109. var notEmpty = function (o) {
  110. return !isEmpty(o);
  111. };
  112. var sanitise = function (str) {
  113. return typeof str === 'string'
  114. ? str.replace(/</g, '&lt;').replace(/>/g, '&gt;')
  115. : str;
  116. };
  117. var flattenArray = function (arr) {
  118. return Array.isArray(arr) ? [].concat.apply([], arr) : [];
  119. };
  120. /**
  121. * Returns whether the point is within the given box.
  122. *
  123. * @param {Array} point An [x,y] coordinate
  124. * @param {Object} box An object with {x, y, width, height} keys
  125. * @param {Number} sensitivity An offset to ease check on very small boxes
  126. */
  127. var isWithinBox = function (point, box, sensitivity) {
  128. if (sensitivity === void 0) { sensitivity = 0; }
  129. var xStart = box.x - sensitivity;
  130. var xEnd = box.x + box.width + sensitivity;
  131. var yStart = box.y + box.height + sensitivity;
  132. var yEnd = box.y - sensitivity;
  133. return (xStart < point[0] && point[0] < xEnd && yEnd < point[1] && point[1] < yStart);
  134. };
  135. /**
  136. * Returns Internet Explorer version number (or false if no Internet Explorer used).
  137. *
  138. * @param string agent Optional parameter to specify user agent
  139. */
  140. var getIEVersion = function (agent) {
  141. // https://stackoverflow.com/questions/19999388/check-if-user-is-using-ie
  142. if (typeof agent === 'undefined') {
  143. agent = window.navigator.userAgent;
  144. }
  145. var pos = agent.indexOf('MSIE '); // up to IE10
  146. if (pos > 0) {
  147. return parseInt(agent.substring(pos + 5, agent.indexOf('.', pos)), 10);
  148. }
  149. pos = agent.indexOf('Trident/'); // IE11
  150. if (pos > 0) {
  151. pos = agent.indexOf('rv:');
  152. return parseInt(agent.substring(pos + 3, agent.indexOf('.', pos)), 10);
  153. }
  154. return false;
  155. };
  156. /**
  157. * Returns whether the used browser is Internet Explorer.
  158. *
  159. * @param version Optional parameter to specify IE version
  160. */
  161. var isIE = function (version) {
  162. var ver = getIEVersion();
  163. if (typeof version === 'undefined') {
  164. return !!ver;
  165. }
  166. return version === ver;
  167. };
  168. function AxisInternal(component, params) {
  169. var internal = this;
  170. internal.component = component;
  171. internal.params = params || {};
  172. internal.d3 = component.d3;
  173. internal.scale = internal.d3.scaleLinear();
  174. internal.range;
  175. internal.orient = 'bottom';
  176. internal.innerTickSize = 6;
  177. internal.outerTickSize = this.params.withOuterTick ? 6 : 0;
  178. internal.tickPadding = 3;
  179. internal.tickValues = null;
  180. internal.tickFormat;
  181. internal.tickArguments;
  182. internal.tickOffset = 0;
  183. internal.tickCulling = true;
  184. internal.tickCentered;
  185. internal.tickTextCharSize;
  186. internal.tickTextRotate = internal.params.tickTextRotate;
  187. internal.tickLength;
  188. internal.axis = internal.generateAxis();
  189. }
  190. AxisInternal.prototype.axisX = function (selection, x, tickOffset) {
  191. selection.attr('transform', function (d) {
  192. return 'translate(' + Math.ceil(x(d) + tickOffset) + ', 0)';
  193. });
  194. };
  195. AxisInternal.prototype.axisY = function (selection, y) {
  196. selection.attr('transform', function (d) {
  197. return 'translate(0,' + Math.ceil(y(d)) + ')';
  198. });
  199. };
  200. AxisInternal.prototype.scaleExtent = function (domain) {
  201. var start = domain[0], stop = domain[domain.length - 1];
  202. return start < stop ? [start, stop] : [stop, start];
  203. };
  204. AxisInternal.prototype.generateTicks = function (scale) {
  205. var internal = this;
  206. var i, domain, ticks = [];
  207. if (scale.ticks) {
  208. return scale.ticks.apply(scale, internal.tickArguments);
  209. }
  210. domain = scale.domain();
  211. for (i = Math.ceil(domain[0]); i < domain[1]; i++) {
  212. ticks.push(i);
  213. }
  214. if (ticks.length > 0 && ticks[0] > 0) {
  215. ticks.unshift(ticks[0] - (ticks[1] - ticks[0]));
  216. }
  217. return ticks;
  218. };
  219. AxisInternal.prototype.copyScale = function () {
  220. var internal = this;
  221. var newScale = internal.scale.copy(), domain;
  222. if (internal.params.isCategory) {
  223. domain = internal.scale.domain();
  224. newScale.domain([domain[0], domain[1] - 1]);
  225. }
  226. return newScale;
  227. };
  228. AxisInternal.prototype.textFormatted = function (v) {
  229. var internal = this, formatted = internal.tickFormat ? internal.tickFormat(v) : v;
  230. return typeof formatted !== 'undefined' ? formatted : '';
  231. };
  232. AxisInternal.prototype.updateRange = function () {
  233. var internal = this;
  234. internal.range = internal.scale.rangeExtent
  235. ? internal.scale.rangeExtent()
  236. : internal.scaleExtent(internal.scale.range());
  237. return internal.range;
  238. };
  239. AxisInternal.prototype.updateTickTextCharSize = function (tick) {
  240. var internal = this;
  241. if (internal.tickTextCharSize) {
  242. return internal.tickTextCharSize;
  243. }
  244. var size = {
  245. h: 11.5,
  246. w: 5.5
  247. };
  248. tick
  249. .select('text')
  250. .text(function (d) {
  251. return internal.textFormatted(d);
  252. })
  253. .each(function (d) {
  254. var box = getBBox(this), text = internal.textFormatted(d), h = box.height, w = text ? box.width / text.length : undefined;
  255. if (h && w) {
  256. size.h = h;
  257. size.w = w;
  258. }
  259. })
  260. .text('');
  261. internal.tickTextCharSize = size;
  262. return size;
  263. };
  264. AxisInternal.prototype.isVertical = function () {
  265. return this.orient === 'left' || this.orient === 'right';
  266. };
  267. AxisInternal.prototype.tspanData = function (d, i, scale) {
  268. var internal = this;
  269. var splitted = internal.params.tickMultiline
  270. ? internal.splitTickText(d, scale)
  271. : [].concat(internal.textFormatted(d));
  272. if (internal.params.tickMultiline && internal.params.tickMultilineMax > 0) {
  273. splitted = internal.ellipsify(splitted, internal.params.tickMultilineMax);
  274. }
  275. return splitted.map(function (s) {
  276. return { index: i, splitted: s, length: splitted.length };
  277. });
  278. };
  279. AxisInternal.prototype.splitTickText = function (d, scale) {
  280. var internal = this, tickText = internal.textFormatted(d), maxWidth = internal.params.tickWidth, subtext, spaceIndex, textWidth, splitted = [];
  281. if (Object.prototype.toString.call(tickText) === '[object Array]') {
  282. return tickText;
  283. }
  284. if (!maxWidth || maxWidth <= 0) {
  285. maxWidth = internal.isVertical()
  286. ? 95
  287. : internal.params.isCategory
  288. ? Math.ceil(scale(1) - scale(0)) - 12
  289. : 110;
  290. }
  291. function split(splitted, text) {
  292. spaceIndex = undefined;
  293. for (var i = 1; i < text.length; i++) {
  294. if (text.charAt(i) === ' ') {
  295. spaceIndex = i;
  296. }
  297. subtext = text.substr(0, i + 1);
  298. textWidth = internal.tickTextCharSize.w * subtext.length;
  299. // if text width gets over tick width, split by space index or crrent index
  300. if (maxWidth < textWidth) {
  301. return split(splitted.concat(text.substr(0, spaceIndex ? spaceIndex : i)), text.slice(spaceIndex ? spaceIndex + 1 : i));
  302. }
  303. }
  304. return splitted.concat(text);
  305. }
  306. return split(splitted, tickText + '');
  307. };
  308. AxisInternal.prototype.ellipsify = function (splitted, max) {
  309. if (splitted.length <= max) {
  310. return splitted;
  311. }
  312. var ellipsified = splitted.slice(0, max);
  313. var remaining = 3;
  314. for (var i = max - 1; i >= 0; i--) {
  315. var available = ellipsified[i].length;
  316. ellipsified[i] = ellipsified[i]
  317. .substr(0, available - remaining)
  318. .padEnd(available, '.');
  319. remaining -= available;
  320. if (remaining <= 0) {
  321. break;
  322. }
  323. }
  324. return ellipsified;
  325. };
  326. AxisInternal.prototype.updateTickLength = function () {
  327. var internal = this;
  328. internal.tickLength =
  329. Math.max(internal.innerTickSize, 0) + internal.tickPadding;
  330. };
  331. AxisInternal.prototype.lineY2 = function (d) {
  332. var internal = this, tickPosition = internal.scale(d) + (internal.tickCentered ? 0 : internal.tickOffset);
  333. return internal.range[0] < tickPosition && tickPosition < internal.range[1]
  334. ? internal.innerTickSize
  335. : 0;
  336. };
  337. AxisInternal.prototype.textY = function () {
  338. var internal = this, rotate = internal.tickTextRotate;
  339. return rotate
  340. ? 11.5 - 2.5 * (rotate / 15) * (rotate > 0 ? 1 : -1)
  341. : internal.tickLength;
  342. };
  343. AxisInternal.prototype.textTransform = function () {
  344. var internal = this, rotate = internal.tickTextRotate;
  345. return rotate ? 'rotate(' + rotate + ')' : '';
  346. };
  347. AxisInternal.prototype.textTextAnchor = function () {
  348. var internal = this, rotate = internal.tickTextRotate;
  349. return rotate ? (rotate > 0 ? 'start' : 'end') : 'middle';
  350. };
  351. AxisInternal.prototype.tspanDx = function () {
  352. var internal = this, rotate = internal.tickTextRotate;
  353. return rotate ? 8 * Math.sin(Math.PI * (rotate / 180)) : 0;
  354. };
  355. AxisInternal.prototype.tspanDy = function (d, i) {
  356. var internal = this, dy = internal.tickTextCharSize.h;
  357. if (i === 0) {
  358. if (internal.isVertical()) {
  359. dy = -((d.length - 1) * (internal.tickTextCharSize.h / 2) - 3);
  360. }
  361. else {
  362. dy = '.71em';
  363. }
  364. }
  365. return dy;
  366. };
  367. AxisInternal.prototype.generateAxis = function () {
  368. var internal = this, d3 = internal.d3, params = internal.params;
  369. function axis(g, transition) {
  370. var self;
  371. g.each(function () {
  372. var g = (axis.g = d3.select(this));
  373. var scale0 = this.__chart__ || internal.scale, scale1 = (this.__chart__ = internal.copyScale());
  374. var ticksValues = internal.tickValues
  375. ? internal.tickValues
  376. : internal.generateTicks(scale1), ticks = g.selectAll('.tick').data(ticksValues, scale1), tickEnter = ticks
  377. .enter()
  378. .insert('g', '.domain')
  379. .attr('class', 'tick')
  380. .style('opacity', 1e-6),
  381. // MEMO: No exit transition. The reason is this transition affects max tick width calculation because old tick will be included in the ticks.
  382. tickExit = ticks.exit().remove(), tickUpdate = ticks.merge(tickEnter), tickTransform, tickX, tickY;
  383. if (params.isCategory) {
  384. internal.tickOffset = Math.ceil((scale1(1) - scale1(0)) / 2);
  385. tickX = internal.tickCentered ? 0 : internal.tickOffset;
  386. tickY = internal.tickCentered ? internal.tickOffset : 0;
  387. }
  388. else {
  389. internal.tickOffset = tickX = 0;
  390. }
  391. internal.updateRange();
  392. internal.updateTickLength();
  393. internal.updateTickTextCharSize(g.select('.tick'));
  394. var lineUpdate = tickUpdate
  395. .select('line')
  396. .merge(tickEnter.append('line')), textUpdate = tickUpdate.select('text').merge(tickEnter.append('text'));
  397. var tspans = tickUpdate
  398. .selectAll('text')
  399. .selectAll('tspan')
  400. .data(function (d, i) {
  401. return internal.tspanData(d, i, scale1);
  402. }), tspanEnter = tspans.enter().append('tspan'), tspanUpdate = tspanEnter.merge(tspans).text(function (d) {
  403. return d.splitted;
  404. });
  405. tspans.exit().remove();
  406. var path = g.selectAll('.domain').data([0]), pathUpdate = path
  407. .enter()
  408. .append('path')
  409. .merge(path)
  410. .attr('class', 'domain');
  411. // TODO: each attr should be one function and change its behavior by internal.orient, probably
  412. switch (internal.orient) {
  413. case 'bottom': {
  414. tickTransform = internal.axisX;
  415. lineUpdate
  416. .attr('x1', tickX)
  417. .attr('x2', tickX)
  418. .attr('y2', function (d, i) {
  419. return internal.lineY2(d, i);
  420. });
  421. textUpdate
  422. .attr('x', 0)
  423. .attr('y', function (d, i) {
  424. return internal.textY(d, i);
  425. })
  426. .attr('transform', function (d, i) {
  427. return internal.textTransform(d, i);
  428. })
  429. .style('text-anchor', function (d, i) {
  430. return internal.textTextAnchor(d, i);
  431. });
  432. tspanUpdate
  433. .attr('x', 0)
  434. .attr('dy', function (d, i) {
  435. return internal.tspanDy(d, i);
  436. })
  437. .attr('dx', function (d, i) {
  438. return internal.tspanDx(d, i);
  439. });
  440. pathUpdate.attr('d', 'M' +
  441. internal.range[0] +
  442. ',' +
  443. internal.outerTickSize +
  444. 'V0H' +
  445. internal.range[1] +
  446. 'V' +
  447. internal.outerTickSize);
  448. break;
  449. }
  450. case 'top': {
  451. // TODO: rotated tick text
  452. tickTransform = internal.axisX;
  453. lineUpdate
  454. .attr('x1', tickX)
  455. .attr('x2', tickX)
  456. .attr('y2', function (d, i) {
  457. return -1 * internal.lineY2(d, i);
  458. });
  459. textUpdate
  460. .attr('x', 0)
  461. .attr('y', function (d, i) {
  462. return (-1 * internal.textY(d, i) -
  463. (params.isCategory ? 2 : internal.tickLength - 2));
  464. })
  465. .attr('transform', function (d, i) {
  466. return internal.textTransform(d, i);
  467. })
  468. .style('text-anchor', function (d, i) {
  469. return internal.textTextAnchor(d, i);
  470. });
  471. tspanUpdate
  472. .attr('x', 0)
  473. .attr('dy', function (d, i) {
  474. return internal.tspanDy(d, i);
  475. })
  476. .attr('dx', function (d, i) {
  477. return internal.tspanDx(d, i);
  478. });
  479. pathUpdate.attr('d', 'M' +
  480. internal.range[0] +
  481. ',' +
  482. -internal.outerTickSize +
  483. 'V0H' +
  484. internal.range[1] +
  485. 'V' +
  486. -internal.outerTickSize);
  487. break;
  488. }
  489. case 'left': {
  490. tickTransform = internal.axisY;
  491. lineUpdate
  492. .attr('x2', -internal.innerTickSize)
  493. .attr('y1', tickY)
  494. .attr('y2', tickY);
  495. textUpdate
  496. .attr('x', -internal.tickLength)
  497. .attr('y', internal.tickOffset)
  498. .style('text-anchor', 'end');
  499. tspanUpdate
  500. .attr('x', -internal.tickLength)
  501. .attr('dy', function (d, i) {
  502. return internal.tspanDy(d, i);
  503. });
  504. pathUpdate.attr('d', 'M' +
  505. -internal.outerTickSize +
  506. ',' +
  507. internal.range[0] +
  508. 'H0V' +
  509. internal.range[1] +
  510. 'H' +
  511. -internal.outerTickSize);
  512. break;
  513. }
  514. case 'right': {
  515. tickTransform = internal.axisY;
  516. lineUpdate
  517. .attr('x2', internal.innerTickSize)
  518. .attr('y1', tickY)
  519. .attr('y2', tickY);
  520. textUpdate
  521. .attr('x', internal.tickLength)
  522. .attr('y', internal.tickOffset)
  523. .style('text-anchor', 'start');
  524. tspanUpdate.attr('x', internal.tickLength).attr('dy', function (d, i) {
  525. return internal.tspanDy(d, i);
  526. });
  527. pathUpdate.attr('d', 'M' +
  528. internal.outerTickSize +
  529. ',' +
  530. internal.range[0] +
  531. 'H0V' +
  532. internal.range[1] +
  533. 'H' +
  534. internal.outerTickSize);
  535. break;
  536. }
  537. }
  538. if (scale1.rangeBand) {
  539. var x = scale1, dx = x.rangeBand() / 2;
  540. scale0 = scale1 = function (d) {
  541. return x(d) + dx;
  542. };
  543. }
  544. else if (scale0.rangeBand) {
  545. scale0 = scale1;
  546. }
  547. else {
  548. tickExit.call(tickTransform, scale1, internal.tickOffset);
  549. }
  550. tickEnter.call(tickTransform, scale0, internal.tickOffset);
  551. self = (transition ? tickUpdate.transition(transition) : tickUpdate)
  552. .style('opacity', 1)
  553. .call(tickTransform, scale1, internal.tickOffset);
  554. });
  555. return self;
  556. }
  557. axis.scale = function (x) {
  558. if (!arguments.length) {
  559. return internal.scale;
  560. }
  561. internal.scale = x;
  562. return axis;
  563. };
  564. axis.orient = function (x) {
  565. if (!arguments.length) {
  566. return internal.orient;
  567. }
  568. internal.orient =
  569. x in { top: 1, right: 1, bottom: 1, left: 1 } ? x + '' : 'bottom';
  570. return axis;
  571. };
  572. axis.tickFormat = function (format) {
  573. if (!arguments.length) {
  574. return internal.tickFormat;
  575. }
  576. internal.tickFormat = format;
  577. return axis;
  578. };
  579. axis.tickCentered = function (isCentered) {
  580. if (!arguments.length) {
  581. return internal.tickCentered;
  582. }
  583. internal.tickCentered = isCentered;
  584. return axis;
  585. };
  586. axis.tickOffset = function () {
  587. return internal.tickOffset;
  588. };
  589. axis.tickInterval = function () {
  590. var interval, length;
  591. if (params.isCategory) {
  592. interval = internal.tickOffset * 2;
  593. }
  594. else {
  595. length =
  596. axis.g
  597. .select('path.domain')
  598. .node()
  599. .getTotalLength() -
  600. internal.outerTickSize * 2;
  601. interval = length / axis.g.selectAll('line').size();
  602. }
  603. return interval === Infinity ? 0 : interval;
  604. };
  605. axis.ticks = function () {
  606. if (!arguments.length) {
  607. return internal.tickArguments;
  608. }
  609. internal.tickArguments = arguments;
  610. return axis;
  611. };
  612. axis.tickCulling = function (culling) {
  613. if (!arguments.length) {
  614. return internal.tickCulling;
  615. }
  616. internal.tickCulling = culling;
  617. return axis;
  618. };
  619. axis.tickValues = function (x) {
  620. if (typeof x === 'function') {
  621. internal.tickValues = function () {
  622. return x(internal.scale.domain());
  623. };
  624. }
  625. else {
  626. if (!arguments.length) {
  627. return internal.tickValues;
  628. }
  629. internal.tickValues = x;
  630. }
  631. return axis;
  632. };
  633. return axis;
  634. };
  635. var CLASS = {
  636. target: 'c3-target',
  637. chart: 'c3-chart',
  638. chartLine: 'c3-chart-line',
  639. chartLines: 'c3-chart-lines',
  640. chartBar: 'c3-chart-bar',
  641. chartBars: 'c3-chart-bars',
  642. chartText: 'c3-chart-text',
  643. chartTexts: 'c3-chart-texts',
  644. chartArc: 'c3-chart-arc',
  645. chartArcs: 'c3-chart-arcs',
  646. chartArcsTitle: 'c3-chart-arcs-title',
  647. chartArcsBackground: 'c3-chart-arcs-background',
  648. chartArcsGaugeUnit: 'c3-chart-arcs-gauge-unit',
  649. chartArcsGaugeMax: 'c3-chart-arcs-gauge-max',
  650. chartArcsGaugeMin: 'c3-chart-arcs-gauge-min',
  651. selectedCircle: 'c3-selected-circle',
  652. selectedCircles: 'c3-selected-circles',
  653. eventRect: 'c3-event-rect',
  654. eventRects: 'c3-event-rects',
  655. eventRectsSingle: 'c3-event-rects-single',
  656. eventRectsMultiple: 'c3-event-rects-multiple',
  657. zoomRect: 'c3-zoom-rect',
  658. brush: 'c3-brush',
  659. dragZoom: 'c3-drag-zoom',
  660. focused: 'c3-focused',
  661. defocused: 'c3-defocused',
  662. region: 'c3-region',
  663. regions: 'c3-regions',
  664. title: 'c3-title',
  665. tooltipContainer: 'c3-tooltip-container',
  666. tooltip: 'c3-tooltip',
  667. tooltipName: 'c3-tooltip-name',
  668. shape: 'c3-shape',
  669. shapes: 'c3-shapes',
  670. line: 'c3-line',
  671. lines: 'c3-lines',
  672. bar: 'c3-bar',
  673. bars: 'c3-bars',
  674. circle: 'c3-circle',
  675. circles: 'c3-circles',
  676. arc: 'c3-arc',
  677. arcLabelLine: 'c3-arc-label-line',
  678. arcs: 'c3-arcs',
  679. area: 'c3-area',
  680. areas: 'c3-areas',
  681. empty: 'c3-empty',
  682. text: 'c3-text',
  683. texts: 'c3-texts',
  684. gaugeValue: 'c3-gauge-value',
  685. grid: 'c3-grid',
  686. gridLines: 'c3-grid-lines',
  687. xgrid: 'c3-xgrid',
  688. xgrids: 'c3-xgrids',
  689. xgridLine: 'c3-xgrid-line',
  690. xgridLines: 'c3-xgrid-lines',
  691. xgridFocus: 'c3-xgrid-focus',
  692. ygrid: 'c3-ygrid',
  693. ygrids: 'c3-ygrids',
  694. ygridLine: 'c3-ygrid-line',
  695. ygridLines: 'c3-ygrid-lines',
  696. colorScale: 'c3-colorscale',
  697. stanfordElements: 'c3-stanford-elements',
  698. stanfordLine: 'c3-stanford-line',
  699. stanfordLines: 'c3-stanford-lines',
  700. stanfordRegion: 'c3-stanford-region',
  701. stanfordRegions: 'c3-stanford-regions',
  702. stanfordText: 'c3-stanford-text',
  703. stanfordTexts: 'c3-stanford-texts',
  704. axis: 'c3-axis',
  705. axisX: 'c3-axis-x',
  706. axisXLabel: 'c3-axis-x-label',
  707. axisY: 'c3-axis-y',
  708. axisYLabel: 'c3-axis-y-label',
  709. axisY2: 'c3-axis-y2',
  710. axisY2Label: 'c3-axis-y2-label',
  711. legendBackground: 'c3-legend-background',
  712. legendItem: 'c3-legend-item',
  713. legendItemEvent: 'c3-legend-item-event',
  714. legendItemTile: 'c3-legend-item-tile',
  715. legendItemHidden: 'c3-legend-item-hidden',
  716. legendItemFocused: 'c3-legend-item-focused',
  717. dragarea: 'c3-dragarea',
  718. EXPANDED: '_expanded_',
  719. SELECTED: '_selected_',
  720. INCLUDED: '_included_'
  721. };
  722. var AxisClass = /** @class */ (function () {
  723. function AxisClass(owner) {
  724. this.owner = owner;
  725. this.d3 = owner.d3;
  726. this.internal = AxisInternal;
  727. }
  728. return AxisClass;
  729. }());
  730. var Axis = AxisClass;
  731. Axis.prototype.init = function init() {
  732. var $$ = this.owner, config = $$.config, main = $$.main;
  733. $$.axes.x = main
  734. .append('g')
  735. .attr('class', CLASS.axis + ' ' + CLASS.axisX)
  736. .attr('clip-path', config.axis_x_inner ? '' : $$.clipPathForXAxis)
  737. .attr('transform', $$.getTranslate('x'))
  738. .style('visibility', config.axis_x_show ? 'visible' : 'hidden');
  739. $$.axes.x
  740. .append('text')
  741. .attr('class', CLASS.axisXLabel)
  742. .attr('transform', config.axis_rotated ? 'rotate(-90)' : '')
  743. .style('text-anchor', this.textAnchorForXAxisLabel.bind(this));
  744. $$.axes.y = main
  745. .append('g')
  746. .attr('class', CLASS.axis + ' ' + CLASS.axisY)
  747. .attr('clip-path', config.axis_y_inner ? '' : $$.clipPathForYAxis)
  748. .attr('transform', $$.getTranslate('y'))
  749. .style('visibility', config.axis_y_show ? 'visible' : 'hidden');
  750. $$.axes.y
  751. .append('text')
  752. .attr('class', CLASS.axisYLabel)
  753. .attr('transform', config.axis_rotated ? '' : 'rotate(-90)')
  754. .style('text-anchor', this.textAnchorForYAxisLabel.bind(this));
  755. $$.axes.y2 = main
  756. .append('g')
  757. .attr('class', CLASS.axis + ' ' + CLASS.axisY2)
  758. // clip-path?
  759. .attr('transform', $$.getTranslate('y2'))
  760. .style('visibility', config.axis_y2_show ? 'visible' : 'hidden');
  761. $$.axes.y2
  762. .append('text')
  763. .attr('class', CLASS.axisY2Label)
  764. .attr('transform', config.axis_rotated ? '' : 'rotate(-90)')
  765. .style('text-anchor', this.textAnchorForY2AxisLabel.bind(this));
  766. };
  767. Axis.prototype.getXAxis = function getXAxis(scale, orient, tickFormat, tickValues, withOuterTick, withoutTransition, withoutRotateTickText) {
  768. var $$ = this.owner, config = $$.config, axisParams = {
  769. isCategory: $$.isCategorized(),
  770. withOuterTick: withOuterTick,
  771. tickMultiline: config.axis_x_tick_multiline,
  772. tickMultilineMax: config.axis_x_tick_multiline
  773. ? Number(config.axis_x_tick_multilineMax)
  774. : 0,
  775. tickWidth: config.axis_x_tick_width,
  776. tickTextRotate: withoutRotateTickText ? 0 : config.axis_x_tick_rotate,
  777. withoutTransition: withoutTransition
  778. }, axis = new this.internal(this, axisParams).axis.scale(scale).orient(orient);
  779. if ($$.isTimeSeries() && tickValues && typeof tickValues !== 'function') {
  780. tickValues = tickValues.map(function (v) {
  781. return $$.parseDate(v);
  782. });
  783. }
  784. // Set tick
  785. axis.tickFormat(tickFormat).tickValues(tickValues);
  786. if ($$.isCategorized()) {
  787. axis.tickCentered(config.axis_x_tick_centered);
  788. if (isEmpty(config.axis_x_tick_culling)) {
  789. config.axis_x_tick_culling = false;
  790. }
  791. }
  792. return axis;
  793. };
  794. Axis.prototype.updateXAxisTickValues = function updateXAxisTickValues(targets, axis) {
  795. var $$ = this.owner, config = $$.config, tickValues;
  796. if (config.axis_x_tick_fit || config.axis_x_tick_count) {
  797. tickValues = this.generateTickValues($$.mapTargetsToUniqueXs(targets), config.axis_x_tick_count, $$.isTimeSeries());
  798. }
  799. if (axis) {
  800. axis.tickValues(tickValues);
  801. }
  802. else {
  803. $$.xAxis.tickValues(tickValues);
  804. $$.subXAxis.tickValues(tickValues);
  805. }
  806. return tickValues;
  807. };
  808. Axis.prototype.getYAxis = function getYAxis(axisId, scale, orient, tickValues, withOuterTick, withoutTransition, withoutRotateTickText) {
  809. var $$ = this.owner;
  810. var config = $$.config;
  811. var tickFormat = config["axis_" + axisId + "_tick_format"];
  812. if (!tickFormat && $$.isAxisNormalized(axisId)) {
  813. tickFormat = function (x) { return x + "%"; };
  814. }
  815. var axis = new this.internal(this, {
  816. withOuterTick: withOuterTick,
  817. withoutTransition: withoutTransition,
  818. tickTextRotate: withoutRotateTickText ? 0 : config.axis_y_tick_rotate
  819. }).axis
  820. .scale(scale)
  821. .orient(orient);
  822. if (tickFormat) {
  823. axis.tickFormat(tickFormat);
  824. }
  825. if ($$.isTimeSeriesY()) {
  826. axis.ticks(config.axis_y_tick_time_type, config.axis_y_tick_time_interval);
  827. }
  828. else {
  829. axis.tickValues(tickValues);
  830. }
  831. return axis;
  832. };
  833. Axis.prototype.getId = function getId(id) {
  834. var config = this.owner.config;
  835. return id in config.data_axes ? config.data_axes[id] : 'y';
  836. };
  837. Axis.prototype.getXAxisTickFormat = function getXAxisTickFormat() {
  838. // #2251 previously set any negative values to a whole number,
  839. // however both should be truncated according to the users format specification
  840. var $$ = this.owner, config = $$.config;
  841. var format = $$.isTimeSeries()
  842. ? $$.defaultAxisTimeFormat
  843. : $$.isCategorized()
  844. ? $$.categoryName
  845. : function (v) {
  846. return v;
  847. };
  848. if (config.axis_x_tick_format) {
  849. if (isFunction(config.axis_x_tick_format)) {
  850. format = config.axis_x_tick_format;
  851. }
  852. else if ($$.isTimeSeries()) {
  853. format = function (date) {
  854. return date ? $$.axisTimeFormat(config.axis_x_tick_format)(date) : '';
  855. };
  856. }
  857. }
  858. return isFunction(format)
  859. ? function (v) {
  860. return format.call($$, v);
  861. }
  862. : format;
  863. };
  864. Axis.prototype.getTickValues = function getTickValues(tickValues, axis) {
  865. return tickValues ? tickValues : axis ? axis.tickValues() : undefined;
  866. };
  867. Axis.prototype.getXAxisTickValues = function getXAxisTickValues() {
  868. return this.getTickValues(this.owner.config.axis_x_tick_values, this.owner.xAxis);
  869. };
  870. Axis.prototype.getYAxisTickValues = function getYAxisTickValues() {
  871. return this.getTickValues(this.owner.config.axis_y_tick_values, this.owner.yAxis);
  872. };
  873. Axis.prototype.getY2AxisTickValues = function getY2AxisTickValues() {
  874. return this.getTickValues(this.owner.config.axis_y2_tick_values, this.owner.y2Axis);
  875. };
  876. Axis.prototype.getLabelOptionByAxisId = function getLabelOptionByAxisId(axisId) {
  877. var $$ = this.owner, config = $$.config, option;
  878. if (axisId === 'y') {
  879. option = config.axis_y_label;
  880. }
  881. else if (axisId === 'y2') {
  882. option = config.axis_y2_label;
  883. }
  884. else if (axisId === 'x') {
  885. option = config.axis_x_label;
  886. }
  887. return option;
  888. };
  889. Axis.prototype.getLabelText = function getLabelText(axisId) {
  890. var option = this.getLabelOptionByAxisId(axisId);
  891. return isString(option) ? option : option ? option.text : null;
  892. };
  893. Axis.prototype.setLabelText = function setLabelText(axisId, text) {
  894. var $$ = this.owner, config = $$.config, option = this.getLabelOptionByAxisId(axisId);
  895. if (isString(option)) {
  896. if (axisId === 'y') {
  897. config.axis_y_label = text;
  898. }
  899. else if (axisId === 'y2') {
  900. config.axis_y2_label = text;
  901. }
  902. else if (axisId === 'x') {
  903. config.axis_x_label = text;
  904. }
  905. }
  906. else if (option) {
  907. option.text = text;
  908. }
  909. };
  910. Axis.prototype.getLabelPosition = function getLabelPosition(axisId, defaultPosition) {
  911. var option = this.getLabelOptionByAxisId(axisId), position = option && typeof option === 'object' && option.position
  912. ? option.position
  913. : defaultPosition;
  914. return {
  915. isInner: position.indexOf('inner') >= 0,
  916. isOuter: position.indexOf('outer') >= 0,
  917. isLeft: position.indexOf('left') >= 0,
  918. isCenter: position.indexOf('center') >= 0,
  919. isRight: position.indexOf('right') >= 0,
  920. isTop: position.indexOf('top') >= 0,
  921. isMiddle: position.indexOf('middle') >= 0,
  922. isBottom: position.indexOf('bottom') >= 0
  923. };
  924. };
  925. Axis.prototype.getXAxisLabelPosition = function getXAxisLabelPosition() {
  926. return this.getLabelPosition('x', this.owner.config.axis_rotated ? 'inner-top' : 'inner-right');
  927. };
  928. Axis.prototype.getYAxisLabelPosition = function getYAxisLabelPosition() {
  929. return this.getLabelPosition('y', this.owner.config.axis_rotated ? 'inner-right' : 'inner-top');
  930. };
  931. Axis.prototype.getY2AxisLabelPosition = function getY2AxisLabelPosition() {
  932. return this.getLabelPosition('y2', this.owner.config.axis_rotated ? 'inner-right' : 'inner-top');
  933. };
  934. Axis.prototype.getLabelPositionById = function getLabelPositionById(id) {
  935. return id === 'y2'
  936. ? this.getY2AxisLabelPosition()
  937. : id === 'y'
  938. ? this.getYAxisLabelPosition()
  939. : this.getXAxisLabelPosition();
  940. };
  941. Axis.prototype.textForXAxisLabel = function textForXAxisLabel() {
  942. return this.getLabelText('x');
  943. };
  944. Axis.prototype.textForYAxisLabel = function textForYAxisLabel() {
  945. return this.getLabelText('y');
  946. };
  947. Axis.prototype.textForY2AxisLabel = function textForY2AxisLabel() {
  948. return this.getLabelText('y2');
  949. };
  950. Axis.prototype.xForAxisLabel = function xForAxisLabel(forHorizontal, position) {
  951. var $$ = this.owner;
  952. if (forHorizontal) {
  953. return position.isLeft ? 0 : position.isCenter ? $$.width / 2 : $$.width;
  954. }
  955. else {
  956. return position.isBottom
  957. ? -$$.height
  958. : position.isMiddle
  959. ? -$$.height / 2
  960. : 0;
  961. }
  962. };
  963. Axis.prototype.dxForAxisLabel = function dxForAxisLabel(forHorizontal, position) {
  964. if (forHorizontal) {
  965. return position.isLeft ? '0.5em' : position.isRight ? '-0.5em' : '0';
  966. }
  967. else {
  968. return position.isTop ? '-0.5em' : position.isBottom ? '0.5em' : '0';
  969. }
  970. };
  971. Axis.prototype.textAnchorForAxisLabel = function textAnchorForAxisLabel(forHorizontal, position) {
  972. if (forHorizontal) {
  973. return position.isLeft ? 'start' : position.isCenter ? 'middle' : 'end';
  974. }
  975. else {
  976. return position.isBottom ? 'start' : position.isMiddle ? 'middle' : 'end';
  977. }
  978. };
  979. Axis.prototype.xForXAxisLabel = function xForXAxisLabel() {
  980. return this.xForAxisLabel(!this.owner.config.axis_rotated, this.getXAxisLabelPosition());
  981. };
  982. Axis.prototype.xForYAxisLabel = function xForYAxisLabel() {
  983. return this.xForAxisLabel(this.owner.config.axis_rotated, this.getYAxisLabelPosition());
  984. };
  985. Axis.prototype.xForY2AxisLabel = function xForY2AxisLabel() {
  986. return this.xForAxisLabel(this.owner.config.axis_rotated, this.getY2AxisLabelPosition());
  987. };
  988. Axis.prototype.dxForXAxisLabel = function dxForXAxisLabel() {
  989. return this.dxForAxisLabel(!this.owner.config.axis_rotated, this.getXAxisLabelPosition());
  990. };
  991. Axis.prototype.dxForYAxisLabel = function dxForYAxisLabel() {
  992. return this.dxForAxisLabel(this.owner.config.axis_rotated, this.getYAxisLabelPosition());
  993. };
  994. Axis.prototype.dxForY2AxisLabel = function dxForY2AxisLabel() {
  995. return this.dxForAxisLabel(this.owner.config.axis_rotated, this.getY2AxisLabelPosition());
  996. };
  997. Axis.prototype.dyForXAxisLabel = function dyForXAxisLabel() {
  998. var $$ = this.owner, config = $$.config, position = this.getXAxisLabelPosition();
  999. if (config.axis_rotated) {
  1000. return position.isInner
  1001. ? '1.2em'
  1002. : -25 - ($$.config.axis_x_inner ? 0 : this.getMaxTickWidth('x'));
  1003. }
  1004. else {
  1005. return position.isInner ? '-0.5em' : $$.getHorizontalAxisHeight('x') - 10;
  1006. }
  1007. };
  1008. Axis.prototype.dyForYAxisLabel = function dyForYAxisLabel() {
  1009. var $$ = this.owner, position = this.getYAxisLabelPosition();
  1010. if ($$.config.axis_rotated) {
  1011. return position.isInner ? '-0.5em' : '3em';
  1012. }
  1013. else {
  1014. return position.isInner
  1015. ? '1.2em'
  1016. : -10 - ($$.config.axis_y_inner ? 0 : this.getMaxTickWidth('y') + 10);
  1017. }
  1018. };
  1019. Axis.prototype.dyForY2AxisLabel = function dyForY2AxisLabel() {
  1020. var $$ = this.owner, position = this.getY2AxisLabelPosition();
  1021. if ($$.config.axis_rotated) {
  1022. return position.isInner ? '1.2em' : '-2.2em';
  1023. }
  1024. else {
  1025. return position.isInner
  1026. ? '-0.5em'
  1027. : 15 + ($$.config.axis_y2_inner ? 0 : this.getMaxTickWidth('y2') + 15);
  1028. }
  1029. };
  1030. Axis.prototype.textAnchorForXAxisLabel = function textAnchorForXAxisLabel() {
  1031. var $$ = this.owner;
  1032. return this.textAnchorForAxisLabel(!$$.config.axis_rotated, this.getXAxisLabelPosition());
  1033. };
  1034. Axis.prototype.textAnchorForYAxisLabel = function textAnchorForYAxisLabel() {
  1035. var $$ = this.owner;
  1036. return this.textAnchorForAxisLabel($$.config.axis_rotated, this.getYAxisLabelPosition());
  1037. };
  1038. Axis.prototype.textAnchorForY2AxisLabel = function textAnchorForY2AxisLabel() {
  1039. var $$ = this.owner;
  1040. return this.textAnchorForAxisLabel($$.config.axis_rotated, this.getY2AxisLabelPosition());
  1041. };
  1042. Axis.prototype.getMaxTickWidth = function getMaxTickWidth(id, withoutRecompute) {
  1043. var $$ = this.owner, maxWidth = 0, targetsToShow, scale, axis, dummy, svg;
  1044. if (withoutRecompute && $$.currentMaxTickWidths[id]) {
  1045. return $$.currentMaxTickWidths[id];
  1046. }
  1047. if ($$.svg) {
  1048. targetsToShow = $$.filterTargetsToShow($$.data.targets);
  1049. if (id === 'y') {
  1050. scale = $$.y.copy().domain($$.getYDomain(targetsToShow, 'y'));
  1051. axis = this.getYAxis(id, scale, $$.yOrient, $$.yAxisTickValues, false, true, true);
  1052. }
  1053. else if (id === 'y2') {
  1054. scale = $$.y2.copy().domain($$.getYDomain(targetsToShow, 'y2'));
  1055. axis = this.getYAxis(id, scale, $$.y2Orient, $$.y2AxisTickValues, false, true, true);
  1056. }
  1057. else {
  1058. scale = $$.x.copy().domain($$.getXDomain(targetsToShow));
  1059. axis = this.getXAxis(scale, $$.xOrient, $$.xAxisTickFormat, $$.xAxisTickValues, false, true, true);
  1060. this.updateXAxisTickValues(targetsToShow, axis);
  1061. }
  1062. dummy = $$.d3
  1063. .select('body')
  1064. .append('div')
  1065. .classed('c3', true);
  1066. (svg = dummy
  1067. .append('svg')
  1068. .style('visibility', 'hidden')
  1069. .style('position', 'fixed')
  1070. .style('top', 0)
  1071. .style('left', 0)),
  1072. svg
  1073. .append('g')
  1074. .call(axis)
  1075. .each(function () {
  1076. $$.d3
  1077. .select(this)
  1078. .selectAll('text')
  1079. .each(function () {
  1080. var box = getBBox(this);
  1081. if (maxWidth < box.width) {
  1082. maxWidth = box.width;
  1083. }
  1084. });
  1085. dummy.remove();
  1086. });
  1087. }
  1088. $$.currentMaxTickWidths[id] =
  1089. maxWidth <= 0 ? $$.currentMaxTickWidths[id] : maxWidth;
  1090. return $$.currentMaxTickWidths[id];
  1091. };
  1092. Axis.prototype.updateLabels = function updateLabels(withTransition) {
  1093. var $$ = this.owner;
  1094. var axisXLabel = $$.main.select('.' + CLASS.axisX + ' .' + CLASS.axisXLabel), axisYLabel = $$.main.select('.' + CLASS.axisY + ' .' + CLASS.axisYLabel), axisY2Label = $$.main.select('.' + CLASS.axisY2 + ' .' + CLASS.axisY2Label);
  1095. (withTransition ? axisXLabel.transition() : axisXLabel)
  1096. .attr('x', this.xForXAxisLabel.bind(this))
  1097. .attr('dx', this.dxForXAxisLabel.bind(this))
  1098. .attr('dy', this.dyForXAxisLabel.bind(this))
  1099. .text(this.textForXAxisLabel.bind(this));
  1100. (withTransition ? axisYLabel.transition() : axisYLabel)
  1101. .attr('x', this.xForYAxisLabel.bind(this))
  1102. .attr('dx', this.dxForYAxisLabel.bind(this))
  1103. .attr('dy', this.dyForYAxisLabel.bind(this))
  1104. .text(this.textForYAxisLabel.bind(this));
  1105. (withTransition ? axisY2Label.transition() : axisY2Label)
  1106. .attr('x', this.xForY2AxisLabel.bind(this))
  1107. .attr('dx', this.dxForY2AxisLabel.bind(this))
  1108. .attr('dy', this.dyForY2AxisLabel.bind(this))
  1109. .text(this.textForY2AxisLabel.bind(this));
  1110. };
  1111. Axis.prototype.getPadding = function getPadding(padding, key, defaultValue, domainLength) {
  1112. var p = typeof padding === 'number' ? padding : padding[key];
  1113. if (!isValue(p)) {
  1114. return defaultValue;
  1115. }
  1116. if (padding.unit === 'ratio') {
  1117. return padding[key] * domainLength;
  1118. }
  1119. // assume padding is pixels if unit is not specified
  1120. return this.convertPixelsToAxisPadding(p, domainLength);
  1121. };
  1122. Axis.prototype.convertPixelsToAxisPadding = function convertPixelsToAxisPadding(pixels, domainLength) {
  1123. var $$ = this.owner, length = $$.config.axis_rotated ? $$.width : $$.height;
  1124. return domainLength * (pixels / length);
  1125. };
  1126. Axis.prototype.generateTickValues = function generateTickValues(values, tickCount, forTimeSeries) {
  1127. var tickValues = values, targetCount, start, end, count, interval, i, tickValue;
  1128. if (tickCount) {
  1129. targetCount = isFunction(tickCount) ? tickCount() : tickCount;
  1130. // compute ticks according to tickCount
  1131. if (targetCount === 1) {
  1132. tickValues = [values[0]];
  1133. }
  1134. else if (targetCount === 2) {
  1135. tickValues = [values[0], values[values.length - 1]];
  1136. }
  1137. else if (targetCount > 2) {
  1138. count = targetCount - 2;
  1139. start = values[0];
  1140. end = values[values.length - 1];
  1141. interval = (end - start) / (count + 1);
  1142. // re-construct unique values
  1143. tickValues = [start];
  1144. for (i = 0; i < count; i++) {
  1145. tickValue = +start + interval * (i + 1);
  1146. tickValues.push(forTimeSeries ? new Date(tickValue) : tickValue);
  1147. }
  1148. tickValues.push(end);
  1149. }
  1150. }
  1151. if (!forTimeSeries) {
  1152. tickValues = tickValues.sort(function (a, b) {
  1153. return a - b;
  1154. });
  1155. }
  1156. return tickValues;
  1157. };
  1158. Axis.prototype.generateTransitions = function generateTransitions(duration) {
  1159. var $$ = this.owner, axes = $$.axes;
  1160. return {
  1161. axisX: duration ? axes.x.transition().duration(duration) : axes.x,
  1162. axisY: duration ? axes.y.transition().duration(duration) : axes.y,
  1163. axisY2: duration ? axes.y2.transition().duration(duration) : axes.y2,
  1164. axisSubX: duration ? axes.subx.transition().duration(duration) : axes.subx
  1165. };
  1166. };
  1167. Axis.prototype.redraw = function redraw(duration, isHidden) {
  1168. var $$ = this.owner, transition = duration ? $$.d3.transition().duration(duration) : null;
  1169. $$.axes.x.style('opacity', isHidden ? 0 : 1).call($$.xAxis, transition);
  1170. $$.axes.y.style('opacity', isHidden ? 0 : 1).call($$.yAxis, transition);
  1171. $$.axes.y2.style('opacity', isHidden ? 0 : 1).call($$.y2Axis, transition);
  1172. $$.axes.subx.style('opacity', isHidden ? 0 : 1).call($$.subXAxis, transition);
  1173. };
  1174. var c3 = {
  1175. version: '0.7.20',
  1176. chart: {
  1177. fn: Chart.prototype,
  1178. internal: {
  1179. fn: ChartInternal.prototype,
  1180. axis: {
  1181. fn: AxisClass.prototype,
  1182. internal: {
  1183. fn: AxisInternal.prototype
  1184. }
  1185. }
  1186. }
  1187. },
  1188. generate: function (config) {
  1189. return new Chart(config);
  1190. }
  1191. };
  1192. ChartInternal.prototype.beforeInit = function () {
  1193. // can do something
  1194. };
  1195. ChartInternal.prototype.afterInit = function () {
  1196. // can do something
  1197. };
  1198. ChartInternal.prototype.init = function () {
  1199. var $$ = this, config = $$.config;
  1200. $$.initParams();
  1201. if (config.data_url) {
  1202. $$.convertUrlToData(config.data_url, config.data_mimeType, config.data_headers, config.data_keys, $$.initWithData);
  1203. }
  1204. else if (config.data_json) {
  1205. $$.initWithData($$.convertJsonToData(config.data_json, config.data_keys));
  1206. }
  1207. else if (config.data_rows) {
  1208. $$.initWithData($$.convertRowsToData(config.data_rows));
  1209. }
  1210. else if (config.data_columns) {
  1211. $$.initWithData($$.convertColumnsToData(config.data_columns));
  1212. }
  1213. else {
  1214. throw Error('url or json or rows or columns is required.');
  1215. }
  1216. };
  1217. ChartInternal.prototype.initParams = function () {
  1218. var $$ = this, d3 = $$.d3, config = $$.config;
  1219. // MEMO: clipId needs to be unique because it conflicts when multiple charts exist
  1220. $$.clipId = 'c3-' + new Date().valueOf() + '-clip';
  1221. $$.clipIdForXAxis = $$.clipId + '-xaxis';
  1222. $$.clipIdForYAxis = $$.clipId + '-yaxis';
  1223. $$.clipIdForGrid = $$.clipId + '-grid';
  1224. $$.clipIdForSubchart = $$.clipId + '-subchart';
  1225. $$.clipPath = $$.getClipPath($$.clipId);
  1226. $$.clipPathForXAxis = $$.getClipPath($$.clipIdForXAxis);
  1227. $$.clipPathForYAxis = $$.getClipPath($$.clipIdForYAxis);
  1228. $$.clipPathForGrid = $$.getClipPath($$.clipIdForGrid);
  1229. $$.clipPathForSubchart = $$.getClipPath($$.clipIdForSubchart);
  1230. $$.dragStart = null;
  1231. $$.dragging = false;
  1232. $$.flowing = false;
  1233. $$.cancelClick = false;
  1234. $$.mouseover = undefined;
  1235. $$.transiting = false;
  1236. $$.color = $$.generateColor();
  1237. $$.levelColor = $$.generateLevelColor();
  1238. $$.dataTimeParse = (config.data_xLocaltime ? d3.timeParse : d3.utcParse)($$.config.data_xFormat);
  1239. $$.axisTimeFormat = config.axis_x_localtime ? d3.timeFormat : d3.utcFormat;
  1240. $$.defaultAxisTimeFormat = function (date) {
  1241. if (date.getMilliseconds()) {
  1242. return d3.timeFormat('.%L')(date);
  1243. }
  1244. if (date.getSeconds()) {
  1245. return d3.timeFormat(':%S')(date);
  1246. }
  1247. if (date.getMinutes()) {
  1248. return d3.timeFormat('%I:%M')(date);
  1249. }
  1250. if (date.getHours()) {
  1251. return d3.timeFormat('%I %p')(date);
  1252. }
  1253. if (date.getDay() && date.getDate() !== 1) {
  1254. return d3.timeFormat('%-m/%-d')(date);
  1255. }
  1256. if (date.getDate() !== 1) {
  1257. return d3.timeFormat('%-m/%-d')(date);
  1258. }
  1259. if (date.getMonth()) {
  1260. return d3.timeFormat('%-m/%-d')(date);
  1261. }
  1262. return d3.timeFormat('%Y/%-m/%-d')(date);
  1263. };
  1264. $$.hiddenTargetIds = [];
  1265. $$.hiddenLegendIds = [];
  1266. $$.focusedTargetIds = [];
  1267. $$.defocusedTargetIds = [];
  1268. $$.xOrient = config.axis_rotated
  1269. ? config.axis_x_inner
  1270. ? 'right'
  1271. : 'left'
  1272. : config.axis_x_inner
  1273. ? 'top'
  1274. : 'bottom';
  1275. $$.yOrient = config.axis_rotated
  1276. ? config.axis_y_inner
  1277. ? 'top'
  1278. : 'bottom'
  1279. : config.axis_y_inner
  1280. ? 'right'
  1281. : 'left';
  1282. $$.y2Orient = config.axis_rotated
  1283. ? config.axis_y2_inner
  1284. ? 'bottom'
  1285. : 'top'
  1286. : config.axis_y2_inner
  1287. ? 'left'
  1288. : 'right';
  1289. $$.subXOrient = config.axis_rotated ? 'left' : 'bottom';
  1290. $$.isLegendRight = config.legend_position === 'right';
  1291. $$.isLegendInset = config.legend_position === 'inset';
  1292. $$.isLegendTop =
  1293. config.legend_inset_anchor === 'top-left' ||
  1294. config.legend_inset_anchor === 'top-right';
  1295. $$.isLegendLeft =
  1296. config.legend_inset_anchor === 'top-left' ||
  1297. config.legend_inset_anchor === 'bottom-left';
  1298. $$.legendStep = 0;
  1299. $$.legendItemWidth = 0;
  1300. $$.legendItemHeight = 0;
  1301. $$.currentMaxTickWidths = {
  1302. x: 0,
  1303. y: 0,
  1304. y2: 0
  1305. };
  1306. $$.rotated_padding_left = 30;
  1307. $$.rotated_padding_right = config.axis_rotated && !config.axis_x_show ? 0 : 30;
  1308. $$.rotated_padding_top = 5;
  1309. $$.withoutFadeIn = {};
  1310. $$.intervalForObserveInserted = undefined;
  1311. $$.axes.subx = d3.selectAll([]); // needs when excluding subchart.js
  1312. };
  1313. ChartInternal.prototype.initChartElements = function () {
  1314. if (this.initBar) {
  1315. this.initBar();
  1316. }
  1317. if (this.initLine) {
  1318. this.initLine();
  1319. }
  1320. if (this.initArc) {
  1321. this.initArc();
  1322. }
  1323. if (this.initGauge) {
  1324. this.initGauge();
  1325. }
  1326. if (this.initText) {
  1327. this.initText();
  1328. }
  1329. };
  1330. ChartInternal.prototype.initWithData = function (data) {
  1331. var $$ = this, d3 = $$.d3, config = $$.config;
  1332. var defs, main, binding = true;
  1333. $$.axis = new AxisClass($$);
  1334. if (!config.bindto) {
  1335. $$.selectChart = d3.selectAll([]);
  1336. }
  1337. else if (typeof config.bindto.node === 'function') {
  1338. $$.selectChart = config.bindto;
  1339. }
  1340. else {
  1341. $$.selectChart = d3.select(config.bindto);
  1342. }
  1343. if ($$.selectChart.empty()) {
  1344. $$.selectChart = d3
  1345. .select(document.createElement('div'))
  1346. .style('opacity', 0);
  1347. $$.observeInserted($$.selectChart);
  1348. binding = false;
  1349. }
  1350. $$.selectChart.html('').classed('c3', true);
  1351. // Init data as targets
  1352. $$.data.xs = {};
  1353. $$.data.targets = $$.convertDataToTargets(data);
  1354. if (config.data_filter) {
  1355. $$.data.targets = $$.data.targets.filter(config.data_filter);
  1356. }
  1357. // Set targets to hide if needed
  1358. if (config.data_hide) {
  1359. $$.addHiddenTargetIds(config.data_hide === true
  1360. ? $$.mapToIds($$.data.targets)
  1361. : config.data_hide);
  1362. }
  1363. if (config.legend_hide) {
  1364. $$.addHiddenLegendIds(config.legend_hide === true
  1365. ? $$.mapToIds($$.data.targets)
  1366. : config.legend_hide);
  1367. }
  1368. if ($$.isStanfordGraphType()) {
  1369. $$.initStanfordData();
  1370. }
  1371. // Init sizes and scales
  1372. $$.updateSizes();
  1373. $$.updateScales();
  1374. // Set domains for each scale
  1375. $$.x.domain(d3.extent($$.getXDomain($$.data.targets)));
  1376. $$.y.domain($$.getYDomain($$.data.targets, 'y'));
  1377. $$.y2.domain($$.getYDomain($$.data.targets, 'y2'));
  1378. $$.subX.domain($$.x.domain());
  1379. $$.subY.domain($$.y.domain());
  1380. $$.subY2.domain($$.y2.domain());
  1381. // Save original x domain for zoom update
  1382. $$.orgXDomain = $$.x.domain();
  1383. /*-- Basic Elements --*/
  1384. // Define svgs
  1385. $$.svg = $$.selectChart
  1386. .append('svg')
  1387. .style('overflow', 'hidden')
  1388. .on('mouseenter', function () {
  1389. return config.onmouseover.call($$);
  1390. })
  1391. .on('mouseleave', function () {
  1392. return config.onmouseout.call($$);
  1393. });
  1394. if ($$.config.svg_classname) {
  1395. $$.svg.attr('class', $$.config.svg_classname);
  1396. }
  1397. // Define defs
  1398. defs = $$.svg.append('defs');
  1399. $$.clipChart = $$.appendClip(defs, $$.clipId);
  1400. $$.clipXAxis = $$.appendClip(defs, $$.clipIdForXAxis);
  1401. $$.clipYAxis = $$.appendClip(defs, $$.clipIdForYAxis);
  1402. $$.clipGrid = $$.appendClip(defs, $$.clipIdForGrid);
  1403. $$.clipSubchart = $$.appendClip(defs, $$.clipIdForSubchart);
  1404. $$.updateSvgSize();
  1405. // Define regions
  1406. main = $$.main = $$.svg.append('g').attr('transform', $$.getTranslate('main'));
  1407. if ($$.initPie) {
  1408. $$.initPie();
  1409. }
  1410. if ($$.initDragZoom) {
  1411. $$.initDragZoom();
  1412. }
  1413. if (config.subchart_show && $$.initSubchart) {
  1414. $$.initSubchart();
  1415. }
  1416. if ($$.initTooltip) {
  1417. $$.initTooltip();
  1418. }
  1419. if ($$.initLegend) {
  1420. $$.initLegend();
  1421. }
  1422. if ($$.initTitle) {
  1423. $$.initTitle();
  1424. }
  1425. if ($$.initZoom) {
  1426. $$.initZoom();
  1427. }
  1428. if ($$.isStanfordGraphType()) {
  1429. $$.drawColorScale();
  1430. }
  1431. // Update selection based on size and scale
  1432. // TODO: currently this must be called after initLegend because of update of sizes, but it should be done in initSubchart.
  1433. if (config.subchart_show && $$.initSubchartBrush) {
  1434. $$.initSubchartBrush();
  1435. }
  1436. /*-- Main Region --*/
  1437. // text when empty
  1438. main
  1439. .append('text')
  1440. .attr('class', CLASS.text + ' ' + CLASS.empty)
  1441. .attr('text-anchor', 'middle') // horizontal centering of text at x position in all browsers.
  1442. .attr('dominant-baseline', 'middle'); // vertical centering of text at y position in all browsers, except IE.
  1443. // Regions
  1444. $$.initRegion();
  1445. // Grids
  1446. $$.initGrid();
  1447. // Define g for chart area
  1448. main
  1449. .append('g')
  1450. .attr('clip-path', $$.clipPath)
  1451. .attr('class', CLASS.chart);
  1452. // Grid lines
  1453. if (config.grid_lines_front) {
  1454. $$.initGridLines();
  1455. }
  1456. $$.initStanfordElements();
  1457. // Cover whole with rects for events
  1458. $$.initEventRect();
  1459. // Define g for chart
  1460. $$.initChartElements();
  1461. // Add Axis
  1462. $$.axis.init();
  1463. // Set targets
  1464. $$.updateTargets($$.data.targets);
  1465. // Set default extent if defined
  1466. if (config.axis_x_selection) {
  1467. $$.brush.selectionAsValue($$.getDefaultSelection());
  1468. }
  1469. // Draw with targets
  1470. if (binding) {
  1471. $$.updateDimension();
  1472. $$.config.oninit.call($$);
  1473. $$.redraw({
  1474. withTransition: false,
  1475. withTransform: true,
  1476. withUpdateXDomain: true,
  1477. withUpdateOrgXDomain: true,
  1478. withTransitionForAxis: false
  1479. });
  1480. }
  1481. // Bind to resize event
  1482. $$.bindResize();
  1483. // Bind to window focus event
  1484. $$.bindWindowFocus();
  1485. // export element of the chart
  1486. $$.api.element = $$.selectChart.node();
  1487. };
  1488. ChartInternal.prototype.smoothLines = function (el, type) {
  1489. var $$ = this;
  1490. if (type === 'grid') {
  1491. el.each(function () {
  1492. var g = $$.d3.select(this), x1 = g.attr('x1'), x2 = g.attr('x2'), y1 = g.attr('y1'), y2 = g.attr('y2');
  1493. g.attr({
  1494. x1: Math.ceil(x1),
  1495. x2: Math.ceil(x2),
  1496. y1: Math.ceil(y1),
  1497. y2: Math.ceil(y2)
  1498. });
  1499. });
  1500. }
  1501. };
  1502. ChartInternal.prototype.updateSizes = function () {
  1503. var $$ = this, config = $$.config;
  1504. var legendHeight = $$.legend ? $$.getLegendHeight() : 0, legendWidth = $$.legend ? $$.getLegendWidth() : 0, legendHeightForBottom = $$.isLegendRight || $$.isLegendInset ? 0 : legendHeight, hasArc = $$.hasArcType(), xAxisHeight = config.axis_rotated || hasArc ? 0 : $$.getHorizontalAxisHeight('x'), subchartXAxisHeight = config.axis_rotated || hasArc ? 0 : $$.getHorizontalAxisHeight('x', true), subchartHeight = config.subchart_show && !hasArc
  1505. ? config.subchart_size_height + subchartXAxisHeight
  1506. : 0;
  1507. $$.currentWidth = $$.getCurrentWidth();
  1508. $$.currentHeight = $$.getCurrentHeight();
  1509. // for main
  1510. $$.margin = config.axis_rotated
  1511. ? {
  1512. top: $$.getHorizontalAxisHeight('y2') + $$.getCurrentPaddingTop(),
  1513. right: hasArc ? 0 : $$.getCurrentPaddingRight(),
  1514. bottom: $$.getHorizontalAxisHeight('y') +
  1515. legendHeightForBottom +
  1516. $$.getCurrentPaddingBottom(),
  1517. left: subchartHeight + (hasArc ? 0 : $$.getCurrentPaddingLeft())
  1518. }
  1519. : {
  1520. top: 4 + $$.getCurrentPaddingTop(),
  1521. right: hasArc ? 0 : $$.getCurrentPaddingRight(),
  1522. bottom: xAxisHeight +
  1523. subchartHeight +
  1524. legendHeightForBottom +
  1525. $$.getCurrentPaddingBottom(),
  1526. left: hasArc ? 0 : $$.getCurrentPaddingLeft()
  1527. };
  1528. // for subchart
  1529. $$.margin2 = config.axis_rotated
  1530. ? {
  1531. top: $$.margin.top,
  1532. right: NaN,
  1533. bottom: 20 + legendHeightForBottom,
  1534. left: $$.rotated_padding_left
  1535. }
  1536. : {
  1537. top: $$.currentHeight - subchartHeight - legendHeightForBottom,
  1538. right: NaN,
  1539. bottom: subchartXAxisHeight + legendHeightForBottom,
  1540. left: $$.margin.left
  1541. };
  1542. // for legend
  1543. $$.margin3 = {
  1544. top: 0,
  1545. right: NaN,
  1546. bottom: 0,
  1547. left: 0
  1548. };
  1549. if ($$.updateSizeForLegend) {
  1550. $$.updateSizeForLegend(legendHeight, legendWidth);
  1551. }
  1552. $$.width = $$.currentWidth - $$.margin.left - $$.margin.right;
  1553. $$.height = $$.currentHeight - $$.margin.top - $$.margin.bottom;
  1554. if ($$.width < 0) {
  1555. $$.width = 0;
  1556. }
  1557. if ($$.height < 0) {
  1558. $$.height = 0;
  1559. }
  1560. $$.width2 = config.axis_rotated
  1561. ? $$.margin.left - $$.rotated_padding_left - $$.rotated_padding_right
  1562. : $$.width;
  1563. $$.height2 = config.axis_rotated
  1564. ? $$.height
  1565. : $$.currentHeight - $$.margin2.top - $$.margin2.bottom;
  1566. if ($$.width2 < 0) {
  1567. $$.width2 = 0;
  1568. }
  1569. if ($$.height2 < 0) {
  1570. $$.height2 = 0;
  1571. }
  1572. // for arc
  1573. $$.arcWidth = $$.width - ($$.isLegendRight ? legendWidth + 10 : 0);
  1574. $$.arcHeight = $$.height - ($$.isLegendRight ? 0 : 10);
  1575. if ($$.hasType('gauge') && !config.gauge_fullCircle) {
  1576. $$.arcHeight += $$.height - $$.getGaugeLabelHeight();
  1577. }
  1578. if ($$.updateRadius) {
  1579. $$.updateRadius();
  1580. }
  1581. if ($$.isLegendRight && hasArc) {
  1582. $$.margin3.left = $$.arcWidth / 2 + $$.radiusExpanded * 1.1;
  1583. }
  1584. };
  1585. ChartInternal.prototype.updateTargets = function (targets) {
  1586. var $$ = this, config = $$.config;
  1587. /*-- Main --*/
  1588. //-- Text --//
  1589. $$.updateTargetsForText(targets);
  1590. //-- Bar --//
  1591. $$.updateTargetsForBar(targets);
  1592. //-- Line --//
  1593. $$.updateTargetsForLine(targets);
  1594. //-- Arc --//
  1595. if ($$.hasArcType() && $$.updateTargetsForArc) {
  1596. $$.updateTargetsForArc(targets);
  1597. }
  1598. /*-- Sub --*/
  1599. if (config.subchart_show && $$.updateTargetsForSubchart) {
  1600. $$.updateTargetsForSubchart(targets);
  1601. }
  1602. // Fade-in each chart
  1603. $$.showTargets();
  1604. };
  1605. ChartInternal.prototype.showTargets = function () {
  1606. var $$ = this;
  1607. $$.svg
  1608. .selectAll('.' + CLASS.target)
  1609. .filter(function (d) {
  1610. return $$.isTargetToShow(d.id);
  1611. })
  1612. .transition()
  1613. .duration($$.config.transition_duration)
  1614. .style('opacity', 1);
  1615. };
  1616. ChartInternal.prototype.redraw = function (options, transitions) {
  1617. var $$ = this, main = $$.main, d3 = $$.d3, config = $$.config;
  1618. var areaIndices = $$.getShapeIndices($$.isAreaType), barIndices = $$.getShapeIndices($$.isBarType), lineIndices = $$.getShapeIndices($$.isLineType);
  1619. var withY, withSubchart, withTransition, withTransitionForExit, withTransitionForAxis, withTransform, withUpdateXDomain, withUpdateOrgXDomain, withTrimXDomain, withLegend, withEventRect, withDimension, withUpdateXAxis;
  1620. var hideAxis = $$.hasArcType();
  1621. var drawArea, drawBar, drawLine, xForText, yForText;
  1622. var duration, durationForExit, durationForAxis;
  1623. var transitionsToWait, waitForDraw, flow, transition;
  1624. var targetsToShow = $$.filterTargetsToShow($$.data.targets), tickValues, i, intervalForCulling, xDomainForZoom;
  1625. var xv = $$.xv.bind($$), cx, cy;
  1626. options = options || {};
  1627. withY = getOption(options, 'withY', true);
  1628. withSubchart = getOption(options, 'withSubchart', true);
  1629. withTransition = getOption(options, 'withTransition', true);
  1630. withTransform = getOption(options, 'withTransform', false);
  1631. withUpdateXDomain = getOption(options, 'withUpdateXDomain', false);
  1632. withUpdateOrgXDomain = getOption(options, 'withUpdateOrgXDomain', false);
  1633. withTrimXDomain = getOption(options, 'withTrimXDomain', true);
  1634. withUpdateXAxis = getOption(options, 'withUpdateXAxis', withUpdateXDomain);
  1635. withLegend = getOption(options, 'withLegend', false);
  1636. withEventRect = getOption(options, 'withEventRect', true);
  1637. withDimension = getOption(options, 'withDimension', true);
  1638. withTransitionForExit = getOption(options, 'withTransitionForExit', withTransition);
  1639. withTransitionForAxis = getOption(options, 'withTransitionForAxis', withTransition);
  1640. duration = withTransition ? config.transition_duration : 0;
  1641. durationForExit = withTransitionForExit ? duration : 0;
  1642. durationForAxis = withTransitionForAxis ? duration : 0;
  1643. transitions = transitions || $$.axis.generateTransitions(durationForAxis);
  1644. // update legend and transform each g
  1645. if (withLegend && config.legend_show) {
  1646. $$.updateLegend($$.mapToIds($$.data.targets), options, transitions);
  1647. }
  1648. else if (withDimension) {
  1649. // need to update dimension (e.g. axis.y.tick.values) because y tick values should change
  1650. // no need to update axis in it because they will be updated in redraw()
  1651. $$.updateDimension(true);
  1652. }
  1653. // MEMO: needed for grids calculation
  1654. if ($$.isCategorized() && targetsToShow.length === 0) {
  1655. $$.x.domain([0, $$.axes.x.selectAll('.tick').size()]);
  1656. }
  1657. if (targetsToShow.length) {
  1658. $$.updateXDomain(targetsToShow, withUpdateXDomain, withUpdateOrgXDomain, withTrimXDomain);
  1659. if (!config.axis_x_tick_values) {
  1660. tickValues = $$.axis.updateXAxisTickValues(targetsToShow);
  1661. }
  1662. }
  1663. else {
  1664. $$.xAxis.tickValues([]);
  1665. $$.subXAxis.tickValues([]);
  1666. }
  1667. if (config.zoom_rescale && !options.flow) {
  1668. xDomainForZoom = $$.x.orgDomain();
  1669. }
  1670. $$.y.domain($$.getYDomain(targetsToShow, 'y', xDomainForZoom));
  1671. $$.y2.domain($$.getYDomain(targetsToShow, 'y2', xDomainForZoom));
  1672. if (!config.axis_y_tick_values && config.axis_y_tick_count) {
  1673. $$.yAxis.tickValues($$.axis.generateTickValues($$.y.domain(), config.axis_y_tick_count));
  1674. }
  1675. if (!config.axis_y2_tick_values && config.axis_y2_tick_count) {
  1676. $$.y2Axis.tickValues($$.axis.generateTickValues($$.y2.domain(), config.axis_y2_tick_count));
  1677. }
  1678. // axes
  1679. $$.axis.redraw(durationForAxis, hideAxis);
  1680. // Update axis label
  1681. $$.axis.updateLabels(withTransition);
  1682. // show/hide if manual culling needed
  1683. if ((withUpdateXDomain || withUpdateXAxis) && targetsToShow.length) {
  1684. if (config.axis_x_tick_culling && tickValues) {
  1685. for (i = 1; i < tickValues.length; i++) {
  1686. if (tickValues.length / i < config.axis_x_tick_culling_max) {
  1687. intervalForCulling = i;
  1688. break;
  1689. }
  1690. }
  1691. $$.svg.selectAll('.' + CLASS.axisX + ' .tick text').each(function (e) {
  1692. var index = tickValues.indexOf(e);
  1693. if (index >= 0) {
  1694. d3.select(this).style('display', index % intervalForCulling ? 'none' : 'block');
  1695. }
  1696. });
  1697. }
  1698. else {
  1699. $$.svg
  1700. .selectAll('.' + CLASS.axisX + ' .tick text')
  1701. .style('display', 'block');
  1702. }
  1703. }
  1704. // setup drawer - MEMO: these must be called after axis updated
  1705. drawArea = $$.generateDrawArea
  1706. ? $$.generateDrawArea(areaIndices, false)
  1707. : undefined;
  1708. drawBar = $$.generateDrawBar ? $$.generateDrawBar(barIndices) : undefined;
  1709. drawLine = $$.generateDrawLine
  1710. ? $$.generateDrawLine(lineIndices, false)
  1711. : undefined;
  1712. xForText = $$.generateXYForText(areaIndices, barIndices, lineIndices, true);
  1713. yForText = $$.generateXYForText(areaIndices, barIndices, lineIndices, false);
  1714. // update circleY based on updated parameters
  1715. $$.updateCircleY();
  1716. // generate circle x/y functions depending on updated params
  1717. cx = ($$.config.axis_rotated ? $$.circleY : $$.circleX).bind($$);
  1718. cy = ($$.config.axis_rotated ? $$.circleX : $$.circleY).bind($$);
  1719. // Update sub domain
  1720. if (withY) {
  1721. $$.subY.domain($$.getYDomain(targetsToShow, 'y'));
  1722. $$.subY2.domain($$.getYDomain(targetsToShow, 'y2'));
  1723. }
  1724. // xgrid focus
  1725. $$.updateXgridFocus();
  1726. // Data empty label positioning and text.
  1727. main
  1728. .select('text.' + CLASS.text + '.' + CLASS.empty)
  1729. .attr('x', $$.width / 2)
  1730. .attr('y', $$.height / 2)
  1731. .text(config.data_empty_label_text)
  1732. .transition()
  1733. .style('opacity', targetsToShow.length ? 0 : 1);
  1734. // event rect
  1735. if (withEventRect) {
  1736. $$.redrawEventRect();
  1737. }
  1738. // grid
  1739. $$.updateGrid(duration);
  1740. $$.updateStanfordElements(duration);
  1741. // rect for regions
  1742. $$.updateRegion(duration);
  1743. // bars
  1744. $$.updateBar(durationForExit);
  1745. // lines, areas and circles
  1746. $$.updateLine(durationForExit);
  1747. $$.updateArea(durationForExit);
  1748. $$.updateCircle(cx, cy);
  1749. // text
  1750. if ($$.hasDataLabel()) {
  1751. $$.updateText(xForText, yForText, durationForExit);
  1752. }
  1753. // title
  1754. if ($$.redrawTitle) {
  1755. $$.redrawTitle();
  1756. }
  1757. // arc
  1758. if ($$.redrawArc) {
  1759. $$.redrawArc(duration, durationForExit, withTransform);
  1760. }
  1761. // subchart
  1762. if (config.subchart_show && $$.redrawSubchart) {
  1763. $$.redrawSubchart(withSubchart, transitions, duration, durationForExit, areaIndices, barIndices, lineIndices);
  1764. }
  1765. if ($$.isStanfordGraphType()) {
  1766. $$.drawColorScale();
  1767. }
  1768. // circles for select
  1769. main
  1770. .selectAll('.' + CLASS.selectedCircles)
  1771. .filter($$.isBarType.bind($$))
  1772. .selectAll('circle')
  1773. .remove();
  1774. if (options.flow) {
  1775. flow = $$.generateFlow({
  1776. targets: targetsToShow,
  1777. flow: options.flow,
  1778. duration: options.flow.duration,
  1779. drawBar: drawBar,
  1780. drawLine: drawLine,
  1781. drawArea: drawArea,
  1782. cx: cx,
  1783. cy: cy,
  1784. xv: xv,
  1785. xForText: xForText,
  1786. yForText: yForText
  1787. });
  1788. }
  1789. if (duration && $$.isTabVisible()) {
  1790. // Only use transition if tab visible. See #938.
  1791. // transition should be derived from one transition
  1792. transition = d3.transition().duration(duration);
  1793. transitionsToWait = [];
  1794. [
  1795. $$.redrawBar(drawBar, true, transition),
  1796. $$.redrawLine(drawLine, true, transition),
  1797. $$.redrawArea(drawArea, true, transition),
  1798. $$.redrawCircle(cx, cy, true, transition),
  1799. $$.redrawText(xForText, yForText, options.flow, true, transition),
  1800. $$.redrawRegion(true, transition),
  1801. $$.redrawGrid(true, transition)
  1802. ].forEach(function (transitions) {
  1803. transitions.forEach(function (transition) {
  1804. transitionsToWait.push(transition);
  1805. });
  1806. });
  1807. // Wait for end of transitions to call flow and onrendered callback
  1808. waitForDraw = $$.generateWait();
  1809. transitionsToWait.forEach(function (t) {
  1810. waitForDraw.add(t);
  1811. });
  1812. waitForDraw(function () {
  1813. if (flow) {
  1814. flow();
  1815. }
  1816. if (config.onrendered) {
  1817. config.onrendered.call($$);
  1818. }
  1819. });
  1820. }
  1821. else {
  1822. $$.redrawBar(drawBar);
  1823. $$.redrawLine(drawLine);
  1824. $$.redrawArea(drawArea);
  1825. $$.redrawCircle(cx, cy);
  1826. $$.redrawText(xForText, yForText, options.flow);
  1827. $$.redrawRegion();
  1828. $$.redrawGrid();
  1829. if (flow) {
  1830. flow();
  1831. }
  1832. if (config.onrendered) {
  1833. config.onrendered.call($$);
  1834. }
  1835. }
  1836. // update fadein condition
  1837. $$.mapToIds($$.data.targets).forEach(function (id) {
  1838. $$.withoutFadeIn[id] = true;
  1839. });
  1840. };
  1841. ChartInternal.prototype.updateAndRedraw = function (options) {
  1842. var $$ = this, config = $$.config, transitions;
  1843. options = options || {};
  1844. // same with redraw
  1845. options.withTransition = getOption(options, 'withTransition', true);
  1846. options.withTransform = getOption(options, 'withTransform', false);
  1847. options.withLegend = getOption(options, 'withLegend', false);
  1848. // NOT same with redraw
  1849. options.withUpdateXDomain = getOption(options, 'withUpdateXDomain', true);
  1850. options.withUpdateOrgXDomain = getOption(options, 'withUpdateOrgXDomain', true);
  1851. options.withTransitionForExit = false;
  1852. options.withTransitionForTransform = getOption(options, 'withTransitionForTransform', options.withTransition);
  1853. // MEMO: this needs to be called before updateLegend and it means this ALWAYS needs to be called)
  1854. $$.updateSizes();
  1855. // MEMO: called in updateLegend in redraw if withLegend
  1856. if (!(options.withLegend && config.legend_show)) {
  1857. transitions = $$.axis.generateTransitions(options.withTransitionForAxis ? config.transition_duration : 0);
  1858. // Update scales
  1859. $$.updateScales();
  1860. $$.updateSvgSize();
  1861. // Update g positions
  1862. $$.transformAll(options.withTransitionForTransform, transitions);
  1863. }
  1864. // Draw with new sizes & scales
  1865. $$.redraw(options, transitions);
  1866. };
  1867. ChartInternal.prototype.redrawWithoutRescale = function () {
  1868. this.redraw({
  1869. withY: false,
  1870. withSubchart: false,
  1871. withEventRect: false,
  1872. withTransitionForAxis: false
  1873. });
  1874. };
  1875. ChartInternal.prototype.isTimeSeries = function () {
  1876. return this.config.axis_x_type === 'timeseries';
  1877. };
  1878. ChartInternal.prototype.isCategorized = function () {
  1879. return this.config.axis_x_type.indexOf('categor') >= 0;
  1880. };
  1881. ChartInternal.prototype.isCustomX = function () {
  1882. var $$ = this, config = $$.config;
  1883. return !$$.isTimeSeries() && (config.data_x || notEmpty(config.data_xs));
  1884. };
  1885. ChartInternal.prototype.isTimeSeriesY = function () {
  1886. return this.config.axis_y_type === 'timeseries';
  1887. };
  1888. ChartInternal.prototype.getTranslate = function (target) {
  1889. var $$ = this, config = $$.config, x, y;
  1890. if (target === 'main') {
  1891. x = asHalfPixel($$.margin.left);
  1892. y = asHalfPixel($$.margin.top);
  1893. }
  1894. else if (target === 'context') {
  1895. x = asHalfPixel($$.margin2.left);
  1896. y = asHalfPixel($$.margin2.top);
  1897. }
  1898. else if (target === 'legend') {
  1899. x = $$.margin3.left;
  1900. y = $$.margin3.top;
  1901. }
  1902. else if (target === 'x') {
  1903. x = 0;
  1904. y = config.axis_rotated ? 0 : $$.height;
  1905. }
  1906. else if (target === 'y') {
  1907. x = 0;
  1908. y = config.axis_rotated ? $$.height : 0;
  1909. }
  1910. else if (target === 'y2') {
  1911. x = config.axis_rotated ? 0 : $$.width;
  1912. y = config.axis_rotated ? 1 : 0;
  1913. }
  1914. else if (target === 'subx') {
  1915. x = 0;
  1916. y = config.axis_rotated ? 0 : $$.height2;
  1917. }
  1918. else if (target === 'arc') {
  1919. x = $$.arcWidth / 2;
  1920. y = $$.arcHeight / 2 - ($$.hasType('gauge') ? 6 : 0); // to prevent wrong display of min and max label
  1921. }
  1922. return 'translate(' + x + ',' + y + ')';
  1923. };
  1924. ChartInternal.prototype.initialOpacity = function (d) {
  1925. return d.value !== null && this.withoutFadeIn[d.id] ? 1 : 0;
  1926. };
  1927. ChartInternal.prototype.initialOpacityForCircle = function (d) {
  1928. return d.value !== null && this.withoutFadeIn[d.id]
  1929. ? this.opacityForCircle(d)
  1930. : 0;
  1931. };
  1932. ChartInternal.prototype.opacityForCircle = function (d) {
  1933. var isPointShouldBeShown = isFunction(this.config.point_show)
  1934. ? this.config.point_show(d)
  1935. : this.config.point_show;
  1936. var opacity = isPointShouldBeShown || this.isStanfordType(d) ? 1 : 0;
  1937. return isValue(d.value) ? (this.isScatterType(d) ? 0.5 : opacity) : 0;
  1938. };
  1939. ChartInternal.prototype.opacityForText = function () {
  1940. return this.hasDataLabel() ? 1 : 0;
  1941. };
  1942. ChartInternal.prototype.xx = function (d) {
  1943. return d ? this.x(d.x) : null;
  1944. };
  1945. ChartInternal.prototype.xvCustom = function (d, xyValue) {
  1946. var $$ = this, value = xyValue ? d[xyValue] : d.value;
  1947. if ($$.isTimeSeries()) {
  1948. value = $$.parseDate(d.value);
  1949. }
  1950. else if ($$.isCategorized() && typeof d.value === 'string') {
  1951. value = $$.config.axis_x_categories.indexOf(d.value);
  1952. }
  1953. return Math.ceil($$.x(value));
  1954. };
  1955. ChartInternal.prototype.yvCustom = function (d, xyValue) {
  1956. var $$ = this, yScale = d.axis && d.axis === 'y2' ? $$.y2 : $$.y, value = xyValue ? d[xyValue] : d.value;
  1957. return Math.ceil(yScale(value));
  1958. };
  1959. ChartInternal.prototype.xv = function (d) {
  1960. var $$ = this, value = d.value;
  1961. if ($$.isTimeSeries()) {
  1962. value = $$.parseDate(d.value);
  1963. }
  1964. else if ($$.isCategorized() && typeof d.value === 'string') {
  1965. value = $$.config.axis_x_categories.indexOf(d.value);
  1966. }
  1967. return Math.ceil($$.x(value));
  1968. };
  1969. ChartInternal.prototype.yv = function (d) {
  1970. var $$ = this, yScale = d.axis && d.axis === 'y2' ? $$.y2 : $$.y;
  1971. return Math.ceil(yScale(d.value));
  1972. };
  1973. ChartInternal.prototype.subxx = function (d) {
  1974. return d ? this.subX(d.x) : null;
  1975. };
  1976. ChartInternal.prototype.transformMain = function (withTransition, transitions) {
  1977. var $$ = this, xAxis, yAxis, y2Axis;
  1978. if (transitions && transitions.axisX) {
  1979. xAxis = transitions.axisX;
  1980. }
  1981. else {
  1982. xAxis = $$.main.select('.' + CLASS.axisX);
  1983. if (withTransition) {
  1984. xAxis = xAxis.transition();
  1985. }
  1986. }
  1987. if (transitions && transitions.axisY) {
  1988. yAxis = transitions.axisY;
  1989. }
  1990. else {
  1991. yAxis = $$.main.select('.' + CLASS.axisY);
  1992. if (withTransition) {
  1993. yAxis = yAxis.transition();
  1994. }
  1995. }
  1996. if (transitions && transitions.axisY2) {
  1997. y2Axis = transitions.axisY2;
  1998. }
  1999. else {
  2000. y2Axis = $$.main.select('.' + CLASS.axisY2);
  2001. if (withTransition) {
  2002. y2Axis = y2Axis.transition();
  2003. }
  2004. }
  2005. (withTransition ? $$.main.transition() : $$.main).attr('transform', $$.getTranslate('main'));
  2006. xAxis.attr('transform', $$.getTranslate('x'));
  2007. yAxis.attr('transform', $$.getTranslate('y'));
  2008. y2Axis.attr('transform', $$.getTranslate('y2'));
  2009. $$.main
  2010. .select('.' + CLASS.chartArcs)
  2011. .attr('transform', $$.getTranslate('arc'));
  2012. };
  2013. ChartInternal.prototype.transformAll = function (withTransition, transitions) {
  2014. var $$ = this;
  2015. $$.transformMain(withTransition, transitions);
  2016. if ($$.config.subchart_show) {
  2017. $$.transformContext(withTransition, transitions);
  2018. }
  2019. if ($$.legend) {
  2020. $$.transformLegend(withTransition);
  2021. }
  2022. };
  2023. ChartInternal.prototype.updateSvgSize = function () {
  2024. var $$ = this, brush = $$.svg.select("." + CLASS.brush + " .overlay");
  2025. $$.svg.attr('width', $$.currentWidth).attr('height', $$.currentHeight);
  2026. $$.svg
  2027. .selectAll(['#' + $$.clipId, '#' + $$.clipIdForGrid])
  2028. .select('rect')
  2029. .attr('width', $$.width)
  2030. .attr('height', $$.height);
  2031. $$.svg
  2032. .select('#' + $$.clipIdForXAxis)
  2033. .select('rect')
  2034. .attr('x', $$.getXAxisClipX.bind($$))
  2035. .attr('y', $$.getXAxisClipY.bind($$))
  2036. .attr('width', $$.getXAxisClipWidth.bind($$))
  2037. .attr('height', $$.getXAxisClipHeight.bind($$));
  2038. $$.svg
  2039. .select('#' + $$.clipIdForYAxis)
  2040. .select('rect')
  2041. .attr('x', $$.getYAxisClipX.bind($$))
  2042. .attr('y', $$.getYAxisClipY.bind($$))
  2043. .attr('width', $$.getYAxisClipWidth.bind($$))
  2044. .attr('height', $$.getYAxisClipHeight.bind($$));
  2045. $$.svg
  2046. .select('#' + $$.clipIdForSubchart)
  2047. .select('rect')
  2048. .attr('width', $$.width)
  2049. .attr('height', (brush.size() && brush.attr('height')) || 0);
  2050. // MEMO: parent div's height will be bigger than svg when <!DOCTYPE html>
  2051. $$.selectChart.style('max-height', $$.currentHeight + 'px');
  2052. };
  2053. ChartInternal.prototype.updateDimension = function (withoutAxis) {
  2054. var $$ = this;
  2055. if (!withoutAxis) {
  2056. if ($$.config.axis_rotated) {
  2057. $$.axes.x.call($$.xAxis);
  2058. $$.axes.subx.call($$.subXAxis);
  2059. }
  2060. else {
  2061. $$.axes.y.call($$.yAxis);
  2062. $$.axes.y2.call($$.y2Axis);
  2063. }
  2064. }
  2065. $$.updateSizes();
  2066. $$.updateScales();
  2067. $$.updateSvgSize();
  2068. $$.transformAll(false);
  2069. };
  2070. ChartInternal.prototype.observeInserted = function (selection) {
  2071. var $$ = this, observer;
  2072. if (typeof MutationObserver === 'undefined') {
  2073. window.console.error('MutationObserver not defined.');
  2074. return;
  2075. }
  2076. observer = new MutationObserver(function (mutations) {
  2077. mutations.forEach(function (mutation) {
  2078. if (mutation.type === 'childList' && mutation.previousSibling) {
  2079. observer.disconnect();
  2080. // need to wait for completion of load because size calculation requires the actual sizes determined after that completion
  2081. $$.intervalForObserveInserted = window.setInterval(function () {
  2082. // parentNode will NOT be null when completed
  2083. if (selection.node().parentNode) {
  2084. window.clearInterval($$.intervalForObserveInserted);
  2085. $$.updateDimension();
  2086. if ($$.brush) {
  2087. $$.brush.update();
  2088. }
  2089. $$.config.oninit.call($$);
  2090. $$.redraw({
  2091. withTransform: true,
  2092. withUpdateXDomain: true,
  2093. withUpdateOrgXDomain: true,
  2094. withTransition: false,
  2095. withTransitionForTransform: false,
  2096. withLegend: true
  2097. });
  2098. selection.transition().style('opacity', 1);
  2099. }
  2100. }, 10);
  2101. }
  2102. });
  2103. });
  2104. observer.observe(selection.node(), {
  2105. attributes: true,
  2106. childList: true,
  2107. characterData: true
  2108. });
  2109. };
  2110. /**
  2111. * Binds handlers to the window resize event.
  2112. */
  2113. ChartInternal.prototype.bindResize = function () {
  2114. var $$ = this, config = $$.config;
  2115. $$.resizeFunction = $$.generateResize(); // need to call .remove
  2116. $$.resizeFunction.add(function () {
  2117. config.onresize.call($$);
  2118. });
  2119. if (config.resize_auto) {
  2120. $$.resizeFunction.add(function () {
  2121. if ($$.resizeTimeout !== undefined) {
  2122. window.clearTimeout($$.resizeTimeout);
  2123. }
  2124. $$.resizeTimeout = window.setTimeout(function () {
  2125. delete $$.resizeTimeout;
  2126. $$.updateAndRedraw({
  2127. withUpdateXDomain: false,
  2128. withUpdateOrgXDomain: false,
  2129. withTransition: false,
  2130. withTransitionForTransform: false,
  2131. withLegend: true
  2132. });
  2133. if ($$.brush) {
  2134. $$.brush.update();
  2135. }
  2136. }, 100);
  2137. });
  2138. }
  2139. $$.resizeFunction.add(function () {
  2140. config.onresized.call($$);
  2141. });
  2142. $$.resizeIfElementDisplayed = function () {
  2143. // if element not displayed skip it
  2144. if ($$.api == null || !$$.api.element.offsetParent) {
  2145. return;
  2146. }
  2147. $$.resizeFunction();
  2148. };
  2149. window.addEventListener('resize', $$.resizeIfElementDisplayed, false);
  2150. };
  2151. /**
  2152. * Binds handlers to the window focus event.
  2153. */
  2154. ChartInternal.prototype.bindWindowFocus = function () {
  2155. var _this = this;
  2156. if (this.windowFocusHandler) {
  2157. // The handler is already set
  2158. return;
  2159. }
  2160. this.windowFocusHandler = function () {
  2161. _this.redraw();
  2162. };
  2163. window.addEventListener('focus', this.windowFocusHandler);
  2164. };
  2165. /**
  2166. * Unbinds from the window focus event.
  2167. */
  2168. ChartInternal.prototype.unbindWindowFocus = function () {
  2169. window.removeEventListener('focus', this.windowFocusHandler);
  2170. delete this.windowFocusHandler;
  2171. };
  2172. ChartInternal.prototype.generateResize = function () {
  2173. var resizeFunctions = [];
  2174. function callResizeFunctions() {
  2175. resizeFunctions.forEach(function (f) {
  2176. f();
  2177. });
  2178. }
  2179. callResizeFunctions.add = function (f) {
  2180. resizeFunctions.push(f);
  2181. };
  2182. callResizeFunctions.remove = function (f) {
  2183. for (var i = 0; i < resizeFunctions.length; i++) {
  2184. if (resizeFunctions[i] === f) {
  2185. resizeFunctions.splice(i, 1);
  2186. break;
  2187. }
  2188. }
  2189. };
  2190. return callResizeFunctions;
  2191. };
  2192. ChartInternal.prototype.endall = function (transition, callback) {
  2193. var n = 0;
  2194. transition
  2195. .each(function () {
  2196. ++n;
  2197. })
  2198. .on('end', function () {
  2199. if (!--n) {
  2200. callback.apply(this, arguments);
  2201. }
  2202. });
  2203. };
  2204. ChartInternal.prototype.generateWait = function () {
  2205. var $$ = this;
  2206. var transitionsToWait = [], f = function (callback) {
  2207. var timer = setInterval(function () {
  2208. if (!$$.isTabVisible()) {
  2209. return;
  2210. }
  2211. var done = 0;
  2212. transitionsToWait.forEach(function (t) {
  2213. if (t.empty()) {
  2214. done += 1;
  2215. return;
  2216. }
  2217. try {
  2218. t.transition();
  2219. }
  2220. catch (e) {
  2221. done += 1;
  2222. }
  2223. });
  2224. if (done === transitionsToWait.length) {
  2225. clearInterval(timer);
  2226. if (callback) {
  2227. callback();
  2228. }
  2229. }
  2230. }, 50);
  2231. };
  2232. f.add = function (transition) {
  2233. transitionsToWait.push(transition);
  2234. };
  2235. return f;
  2236. };
  2237. ChartInternal.prototype.parseDate = function (date) {
  2238. var $$ = this, parsedDate;
  2239. if (date instanceof Date) {
  2240. parsedDate = date;
  2241. }
  2242. else if (typeof date === 'string') {
  2243. parsedDate = $$.dataTimeParse(date);
  2244. }
  2245. else if (typeof date === 'object') {
  2246. parsedDate = new Date(+date);
  2247. }
  2248. else if (typeof date === 'number' && !isNaN(date)) {
  2249. parsedDate = new Date(+date);
  2250. }
  2251. if (!parsedDate || isNaN(+parsedDate)) {
  2252. window.console.error("Failed to parse x '" + date + "' to Date object");
  2253. }
  2254. return parsedDate;
  2255. };
  2256. ChartInternal.prototype.isTabVisible = function () {
  2257. return !document.hidden;
  2258. };
  2259. ChartInternal.prototype.getPathBox = getPathBox;
  2260. ChartInternal.prototype.CLASS = CLASS;
  2261. /* jshint ignore:start */
  2262. (function () {
  2263. if (!('SVGPathSeg' in window)) {
  2264. // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathSeg
  2265. window.SVGPathSeg = function (type, typeAsLetter, owningPathSegList) {
  2266. this.pathSegType = type;
  2267. this.pathSegTypeAsLetter = typeAsLetter;
  2268. this._owningPathSegList = owningPathSegList;
  2269. };
  2270. window.SVGPathSeg.prototype.classname = 'SVGPathSeg';
  2271. window.SVGPathSeg.PATHSEG_UNKNOWN = 0;
  2272. window.SVGPathSeg.PATHSEG_CLOSEPATH = 1;
  2273. window.SVGPathSeg.PATHSEG_MOVETO_ABS = 2;
  2274. window.SVGPathSeg.PATHSEG_MOVETO_REL = 3;
  2275. window.SVGPathSeg.PATHSEG_LINETO_ABS = 4;
  2276. window.SVGPathSeg.PATHSEG_LINETO_REL = 5;
  2277. window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS = 6;
  2278. window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL = 7;
  2279. window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS = 8;
  2280. window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL = 9;
  2281. window.SVGPathSeg.PATHSEG_ARC_ABS = 10;
  2282. window.SVGPathSeg.PATHSEG_ARC_REL = 11;
  2283. window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS = 12;
  2284. window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL = 13;
  2285. window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS = 14;
  2286. window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL = 15;
  2287. window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS = 16;
  2288. window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL = 17;
  2289. window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS = 18;
  2290. window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL = 19;
  2291. // Notify owning PathSegList on any changes so they can be synchronized back to the path element.
  2292. window.SVGPathSeg.prototype._segmentChanged = function () {
  2293. if (this._owningPathSegList)
  2294. this._owningPathSegList.segmentChanged(this);
  2295. };
  2296. window.SVGPathSegClosePath = function (owningPathSegList) {
  2297. window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CLOSEPATH, 'z', owningPathSegList);
  2298. };
  2299. window.SVGPathSegClosePath.prototype = Object.create(window.SVGPathSeg.prototype);
  2300. window.SVGPathSegClosePath.prototype.toString = function () {
  2301. return '[object SVGPathSegClosePath]';
  2302. };
  2303. window.SVGPathSegClosePath.prototype._asPathString = function () {
  2304. return this.pathSegTypeAsLetter;
  2305. };
  2306. window.SVGPathSegClosePath.prototype.clone = function () {
  2307. return new window.SVGPathSegClosePath(undefined);
  2308. };
  2309. window.SVGPathSegMovetoAbs = function (owningPathSegList, x, y) {
  2310. window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_MOVETO_ABS, 'M', owningPathSegList);
  2311. this._x = x;
  2312. this._y = y;
  2313. };
  2314. window.SVGPathSegMovetoAbs.prototype = Object.create(window.SVGPathSeg.prototype);
  2315. window.SVGPathSegMovetoAbs.prototype.toString = function () {
  2316. return '[object SVGPathSegMovetoAbs]';
  2317. };
  2318. window.SVGPathSegMovetoAbs.prototype._asPathString = function () {
  2319. return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y;
  2320. };
  2321. window.SVGPathSegMovetoAbs.prototype.clone = function () {
  2322. return new window.SVGPathSegMovetoAbs(undefined, this._x, this._y);
  2323. };
  2324. Object.defineProperty(window.SVGPathSegMovetoAbs.prototype, 'x', {
  2325. get: function () {
  2326. return this._x;
  2327. },
  2328. set: function (x) {
  2329. this._x = x;
  2330. this._segmentChanged();
  2331. },
  2332. enumerable: true
  2333. });
  2334. Object.defineProperty(window.SVGPathSegMovetoAbs.prototype, 'y', {
  2335. get: function () {
  2336. return this._y;
  2337. },
  2338. set: function (y) {
  2339. this._y = y;
  2340. this._segmentChanged();
  2341. },
  2342. enumerable: true
  2343. });
  2344. window.SVGPathSegMovetoRel = function (owningPathSegList, x, y) {
  2345. window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_MOVETO_REL, 'm', owningPathSegList);
  2346. this._x = x;
  2347. this._y = y;
  2348. };
  2349. window.SVGPathSegMovetoRel.prototype = Object.create(window.SVGPathSeg.prototype);
  2350. window.SVGPathSegMovetoRel.prototype.toString = function () {
  2351. return '[object SVGPathSegMovetoRel]';
  2352. };
  2353. window.SVGPathSegMovetoRel.prototype._asPathString = function () {
  2354. return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y;
  2355. };
  2356. window.SVGPathSegMovetoRel.prototype.clone = function () {
  2357. return new window.SVGPathSegMovetoRel(undefined, this._x, this._y);
  2358. };
  2359. Object.defineProperty(window.SVGPathSegMovetoRel.prototype, 'x', {
  2360. get: function () {
  2361. return this._x;
  2362. },
  2363. set: function (x) {
  2364. this._x = x;
  2365. this._segmentChanged();
  2366. },
  2367. enumerable: true
  2368. });
  2369. Object.defineProperty(window.SVGPathSegMovetoRel.prototype, 'y', {
  2370. get: function () {
  2371. return this._y;
  2372. },
  2373. set: function (y) {
  2374. this._y = y;
  2375. this._segmentChanged();
  2376. },
  2377. enumerable: true
  2378. });
  2379. window.SVGPathSegLinetoAbs = function (owningPathSegList, x, y) {
  2380. window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_LINETO_ABS, 'L', owningPathSegList);
  2381. this._x = x;
  2382. this._y = y;
  2383. };
  2384. window.SVGPathSegLinetoAbs.prototype = Object.create(window.SVGPathSeg.prototype);
  2385. window.SVGPathSegLinetoAbs.prototype.toString = function () {
  2386. return '[object SVGPathSegLinetoAbs]';
  2387. };
  2388. window.SVGPathSegLinetoAbs.prototype._asPathString = function () {
  2389. return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y;
  2390. };
  2391. window.SVGPathSegLinetoAbs.prototype.clone = function () {
  2392. return new window.SVGPathSegLinetoAbs(undefined, this._x, this._y);
  2393. };
  2394. Object.defineProperty(window.SVGPathSegLinetoAbs.prototype, 'x', {
  2395. get: function () {
  2396. return this._x;
  2397. },
  2398. set: function (x) {
  2399. this._x = x;
  2400. this._segmentChanged();
  2401. },
  2402. enumerable: true
  2403. });
  2404. Object.defineProperty(window.SVGPathSegLinetoAbs.prototype, 'y', {
  2405. get: function () {
  2406. return this._y;
  2407. },
  2408. set: function (y) {
  2409. this._y = y;
  2410. this._segmentChanged();
  2411. },
  2412. enumerable: true
  2413. });
  2414. window.SVGPathSegLinetoRel = function (owningPathSegList, x, y) {
  2415. window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_LINETO_REL, 'l', owningPathSegList);
  2416. this._x = x;
  2417. this._y = y;
  2418. };
  2419. window.SVGPathSegLinetoRel.prototype = Object.create(window.SVGPathSeg.prototype);
  2420. window.SVGPathSegLinetoRel.prototype.toString = function () {
  2421. return '[object SVGPathSegLinetoRel]';
  2422. };
  2423. window.SVGPathSegLinetoRel.prototype._asPathString = function () {
  2424. return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y;
  2425. };
  2426. window.SVGPathSegLinetoRel.prototype.clone = function () {
  2427. return new window.SVGPathSegLinetoRel(undefined, this._x, this._y);
  2428. };
  2429. Object.defineProperty(window.SVGPathSegLinetoRel.prototype, 'x', {
  2430. get: function () {
  2431. return this._x;
  2432. },
  2433. set: function (x) {
  2434. this._x = x;
  2435. this._segmentChanged();
  2436. },
  2437. enumerable: true
  2438. });
  2439. Object.defineProperty(window.SVGPathSegLinetoRel.prototype, 'y', {
  2440. get: function () {
  2441. return this._y;
  2442. },
  2443. set: function (y) {
  2444. this._y = y;
  2445. this._segmentChanged();
  2446. },
  2447. enumerable: true
  2448. });
  2449. window.SVGPathSegCurvetoCubicAbs = function (owningPathSegList, x, y, x1, y1, x2, y2) {
  2450. window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS, 'C', owningPathSegList);
  2451. this._x = x;
  2452. this._y = y;
  2453. this._x1 = x1;
  2454. this._y1 = y1;
  2455. this._x2 = x2;
  2456. this._y2 = y2;
  2457. };
  2458. window.SVGPathSegCurvetoCubicAbs.prototype = Object.create(window.SVGPathSeg.prototype);
  2459. window.SVGPathSegCurvetoCubicAbs.prototype.toString = function () {
  2460. return '[object SVGPathSegCurvetoCubicAbs]';
  2461. };
  2462. window.SVGPathSegCurvetoCubicAbs.prototype._asPathString = function () {
  2463. return (this.pathSegTypeAsLetter +
  2464. ' ' +
  2465. this._x1 +
  2466. ' ' +
  2467. this._y1 +
  2468. ' ' +
  2469. this._x2 +
  2470. ' ' +
  2471. this._y2 +
  2472. ' ' +
  2473. this._x +
  2474. ' ' +
  2475. this._y);
  2476. };
  2477. window.SVGPathSegCurvetoCubicAbs.prototype.clone = function () {
  2478. return new window.SVGPathSegCurvetoCubicAbs(undefined, this._x, this._y, this._x1, this._y1, this._x2, this._y2);
  2479. };
  2480. Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, 'x', {
  2481. get: function () {
  2482. return this._x;
  2483. },
  2484. set: function (x) {
  2485. this._x = x;
  2486. this._segmentChanged();
  2487. },
  2488. enumerable: true
  2489. });
  2490. Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, 'y', {
  2491. get: function () {
  2492. return this._y;
  2493. },
  2494. set: function (y) {
  2495. this._y = y;
  2496. this._segmentChanged();
  2497. },
  2498. enumerable: true
  2499. });
  2500. Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, 'x1', {
  2501. get: function () {
  2502. return this._x1;
  2503. },
  2504. set: function (x1) {
  2505. this._x1 = x1;
  2506. this._segmentChanged();
  2507. },
  2508. enumerable: true
  2509. });
  2510. Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, 'y1', {
  2511. get: function () {
  2512. return this._y1;
  2513. },
  2514. set: function (y1) {
  2515. this._y1 = y1;
  2516. this._segmentChanged();
  2517. },
  2518. enumerable: true
  2519. });
  2520. Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, 'x2', {
  2521. get: function () {
  2522. return this._x2;
  2523. },
  2524. set: function (x2) {
  2525. this._x2 = x2;
  2526. this._segmentChanged();
  2527. },
  2528. enumerable: true
  2529. });
  2530. Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, 'y2', {
  2531. get: function () {
  2532. return this._y2;
  2533. },
  2534. set: function (y2) {
  2535. this._y2 = y2;
  2536. this._segmentChanged();
  2537. },
  2538. enumerable: true
  2539. });
  2540. window.SVGPathSegCurvetoCubicRel = function (owningPathSegList, x, y, x1, y1, x2, y2) {
  2541. window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL, 'c', owningPathSegList);
  2542. this._x = x;
  2543. this._y = y;
  2544. this._x1 = x1;
  2545. this._y1 = y1;
  2546. this._x2 = x2;
  2547. this._y2 = y2;
  2548. };
  2549. window.SVGPathSegCurvetoCubicRel.prototype = Object.create(window.SVGPathSeg.prototype);
  2550. window.SVGPathSegCurvetoCubicRel.prototype.toString = function () {
  2551. return '[object SVGPathSegCurvetoCubicRel]';
  2552. };
  2553. window.SVGPathSegCurvetoCubicRel.prototype._asPathString = function () {
  2554. return (this.pathSegTypeAsLetter +
  2555. ' ' +
  2556. this._x1 +
  2557. ' ' +
  2558. this._y1 +
  2559. ' ' +
  2560. this._x2 +
  2561. ' ' +
  2562. this._y2 +
  2563. ' ' +
  2564. this._x +
  2565. ' ' +
  2566. this._y);
  2567. };
  2568. window.SVGPathSegCurvetoCubicRel.prototype.clone = function () {
  2569. return new window.SVGPathSegCurvetoCubicRel(undefined, this._x, this._y, this._x1, this._y1, this._x2, this._y2);
  2570. };
  2571. Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, 'x', {
  2572. get: function () {
  2573. return this._x;
  2574. },
  2575. set: function (x) {
  2576. this._x = x;
  2577. this._segmentChanged();
  2578. },
  2579. enumerable: true
  2580. });
  2581. Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, 'y', {
  2582. get: function () {
  2583. return this._y;
  2584. },
  2585. set: function (y) {
  2586. this._y = y;
  2587. this._segmentChanged();
  2588. },
  2589. enumerable: true
  2590. });
  2591. Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, 'x1', {
  2592. get: function () {
  2593. return this._x1;
  2594. },
  2595. set: function (x1) {
  2596. this._x1 = x1;
  2597. this._segmentChanged();
  2598. },
  2599. enumerable: true
  2600. });
  2601. Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, 'y1', {
  2602. get: function () {
  2603. return this._y1;
  2604. },
  2605. set: function (y1) {
  2606. this._y1 = y1;
  2607. this._segmentChanged();
  2608. },
  2609. enumerable: true
  2610. });
  2611. Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, 'x2', {
  2612. get: function () {
  2613. return this._x2;
  2614. },
  2615. set: function (x2) {
  2616. this._x2 = x2;
  2617. this._segmentChanged();
  2618. },
  2619. enumerable: true
  2620. });
  2621. Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, 'y2', {
  2622. get: function () {
  2623. return this._y2;
  2624. },
  2625. set: function (y2) {
  2626. this._y2 = y2;
  2627. this._segmentChanged();
  2628. },
  2629. enumerable: true
  2630. });
  2631. window.SVGPathSegCurvetoQuadraticAbs = function (owningPathSegList, x, y, x1, y1) {
  2632. window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS, 'Q', owningPathSegList);
  2633. this._x = x;
  2634. this._y = y;
  2635. this._x1 = x1;
  2636. this._y1 = y1;
  2637. };
  2638. window.SVGPathSegCurvetoQuadraticAbs.prototype = Object.create(window.SVGPathSeg.prototype);
  2639. window.SVGPathSegCurvetoQuadraticAbs.prototype.toString = function () {
  2640. return '[object SVGPathSegCurvetoQuadraticAbs]';
  2641. };
  2642. window.SVGPathSegCurvetoQuadraticAbs.prototype._asPathString = function () {
  2643. return (this.pathSegTypeAsLetter +
  2644. ' ' +
  2645. this._x1 +
  2646. ' ' +
  2647. this._y1 +
  2648. ' ' +
  2649. this._x +
  2650. ' ' +
  2651. this._y);
  2652. };
  2653. window.SVGPathSegCurvetoQuadraticAbs.prototype.clone = function () {
  2654. return new window.SVGPathSegCurvetoQuadraticAbs(undefined, this._x, this._y, this._x1, this._y1);
  2655. };
  2656. Object.defineProperty(window.SVGPathSegCurvetoQuadraticAbs.prototype, 'x', {
  2657. get: function () {
  2658. return this._x;
  2659. },
  2660. set: function (x) {
  2661. this._x = x;
  2662. this._segmentChanged();
  2663. },
  2664. enumerable: true
  2665. });
  2666. Object.defineProperty(window.SVGPathSegCurvetoQuadraticAbs.prototype, 'y', {
  2667. get: function () {
  2668. return this._y;
  2669. },
  2670. set: function (y) {
  2671. this._y = y;
  2672. this._segmentChanged();
  2673. },
  2674. enumerable: true
  2675. });
  2676. Object.defineProperty(window.SVGPathSegCurvetoQuadraticAbs.prototype, 'x1', {
  2677. get: function () {
  2678. return this._x1;
  2679. },
  2680. set: function (x1) {
  2681. this._x1 = x1;
  2682. this._segmentChanged();
  2683. },
  2684. enumerable: true
  2685. });
  2686. Object.defineProperty(window.SVGPathSegCurvetoQuadraticAbs.prototype, 'y1', {
  2687. get: function () {
  2688. return this._y1;
  2689. },
  2690. set: function (y1) {
  2691. this._y1 = y1;
  2692. this._segmentChanged();
  2693. },
  2694. enumerable: true
  2695. });
  2696. window.SVGPathSegCurvetoQuadraticRel = function (owningPathSegList, x, y, x1, y1) {
  2697. window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL, 'q', owningPathSegList);
  2698. this._x = x;
  2699. this._y = y;
  2700. this._x1 = x1;
  2701. this._y1 = y1;
  2702. };
  2703. window.SVGPathSegCurvetoQuadraticRel.prototype = Object.create(window.SVGPathSeg.prototype);
  2704. window.SVGPathSegCurvetoQuadraticRel.prototype.toString = function () {
  2705. return '[object SVGPathSegCurvetoQuadraticRel]';
  2706. };
  2707. window.SVGPathSegCurvetoQuadraticRel.prototype._asPathString = function () {
  2708. return (this.pathSegTypeAsLetter +
  2709. ' ' +
  2710. this._x1 +
  2711. ' ' +
  2712. this._y1 +
  2713. ' ' +
  2714. this._x +
  2715. ' ' +
  2716. this._y);
  2717. };
  2718. window.SVGPathSegCurvetoQuadraticRel.prototype.clone = function () {
  2719. return new window.SVGPathSegCurvetoQuadraticRel(undefined, this._x, this._y, this._x1, this._y1);
  2720. };
  2721. Object.defineProperty(window.SVGPathSegCurvetoQuadraticRel.prototype, 'x', {
  2722. get: function () {
  2723. return this._x;
  2724. },
  2725. set: function (x) {
  2726. this._x = x;
  2727. this._segmentChanged();
  2728. },
  2729. enumerable: true
  2730. });
  2731. Object.defineProperty(window.SVGPathSegCurvetoQuadraticRel.prototype, 'y', {
  2732. get: function () {
  2733. return this._y;
  2734. },
  2735. set: function (y) {
  2736. this._y = y;
  2737. this._segmentChanged();
  2738. },
  2739. enumerable: true
  2740. });
  2741. Object.defineProperty(window.SVGPathSegCurvetoQuadraticRel.prototype, 'x1', {
  2742. get: function () {
  2743. return this._x1;
  2744. },
  2745. set: function (x1) {
  2746. this._x1 = x1;
  2747. this._segmentChanged();
  2748. },
  2749. enumerable: true
  2750. });
  2751. Object.defineProperty(window.SVGPathSegCurvetoQuadraticRel.prototype, 'y1', {
  2752. get: function () {
  2753. return this._y1;
  2754. },
  2755. set: function (y1) {
  2756. this._y1 = y1;
  2757. this._segmentChanged();
  2758. },
  2759. enumerable: true
  2760. });
  2761. window.SVGPathSegArcAbs = function (owningPathSegList, x, y, r1, r2, angle, largeArcFlag, sweepFlag) {
  2762. window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_ARC_ABS, 'A', owningPathSegList);
  2763. this._x = x;
  2764. this._y = y;
  2765. this._r1 = r1;
  2766. this._r2 = r2;
  2767. this._angle = angle;
  2768. this._largeArcFlag = largeArcFlag;
  2769. this._sweepFlag = sweepFlag;
  2770. };
  2771. window.SVGPathSegArcAbs.prototype = Object.create(window.SVGPathSeg.prototype);
  2772. window.SVGPathSegArcAbs.prototype.toString = function () {
  2773. return '[object SVGPathSegArcAbs]';
  2774. };
  2775. window.SVGPathSegArcAbs.prototype._asPathString = function () {
  2776. return (this.pathSegTypeAsLetter +
  2777. ' ' +
  2778. this._r1 +
  2779. ' ' +
  2780. this._r2 +
  2781. ' ' +
  2782. this._angle +
  2783. ' ' +
  2784. (this._largeArcFlag ? '1' : '0') +
  2785. ' ' +
  2786. (this._sweepFlag ? '1' : '0') +
  2787. ' ' +
  2788. this._x +
  2789. ' ' +
  2790. this._y);
  2791. };
  2792. window.SVGPathSegArcAbs.prototype.clone = function () {
  2793. return new window.SVGPathSegArcAbs(undefined, this._x, this._y, this._r1, this._r2, this._angle, this._largeArcFlag, this._sweepFlag);
  2794. };
  2795. Object.defineProperty(window.SVGPathSegArcAbs.prototype, 'x', {
  2796. get: function () {
  2797. return this._x;
  2798. },
  2799. set: function (x) {
  2800. this._x = x;
  2801. this._segmentChanged();
  2802. },
  2803. enumerable: true
  2804. });
  2805. Object.defineProperty(window.SVGPathSegArcAbs.prototype, 'y', {
  2806. get: function () {
  2807. return this._y;
  2808. },
  2809. set: function (y) {
  2810. this._y = y;
  2811. this._segmentChanged();
  2812. },
  2813. enumerable: true
  2814. });
  2815. Object.defineProperty(window.SVGPathSegArcAbs.prototype, 'r1', {
  2816. get: function () {
  2817. return this._r1;
  2818. },
  2819. set: function (r1) {
  2820. this._r1 = r1;
  2821. this._segmentChanged();
  2822. },
  2823. enumerable: true
  2824. });
  2825. Object.defineProperty(window.SVGPathSegArcAbs.prototype, 'r2', {
  2826. get: function () {
  2827. return this._r2;
  2828. },
  2829. set: function (r2) {
  2830. this._r2 = r2;
  2831. this._segmentChanged();
  2832. },
  2833. enumerable: true
  2834. });
  2835. Object.defineProperty(window.SVGPathSegArcAbs.prototype, 'angle', {
  2836. get: function () {
  2837. return this._angle;
  2838. },
  2839. set: function (angle) {
  2840. this._angle = angle;
  2841. this._segmentChanged();
  2842. },
  2843. enumerable: true
  2844. });
  2845. Object.defineProperty(window.SVGPathSegArcAbs.prototype, 'largeArcFlag', {
  2846. get: function () {
  2847. return this._largeArcFlag;
  2848. },
  2849. set: function (largeArcFlag) {
  2850. this._largeArcFlag = largeArcFlag;
  2851. this._segmentChanged();
  2852. },
  2853. enumerable: true
  2854. });
  2855. Object.defineProperty(window.SVGPathSegArcAbs.prototype, 'sweepFlag', {
  2856. get: function () {
  2857. return this._sweepFlag;
  2858. },
  2859. set: function (sweepFlag) {
  2860. this._sweepFlag = sweepFlag;
  2861. this._segmentChanged();
  2862. },
  2863. enumerable: true
  2864. });
  2865. window.SVGPathSegArcRel = function (owningPathSegList, x, y, r1, r2, angle, largeArcFlag, sweepFlag) {
  2866. window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_ARC_REL, 'a', owningPathSegList);
  2867. this._x = x;
  2868. this._y = y;
  2869. this._r1 = r1;
  2870. this._r2 = r2;
  2871. this._angle = angle;
  2872. this._largeArcFlag = largeArcFlag;
  2873. this._sweepFlag = sweepFlag;
  2874. };
  2875. window.SVGPathSegArcRel.prototype = Object.create(window.SVGPathSeg.prototype);
  2876. window.SVGPathSegArcRel.prototype.toString = function () {
  2877. return '[object SVGPathSegArcRel]';
  2878. };
  2879. window.SVGPathSegArcRel.prototype._asPathString = function () {
  2880. return (this.pathSegTypeAsLetter +
  2881. ' ' +
  2882. this._r1 +
  2883. ' ' +
  2884. this._r2 +
  2885. ' ' +
  2886. this._angle +
  2887. ' ' +
  2888. (this._largeArcFlag ? '1' : '0') +
  2889. ' ' +
  2890. (this._sweepFlag ? '1' : '0') +
  2891. ' ' +
  2892. this._x +
  2893. ' ' +
  2894. this._y);
  2895. };
  2896. window.SVGPathSegArcRel.prototype.clone = function () {
  2897. return new window.SVGPathSegArcRel(undefined, this._x, this._y, this._r1, this._r2, this._angle, this._largeArcFlag, this._sweepFlag);
  2898. };
  2899. Object.defineProperty(window.SVGPathSegArcRel.prototype, 'x', {
  2900. get: function () {
  2901. return this._x;
  2902. },
  2903. set: function (x) {
  2904. this._x = x;
  2905. this._segmentChanged();
  2906. },
  2907. enumerable: true
  2908. });
  2909. Object.defineProperty(window.SVGPathSegArcRel.prototype, 'y', {
  2910. get: function () {
  2911. return this._y;
  2912. },
  2913. set: function (y) {
  2914. this._y = y;
  2915. this._segmentChanged();
  2916. },
  2917. enumerable: true
  2918. });
  2919. Object.defineProperty(window.SVGPathSegArcRel.prototype, 'r1', {
  2920. get: function () {
  2921. return this._r1;
  2922. },
  2923. set: function (r1) {
  2924. this._r1 = r1;
  2925. this._segmentChanged();
  2926. },
  2927. enumerable: true
  2928. });
  2929. Object.defineProperty(window.SVGPathSegArcRel.prototype, 'r2', {
  2930. get: function () {
  2931. return this._r2;
  2932. },
  2933. set: function (r2) {
  2934. this._r2 = r2;
  2935. this._segmentChanged();
  2936. },
  2937. enumerable: true
  2938. });
  2939. Object.defineProperty(window.SVGPathSegArcRel.prototype, 'angle', {
  2940. get: function () {
  2941. return this._angle;
  2942. },
  2943. set: function (angle) {
  2944. this._angle = angle;
  2945. this._segmentChanged();
  2946. },
  2947. enumerable: true
  2948. });
  2949. Object.defineProperty(window.SVGPathSegArcRel.prototype, 'largeArcFlag', {
  2950. get: function () {
  2951. return this._largeArcFlag;
  2952. },
  2953. set: function (largeArcFlag) {
  2954. this._largeArcFlag = largeArcFlag;
  2955. this._segmentChanged();
  2956. },
  2957. enumerable: true
  2958. });
  2959. Object.defineProperty(window.SVGPathSegArcRel.prototype, 'sweepFlag', {
  2960. get: function () {
  2961. return this._sweepFlag;
  2962. },
  2963. set: function (sweepFlag) {
  2964. this._sweepFlag = sweepFlag;
  2965. this._segmentChanged();
  2966. },
  2967. enumerable: true
  2968. });
  2969. window.SVGPathSegLinetoHorizontalAbs = function (owningPathSegList, x) {
  2970. window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS, 'H', owningPathSegList);
  2971. this._x = x;
  2972. };
  2973. window.SVGPathSegLinetoHorizontalAbs.prototype = Object.create(window.SVGPathSeg.prototype);
  2974. window.SVGPathSegLinetoHorizontalAbs.prototype.toString = function () {
  2975. return '[object SVGPathSegLinetoHorizontalAbs]';
  2976. };
  2977. window.SVGPathSegLinetoHorizontalAbs.prototype._asPathString = function () {
  2978. return this.pathSegTypeAsLetter + ' ' + this._x;
  2979. };
  2980. window.SVGPathSegLinetoHorizontalAbs.prototype.clone = function () {
  2981. return new window.SVGPathSegLinetoHorizontalAbs(undefined, this._x);
  2982. };
  2983. Object.defineProperty(window.SVGPathSegLinetoHorizontalAbs.prototype, 'x', {
  2984. get: function () {
  2985. return this._x;
  2986. },
  2987. set: function (x) {
  2988. this._x = x;
  2989. this._segmentChanged();
  2990. },
  2991. enumerable: true
  2992. });
  2993. window.SVGPathSegLinetoHorizontalRel = function (owningPathSegList, x) {
  2994. window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL, 'h', owningPathSegList);
  2995. this._x = x;
  2996. };
  2997. window.SVGPathSegLinetoHorizontalRel.prototype = Object.create(window.SVGPathSeg.prototype);
  2998. window.SVGPathSegLinetoHorizontalRel.prototype.toString = function () {
  2999. return '[object SVGPathSegLinetoHorizontalRel]';
  3000. };
  3001. window.SVGPathSegLinetoHorizontalRel.prototype._asPathString = function () {
  3002. return this.pathSegTypeAsLetter + ' ' + this._x;
  3003. };
  3004. window.SVGPathSegLinetoHorizontalRel.prototype.clone = function () {
  3005. return new window.SVGPathSegLinetoHorizontalRel(undefined, this._x);
  3006. };
  3007. Object.defineProperty(window.SVGPathSegLinetoHorizontalRel.prototype, 'x', {
  3008. get: function () {
  3009. return this._x;
  3010. },
  3011. set: function (x) {
  3012. this._x = x;
  3013. this._segmentChanged();
  3014. },
  3015. enumerable: true
  3016. });
  3017. window.SVGPathSegLinetoVerticalAbs = function (owningPathSegList, y) {
  3018. window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS, 'V', owningPathSegList);
  3019. this._y = y;
  3020. };
  3021. window.SVGPathSegLinetoVerticalAbs.prototype = Object.create(window.SVGPathSeg.prototype);
  3022. window.SVGPathSegLinetoVerticalAbs.prototype.toString = function () {
  3023. return '[object SVGPathSegLinetoVerticalAbs]';
  3024. };
  3025. window.SVGPathSegLinetoVerticalAbs.prototype._asPathString = function () {
  3026. return this.pathSegTypeAsLetter + ' ' + this._y;
  3027. };
  3028. window.SVGPathSegLinetoVerticalAbs.prototype.clone = function () {
  3029. return new window.SVGPathSegLinetoVerticalAbs(undefined, this._y);
  3030. };
  3031. Object.defineProperty(window.SVGPathSegLinetoVerticalAbs.prototype, 'y', {
  3032. get: function () {
  3033. return this._y;
  3034. },
  3035. set: function (y) {
  3036. this._y = y;
  3037. this._segmentChanged();
  3038. },
  3039. enumerable: true
  3040. });
  3041. window.SVGPathSegLinetoVerticalRel = function (owningPathSegList, y) {
  3042. window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL, 'v', owningPathSegList);
  3043. this._y = y;
  3044. };
  3045. window.SVGPathSegLinetoVerticalRel.prototype = Object.create(window.SVGPathSeg.prototype);
  3046. window.SVGPathSegLinetoVerticalRel.prototype.toString = function () {
  3047. return '[object SVGPathSegLinetoVerticalRel]';
  3048. };
  3049. window.SVGPathSegLinetoVerticalRel.prototype._asPathString = function () {
  3050. return this.pathSegTypeAsLetter + ' ' + this._y;
  3051. };
  3052. window.SVGPathSegLinetoVerticalRel.prototype.clone = function () {
  3053. return new window.SVGPathSegLinetoVerticalRel(undefined, this._y);
  3054. };
  3055. Object.defineProperty(window.SVGPathSegLinetoVerticalRel.prototype, 'y', {
  3056. get: function () {
  3057. return this._y;
  3058. },
  3059. set: function (y) {
  3060. this._y = y;
  3061. this._segmentChanged();
  3062. },
  3063. enumerable: true
  3064. });
  3065. window.SVGPathSegCurvetoCubicSmoothAbs = function (owningPathSegList, x, y, x2, y2) {
  3066. window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS, 'S', owningPathSegList);
  3067. this._x = x;
  3068. this._y = y;
  3069. this._x2 = x2;
  3070. this._y2 = y2;
  3071. };
  3072. window.SVGPathSegCurvetoCubicSmoothAbs.prototype = Object.create(window.SVGPathSeg.prototype);
  3073. window.SVGPathSegCurvetoCubicSmoothAbs.prototype.toString = function () {
  3074. return '[object SVGPathSegCurvetoCubicSmoothAbs]';
  3075. };
  3076. window.SVGPathSegCurvetoCubicSmoothAbs.prototype._asPathString = function () {
  3077. return (this.pathSegTypeAsLetter +
  3078. ' ' +
  3079. this._x2 +
  3080. ' ' +
  3081. this._y2 +
  3082. ' ' +
  3083. this._x +
  3084. ' ' +
  3085. this._y);
  3086. };
  3087. window.SVGPathSegCurvetoCubicSmoothAbs.prototype.clone = function () {
  3088. return new window.SVGPathSegCurvetoCubicSmoothAbs(undefined, this._x, this._y, this._x2, this._y2);
  3089. };
  3090. Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothAbs.prototype, 'x', {
  3091. get: function () {
  3092. return this._x;
  3093. },
  3094. set: function (x) {
  3095. this._x = x;
  3096. this._segmentChanged();
  3097. },
  3098. enumerable: true
  3099. });
  3100. Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothAbs.prototype, 'y', {
  3101. get: function () {
  3102. return this._y;
  3103. },
  3104. set: function (y) {
  3105. this._y = y;
  3106. this._segmentChanged();
  3107. },
  3108. enumerable: true
  3109. });
  3110. Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothAbs.prototype, 'x2', {
  3111. get: function () {
  3112. return this._x2;
  3113. },
  3114. set: function (x2) {
  3115. this._x2 = x2;
  3116. this._segmentChanged();
  3117. },
  3118. enumerable: true
  3119. });
  3120. Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothAbs.prototype, 'y2', {
  3121. get: function () {
  3122. return this._y2;
  3123. },
  3124. set: function (y2) {
  3125. this._y2 = y2;
  3126. this._segmentChanged();
  3127. },
  3128. enumerable: true
  3129. });
  3130. window.SVGPathSegCurvetoCubicSmoothRel = function (owningPathSegList, x, y, x2, y2) {
  3131. window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL, 's', owningPathSegList);
  3132. this._x = x;
  3133. this._y = y;
  3134. this._x2 = x2;
  3135. this._y2 = y2;
  3136. };
  3137. window.SVGPathSegCurvetoCubicSmoothRel.prototype = Object.create(window.SVGPathSeg.prototype);
  3138. window.SVGPathSegCurvetoCubicSmoothRel.prototype.toString = function () {
  3139. return '[object SVGPathSegCurvetoCubicSmoothRel]';
  3140. };
  3141. window.SVGPathSegCurvetoCubicSmoothRel.prototype._asPathString = function () {
  3142. return (this.pathSegTypeAsLetter +
  3143. ' ' +
  3144. this._x2 +
  3145. ' ' +
  3146. this._y2 +
  3147. ' ' +
  3148. this._x +
  3149. ' ' +
  3150. this._y);
  3151. };
  3152. window.SVGPathSegCurvetoCubicSmoothRel.prototype.clone = function () {
  3153. return new window.SVGPathSegCurvetoCubicSmoothRel(undefined, this._x, this._y, this._x2, this._y2);
  3154. };
  3155. Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothRel.prototype, 'x', {
  3156. get: function () {
  3157. return this._x;
  3158. },
  3159. set: function (x) {
  3160. this._x = x;
  3161. this._segmentChanged();
  3162. },
  3163. enumerable: true
  3164. });
  3165. Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothRel.prototype, 'y', {
  3166. get: function () {
  3167. return this._y;
  3168. },
  3169. set: function (y) {
  3170. this._y = y;
  3171. this._segmentChanged();
  3172. },
  3173. enumerable: true
  3174. });
  3175. Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothRel.prototype, 'x2', {
  3176. get: function () {
  3177. return this._x2;
  3178. },
  3179. set: function (x2) {
  3180. this._x2 = x2;
  3181. this._segmentChanged();
  3182. },
  3183. enumerable: true
  3184. });
  3185. Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothRel.prototype, 'y2', {
  3186. get: function () {
  3187. return this._y2;
  3188. },
  3189. set: function (y2) {
  3190. this._y2 = y2;
  3191. this._segmentChanged();
  3192. },
  3193. enumerable: true
  3194. });
  3195. window.SVGPathSegCurvetoQuadraticSmoothAbs = function (owningPathSegList, x, y) {
  3196. window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS, 'T', owningPathSegList);
  3197. this._x = x;
  3198. this._y = y;
  3199. };
  3200. window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype = Object.create(window.SVGPathSeg.prototype);
  3201. window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype.toString = function () {
  3202. return '[object SVGPathSegCurvetoQuadraticSmoothAbs]';
  3203. };
  3204. window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype._asPathString = function () {
  3205. return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y;
  3206. };
  3207. window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype.clone = function () {
  3208. return new window.SVGPathSegCurvetoQuadraticSmoothAbs(undefined, this._x, this._y);
  3209. };
  3210. Object.defineProperty(window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype, 'x', {
  3211. get: function () {
  3212. return this._x;
  3213. },
  3214. set: function (x) {
  3215. this._x = x;
  3216. this._segmentChanged();
  3217. },
  3218. enumerable: true
  3219. });
  3220. Object.defineProperty(window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype, 'y', {
  3221. get: function () {
  3222. return this._y;
  3223. },
  3224. set: function (y) {
  3225. this._y = y;
  3226. this._segmentChanged();
  3227. },
  3228. enumerable: true
  3229. });
  3230. window.SVGPathSegCurvetoQuadraticSmoothRel = function (owningPathSegList, x, y) {
  3231. window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL, 't', owningPathSegList);
  3232. this._x = x;
  3233. this._y = y;
  3234. };
  3235. window.SVGPathSegCurvetoQuadraticSmoothRel.prototype = Object.create(window.SVGPathSeg.prototype);
  3236. window.SVGPathSegCurvetoQuadraticSmoothRel.prototype.toString = function () {
  3237. return '[object SVGPathSegCurvetoQuadraticSmoothRel]';
  3238. };
  3239. window.SVGPathSegCurvetoQuadraticSmoothRel.prototype._asPathString = function () {
  3240. return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y;
  3241. };
  3242. window.SVGPathSegCurvetoQuadraticSmoothRel.prototype.clone = function () {
  3243. return new window.SVGPathSegCurvetoQuadraticSmoothRel(undefined, this._x, this._y);
  3244. };
  3245. Object.defineProperty(window.SVGPathSegCurvetoQuadraticSmoothRel.prototype, 'x', {
  3246. get: function () {
  3247. return this._x;
  3248. },
  3249. set: function (x) {
  3250. this._x = x;
  3251. this._segmentChanged();
  3252. },
  3253. enumerable: true
  3254. });
  3255. Object.defineProperty(window.SVGPathSegCurvetoQuadraticSmoothRel.prototype, 'y', {
  3256. get: function () {
  3257. return this._y;
  3258. },
  3259. set: function (y) {
  3260. this._y = y;
  3261. this._segmentChanged();
  3262. },
  3263. enumerable: true
  3264. });
  3265. // Add createSVGPathSeg* functions to window.SVGPathElement.
  3266. // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-Interfacewindow.SVGPathElement.
  3267. window.SVGPathElement.prototype.createSVGPathSegClosePath = function () {
  3268. return new window.SVGPathSegClosePath(undefined);
  3269. };
  3270. window.SVGPathElement.prototype.createSVGPathSegMovetoAbs = function (x, y) {
  3271. return new window.SVGPathSegMovetoAbs(undefined, x, y);
  3272. };
  3273. window.SVGPathElement.prototype.createSVGPathSegMovetoRel = function (x, y) {
  3274. return new window.SVGPathSegMovetoRel(undefined, x, y);
  3275. };
  3276. window.SVGPathElement.prototype.createSVGPathSegLinetoAbs = function (x, y) {
  3277. return new window.SVGPathSegLinetoAbs(undefined, x, y);
  3278. };
  3279. window.SVGPathElement.prototype.createSVGPathSegLinetoRel = function (x, y) {
  3280. return new window.SVGPathSegLinetoRel(undefined, x, y);
  3281. };
  3282. window.SVGPathElement.prototype.createSVGPathSegCurvetoCubicAbs = function (x, y, x1, y1, x2, y2) {
  3283. return new window.SVGPathSegCurvetoCubicAbs(undefined, x, y, x1, y1, x2, y2);
  3284. };
  3285. window.SVGPathElement.prototype.createSVGPathSegCurvetoCubicRel = function (x, y, x1, y1, x2, y2) {
  3286. return new window.SVGPathSegCurvetoCubicRel(undefined, x, y, x1, y1, x2, y2);
  3287. };
  3288. window.SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticAbs = function (x, y, x1, y1) {
  3289. return new window.SVGPathSegCurvetoQuadraticAbs(undefined, x, y, x1, y1);
  3290. };
  3291. window.SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticRel = function (x, y, x1, y1) {
  3292. return new window.SVGPathSegCurvetoQuadraticRel(undefined, x, y, x1, y1);
  3293. };
  3294. window.SVGPathElement.prototype.createSVGPathSegArcAbs = function (x, y, r1, r2, angle, largeArcFlag, sweepFlag) {
  3295. return new window.SVGPathSegArcAbs(undefined, x, y, r1, r2, angle, largeArcFlag, sweepFlag);
  3296. };
  3297. window.SVGPathElement.prototype.createSVGPathSegArcRel = function (x, y, r1, r2, angle, largeArcFlag, sweepFlag) {
  3298. return new window.SVGPathSegArcRel(undefined, x, y, r1, r2, angle, largeArcFlag, sweepFlag);
  3299. };
  3300. window.SVGPathElement.prototype.createSVGPathSegLinetoHorizontalAbs = function (x) {
  3301. return new window.SVGPathSegLinetoHorizontalAbs(undefined, x);
  3302. };
  3303. window.SVGPathElement.prototype.createSVGPathSegLinetoHorizontalRel = function (x) {
  3304. return new window.SVGPathSegLinetoHorizontalRel(undefined, x);
  3305. };
  3306. window.SVGPathElement.prototype.createSVGPathSegLinetoVerticalAbs = function (y) {
  3307. return new window.SVGPathSegLinetoVerticalAbs(undefined, y);
  3308. };
  3309. window.SVGPathElement.prototype.createSVGPathSegLinetoVerticalRel = function (y) {
  3310. return new window.SVGPathSegLinetoVerticalRel(undefined, y);
  3311. };
  3312. window.SVGPathElement.prototype.createSVGPathSegCurvetoCubicSmoothAbs = function (x, y, x2, y2) {
  3313. return new window.SVGPathSegCurvetoCubicSmoothAbs(undefined, x, y, x2, y2);
  3314. };
  3315. window.SVGPathElement.prototype.createSVGPathSegCurvetoCubicSmoothRel = function (x, y, x2, y2) {
  3316. return new window.SVGPathSegCurvetoCubicSmoothRel(undefined, x, y, x2, y2);
  3317. };
  3318. window.SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticSmoothAbs = function (x, y) {
  3319. return new window.SVGPathSegCurvetoQuadraticSmoothAbs(undefined, x, y);
  3320. };
  3321. window.SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticSmoothRel = function (x, y) {
  3322. return new window.SVGPathSegCurvetoQuadraticSmoothRel(undefined, x, y);
  3323. };
  3324. if (!('getPathSegAtLength' in window.SVGPathElement.prototype)) {
  3325. // Add getPathSegAtLength to SVGPathElement.
  3326. // Spec: https://www.w3.org/TR/SVG11/single-page.html#paths-__svg__SVGPathElement__getPathSegAtLength
  3327. // This polyfill requires SVGPathElement.getTotalLength to implement the distance-along-a-path algorithm.
  3328. window.SVGPathElement.prototype.getPathSegAtLength = function (distance) {
  3329. if (distance === undefined || !isFinite(distance))
  3330. throw 'Invalid arguments.';
  3331. var measurementElement = document.createElementNS('http://www.w3.org/2000/svg', 'path');
  3332. measurementElement.setAttribute('d', this.getAttribute('d'));
  3333. var lastPathSegment = measurementElement.pathSegList.numberOfItems - 1;
  3334. // If the path is empty, return 0.
  3335. if (lastPathSegment <= 0)
  3336. return 0;
  3337. do {
  3338. measurementElement.pathSegList.removeItem(lastPathSegment);
  3339. if (distance > measurementElement.getTotalLength())
  3340. break;
  3341. lastPathSegment--;
  3342. } while (lastPathSegment > 0);
  3343. return lastPathSegment;
  3344. };
  3345. }
  3346. }
  3347. if (!('SVGPathSegList' in window)) {
  3348. // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathSegList
  3349. window.SVGPathSegList = function (pathElement) {
  3350. this._pathElement = pathElement;
  3351. this._list = this._parsePath(this._pathElement.getAttribute('d'));
  3352. // Use a MutationObserver to catch changes to the path's "d" attribute.
  3353. this._mutationObserverConfig = {
  3354. attributes: true,
  3355. attributeFilter: ['d']
  3356. };
  3357. this._pathElementMutationObserver = new MutationObserver(this._updateListFromPathMutations.bind(this));
  3358. this._pathElementMutationObserver.observe(this._pathElement, this._mutationObserverConfig);
  3359. };
  3360. window.SVGPathSegList.prototype.classname = 'SVGPathSegList';
  3361. Object.defineProperty(window.SVGPathSegList.prototype, 'numberOfItems', {
  3362. get: function () {
  3363. this._checkPathSynchronizedToList();
  3364. return this._list.length;
  3365. },
  3366. enumerable: true
  3367. });
  3368. // Add the pathSegList accessors to window.SVGPathElement.
  3369. // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGAnimatedPathData
  3370. Object.defineProperty(window.SVGPathElement.prototype, 'pathSegList', {
  3371. get: function () {
  3372. if (!this._pathSegList)
  3373. this._pathSegList = new window.SVGPathSegList(this);
  3374. return this._pathSegList;
  3375. },
  3376. enumerable: true
  3377. });
  3378. // FIXME: The following are not implemented and simply return window.SVGPathElement.pathSegList.
  3379. Object.defineProperty(window.SVGPathElement.prototype, 'normalizedPathSegList', {
  3380. get: function () {
  3381. return this.pathSegList;
  3382. },
  3383. enumerable: true
  3384. });
  3385. Object.defineProperty(window.SVGPathElement.prototype, 'animatedPathSegList', {
  3386. get: function () {
  3387. return this.pathSegList;
  3388. },
  3389. enumerable: true
  3390. });
  3391. Object.defineProperty(window.SVGPathElement.prototype, 'animatedNormalizedPathSegList', {
  3392. get: function () {
  3393. return this.pathSegList;
  3394. },
  3395. enumerable: true
  3396. });
  3397. // Process any pending mutations to the path element and update the list as needed.
  3398. // This should be the first call of all public functions and is needed because
  3399. // MutationObservers are not synchronous so we can have pending asynchronous mutations.
  3400. window.SVGPathSegList.prototype._checkPathSynchronizedToList = function () {
  3401. this._updateListFromPathMutations(this._pathElementMutationObserver.takeRecords());
  3402. };
  3403. window.SVGPathSegList.prototype._updateListFromPathMutations = function (mutationRecords) {
  3404. if (!this._pathElement)
  3405. return;
  3406. var hasPathMutations = false;
  3407. mutationRecords.forEach(function (record) {
  3408. if (record.attributeName == 'd')
  3409. hasPathMutations = true;
  3410. });
  3411. if (hasPathMutations)
  3412. this._list = this._parsePath(this._pathElement.getAttribute('d'));
  3413. };
  3414. // Serialize the list and update the path's 'd' attribute.
  3415. window.SVGPathSegList.prototype._writeListToPath = function () {
  3416. this._pathElementMutationObserver.disconnect();
  3417. this._pathElement.setAttribute('d', window.SVGPathSegList._pathSegArrayAsString(this._list));
  3418. this._pathElementMutationObserver.observe(this._pathElement, this._mutationObserverConfig);
  3419. };
  3420. // When a path segment changes the list needs to be synchronized back to the path element.
  3421. window.SVGPathSegList.prototype.segmentChanged = function (pathSeg) {
  3422. this._writeListToPath();
  3423. };
  3424. window.SVGPathSegList.prototype.clear = function () {
  3425. this._checkPathSynchronizedToList();
  3426. this._list.forEach(function (pathSeg) {
  3427. pathSeg._owningPathSegList = null;
  3428. });
  3429. this._list = [];
  3430. this._writeListToPath();
  3431. };
  3432. window.SVGPathSegList.prototype.initialize = function (newItem) {
  3433. this._checkPathSynchronizedToList();
  3434. this._list = [newItem];
  3435. newItem._owningPathSegList = this;
  3436. this._writeListToPath();
  3437. return newItem;
  3438. };
  3439. window.SVGPathSegList.prototype._checkValidIndex = function (index) {
  3440. if (isNaN(index) || index < 0 || index >= this.numberOfItems)
  3441. throw 'INDEX_SIZE_ERR';
  3442. };
  3443. window.SVGPathSegList.prototype.getItem = function (index) {
  3444. this._checkPathSynchronizedToList();
  3445. this._checkValidIndex(index);
  3446. return this._list[index];
  3447. };
  3448. window.SVGPathSegList.prototype.insertItemBefore = function (newItem, index) {
  3449. this._checkPathSynchronizedToList();
  3450. // Spec: If the index is greater than or equal to numberOfItems, then the new item is appended to the end of the list.
  3451. if (index > this.numberOfItems)
  3452. index = this.numberOfItems;
  3453. if (newItem._owningPathSegList) {
  3454. // SVG2 spec says to make a copy.
  3455. newItem = newItem.clone();
  3456. }
  3457. this._list.splice(index, 0, newItem);
  3458. newItem._owningPathSegList = this;
  3459. this._writeListToPath();
  3460. return newItem;
  3461. };
  3462. window.SVGPathSegList.prototype.replaceItem = function (newItem, index) {
  3463. this._checkPathSynchronizedToList();
  3464. if (newItem._owningPathSegList) {
  3465. // SVG2 spec says to make a copy.
  3466. newItem = newItem.clone();
  3467. }
  3468. this._checkValidIndex(index);
  3469. this._list[index] = newItem;
  3470. newItem._owningPathSegList = this;
  3471. this._writeListToPath();
  3472. return newItem;
  3473. };
  3474. window.SVGPathSegList.prototype.removeItem = function (index) {
  3475. this._checkPathSynchronizedToList();
  3476. this._checkValidIndex(index);
  3477. var item = this._list[index];
  3478. this._list.splice(index, 1);
  3479. this._writeListToPath();
  3480. return item;
  3481. };
  3482. window.SVGPathSegList.prototype.appendItem = function (newItem) {
  3483. this._checkPathSynchronizedToList();
  3484. if (newItem._owningPathSegList) {
  3485. // SVG2 spec says to make a copy.
  3486. newItem = newItem.clone();
  3487. }
  3488. this._list.push(newItem);
  3489. newItem._owningPathSegList = this;
  3490. // TODO: Optimize this to just append to the existing attribute.
  3491. this._writeListToPath();
  3492. return newItem;
  3493. };
  3494. window.SVGPathSegList._pathSegArrayAsString = function (pathSegArray) {
  3495. var string = '';
  3496. var first = true;
  3497. pathSegArray.forEach(function (pathSeg) {
  3498. if (first) {
  3499. first = false;
  3500. string += pathSeg._asPathString();
  3501. }
  3502. else {
  3503. string += ' ' + pathSeg._asPathString();
  3504. }
  3505. });
  3506. return string;
  3507. };
  3508. // This closely follows SVGPathParser::parsePath from Source/core/svg/SVGPathParser.cpp.
  3509. window.SVGPathSegList.prototype._parsePath = function (string) {
  3510. if (!string || string.length == 0)
  3511. return [];
  3512. var owningPathSegList = this;
  3513. var Builder = function () {
  3514. this.pathSegList = [];
  3515. };
  3516. Builder.prototype.appendSegment = function (pathSeg) {
  3517. this.pathSegList.push(pathSeg);
  3518. };
  3519. var Source = function (string) {
  3520. this._string = string;
  3521. this._currentIndex = 0;
  3522. this._endIndex = this._string.length;
  3523. this._previousCommand = window.SVGPathSeg.PATHSEG_UNKNOWN;
  3524. this._skipOptionalSpaces();
  3525. };
  3526. Source.prototype._isCurrentSpace = function () {
  3527. var character = this._string[this._currentIndex];
  3528. return (character <= ' ' &&
  3529. (character == ' ' ||
  3530. character == '\n' ||
  3531. character == '\t' ||
  3532. character == '\r' ||
  3533. character == '\f'));
  3534. };
  3535. Source.prototype._skipOptionalSpaces = function () {
  3536. while (this._currentIndex < this._endIndex && this._isCurrentSpace())
  3537. this._currentIndex++;
  3538. return this._currentIndex < this._endIndex;
  3539. };
  3540. Source.prototype._skipOptionalSpacesOrDelimiter = function () {
  3541. if (this._currentIndex < this._endIndex &&
  3542. !this._isCurrentSpace() &&
  3543. this._string.charAt(this._currentIndex) != ',')
  3544. return false;
  3545. if (this._skipOptionalSpaces()) {
  3546. if (this._currentIndex < this._endIndex &&
  3547. this._string.charAt(this._currentIndex) == ',') {
  3548. this._currentIndex++;
  3549. this._skipOptionalSpaces();
  3550. }
  3551. }
  3552. return this._currentIndex < this._endIndex;
  3553. };
  3554. Source.prototype.hasMoreData = function () {
  3555. return this._currentIndex < this._endIndex;
  3556. };
  3557. Source.prototype.peekSegmentType = function () {
  3558. var lookahead = this._string[this._currentIndex];
  3559. return this._pathSegTypeFromChar(lookahead);
  3560. };
  3561. Source.prototype._pathSegTypeFromChar = function (lookahead) {
  3562. switch (lookahead) {
  3563. case 'Z':
  3564. case 'z':
  3565. return window.SVGPathSeg.PATHSEG_CLOSEPATH;
  3566. case 'M':
  3567. return window.SVGPathSeg.PATHSEG_MOVETO_ABS;
  3568. case 'm':
  3569. return window.SVGPathSeg.PATHSEG_MOVETO_REL;
  3570. case 'L':
  3571. return window.SVGPathSeg.PATHSEG_LINETO_ABS;
  3572. case 'l':
  3573. return window.SVGPathSeg.PATHSEG_LINETO_REL;
  3574. case 'C':
  3575. return window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS;
  3576. case 'c':
  3577. return window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL;
  3578. case 'Q':
  3579. return window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS;
  3580. case 'q':
  3581. return window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL;
  3582. case 'A':
  3583. return window.SVGPathSeg.PATHSEG_ARC_ABS;
  3584. case 'a':
  3585. return window.SVGPathSeg.PATHSEG_ARC_REL;
  3586. case 'H':
  3587. return window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS;
  3588. case 'h':
  3589. return window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL;
  3590. case 'V':
  3591. return window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS;
  3592. case 'v':
  3593. return window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL;
  3594. case 'S':
  3595. return window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS;
  3596. case 's':
  3597. return window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL;
  3598. case 'T':
  3599. return window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS;
  3600. case 't':
  3601. return window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL;
  3602. default:
  3603. return window.SVGPathSeg.PATHSEG_UNKNOWN;
  3604. }
  3605. };
  3606. Source.prototype._nextCommandHelper = function (lookahead, previousCommand) {
  3607. // Check for remaining coordinates in the current command.
  3608. if ((lookahead == '+' ||
  3609. lookahead == '-' ||
  3610. lookahead == '.' ||
  3611. (lookahead >= '0' && lookahead <= '9')) &&
  3612. previousCommand != window.SVGPathSeg.PATHSEG_CLOSEPATH) {
  3613. if (previousCommand == window.SVGPathSeg.PATHSEG_MOVETO_ABS)
  3614. return window.SVGPathSeg.PATHSEG_LINETO_ABS;
  3615. if (previousCommand == window.SVGPathSeg.PATHSEG_MOVETO_REL)
  3616. return window.SVGPathSeg.PATHSEG_LINETO_REL;
  3617. return previousCommand;
  3618. }
  3619. return window.SVGPathSeg.PATHSEG_UNKNOWN;
  3620. };
  3621. Source.prototype.initialCommandIsMoveTo = function () {
  3622. // If the path is empty it is still valid, so return true.
  3623. if (!this.hasMoreData())
  3624. return true;
  3625. var command = this.peekSegmentType();
  3626. // Path must start with moveTo.
  3627. return (command == window.SVGPathSeg.PATHSEG_MOVETO_ABS ||
  3628. command == window.SVGPathSeg.PATHSEG_MOVETO_REL);
  3629. };
  3630. // Parse a number from an SVG path. This very closely follows genericParseNumber(...) from Source/core/svg/SVGParserUtilities.cpp.
  3631. // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-PathDataBNF
  3632. Source.prototype._parseNumber = function () {
  3633. var exponent = 0;
  3634. var integer = 0;
  3635. var frac = 1;
  3636. var decimal = 0;
  3637. var sign = 1;
  3638. var expsign = 1;
  3639. var startIndex = this._currentIndex;
  3640. this._skipOptionalSpaces();
  3641. // Read the sign.
  3642. if (this._currentIndex < this._endIndex &&
  3643. this._string.charAt(this._currentIndex) == '+')
  3644. this._currentIndex++;
  3645. else if (this._currentIndex < this._endIndex &&
  3646. this._string.charAt(this._currentIndex) == '-') {
  3647. this._currentIndex++;
  3648. sign = -1;
  3649. }
  3650. if (this._currentIndex == this._endIndex ||
  3651. ((this._string.charAt(this._currentIndex) < '0' ||
  3652. this._string.charAt(this._currentIndex) > '9') &&
  3653. this._string.charAt(this._currentIndex) != '.'))
  3654. // The first character of a number must be one of [0-9+-.].
  3655. return undefined;
  3656. // Read the integer part, build right-to-left.
  3657. var startIntPartIndex = this._currentIndex;
  3658. while (this._currentIndex < this._endIndex &&
  3659. this._string.charAt(this._currentIndex) >= '0' &&
  3660. this._string.charAt(this._currentIndex) <= '9')
  3661. this._currentIndex++; // Advance to first non-digit.
  3662. if (this._currentIndex != startIntPartIndex) {
  3663. var scanIntPartIndex = this._currentIndex - 1;
  3664. var multiplier = 1;
  3665. while (scanIntPartIndex >= startIntPartIndex) {
  3666. integer +=
  3667. multiplier * (this._string.charAt(scanIntPartIndex--) - '0');
  3668. multiplier *= 10;
  3669. }
  3670. }
  3671. // Read the decimals.
  3672. if (this._currentIndex < this._endIndex &&
  3673. this._string.charAt(this._currentIndex) == '.') {
  3674. this._currentIndex++;
  3675. // There must be a least one digit following the .
  3676. if (this._currentIndex >= this._endIndex ||
  3677. this._string.charAt(this._currentIndex) < '0' ||
  3678. this._string.charAt(this._currentIndex) > '9')
  3679. return undefined;
  3680. while (this._currentIndex < this._endIndex &&
  3681. this._string.charAt(this._currentIndex) >= '0' &&
  3682. this._string.charAt(this._currentIndex) <= '9') {
  3683. frac *= 10;
  3684. decimal += (this._string.charAt(this._currentIndex) - '0') / frac;
  3685. this._currentIndex += 1;
  3686. }
  3687. }
  3688. // Read the exponent part.
  3689. if (this._currentIndex != startIndex &&
  3690. this._currentIndex + 1 < this._endIndex &&
  3691. (this._string.charAt(this._currentIndex) == 'e' ||
  3692. this._string.charAt(this._currentIndex) == 'E') &&
  3693. this._string.charAt(this._currentIndex + 1) != 'x' &&
  3694. this._string.charAt(this._currentIndex + 1) != 'm') {
  3695. this._currentIndex++;
  3696. // Read the sign of the exponent.
  3697. if (this._string.charAt(this._currentIndex) == '+') {
  3698. this._currentIndex++;
  3699. }
  3700. else if (this._string.charAt(this._currentIndex) == '-') {
  3701. this._currentIndex++;
  3702. expsign = -1;
  3703. }
  3704. // There must be an exponent.
  3705. if (this._currentIndex >= this._endIndex ||
  3706. this._string.charAt(this._currentIndex) < '0' ||
  3707. this._string.charAt(this._currentIndex) > '9')
  3708. return undefined;
  3709. while (this._currentIndex < this._endIndex &&
  3710. this._string.charAt(this._currentIndex) >= '0' &&
  3711. this._string.charAt(this._currentIndex) <= '9') {
  3712. exponent *= 10;
  3713. exponent += this._string.charAt(this._currentIndex) - '0';
  3714. this._currentIndex++;
  3715. }
  3716. }
  3717. var number = integer + decimal;
  3718. number *= sign;
  3719. if (exponent)
  3720. number *= Math.pow(10, expsign * exponent);
  3721. if (startIndex == this._currentIndex)
  3722. return undefined;
  3723. this._skipOptionalSpacesOrDelimiter();
  3724. return number;
  3725. };
  3726. Source.prototype._parseArcFlag = function () {
  3727. if (this._currentIndex >= this._endIndex)
  3728. return undefined;
  3729. var flag = false;
  3730. var flagChar = this._string.charAt(this._currentIndex++);
  3731. if (flagChar == '0')
  3732. flag = false;
  3733. else if (flagChar == '1')
  3734. flag = true;
  3735. else
  3736. return undefined;
  3737. this._skipOptionalSpacesOrDelimiter();
  3738. return flag;
  3739. };
  3740. Source.prototype.parseSegment = function () {
  3741. var lookahead = this._string[this._currentIndex];
  3742. var command = this._pathSegTypeFromChar(lookahead);
  3743. if (command == window.SVGPathSeg.PATHSEG_UNKNOWN) {
  3744. // Possibly an implicit command. Not allowed if this is the first command.
  3745. if (this._previousCommand == window.SVGPathSeg.PATHSEG_UNKNOWN)
  3746. return null;
  3747. command = this._nextCommandHelper(lookahead, this._previousCommand);
  3748. if (command == window.SVGPathSeg.PATHSEG_UNKNOWN)
  3749. return null;
  3750. }
  3751. else {
  3752. this._currentIndex++;
  3753. }
  3754. this._previousCommand = command;
  3755. switch (command) {
  3756. case window.SVGPathSeg.PATHSEG_MOVETO_REL:
  3757. return new window.SVGPathSegMovetoRel(owningPathSegList, this._parseNumber(), this._parseNumber());
  3758. case window.SVGPathSeg.PATHSEG_MOVETO_ABS:
  3759. return new window.SVGPathSegMovetoAbs(owningPathSegList, this._parseNumber(), this._parseNumber());
  3760. case window.SVGPathSeg.PATHSEG_LINETO_REL:
  3761. return new window.SVGPathSegLinetoRel(owningPathSegList, this._parseNumber(), this._parseNumber());
  3762. case window.SVGPathSeg.PATHSEG_LINETO_ABS:
  3763. return new window.SVGPathSegLinetoAbs(owningPathSegList, this._parseNumber(), this._parseNumber());
  3764. case window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL:
  3765. return new window.SVGPathSegLinetoHorizontalRel(owningPathSegList, this._parseNumber());
  3766. case window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS:
  3767. return new window.SVGPathSegLinetoHorizontalAbs(owningPathSegList, this._parseNumber());
  3768. case window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL:
  3769. return new window.SVGPathSegLinetoVerticalRel(owningPathSegList, this._parseNumber());
  3770. case window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS:
  3771. return new window.SVGPathSegLinetoVerticalAbs(owningPathSegList, this._parseNumber());
  3772. case window.SVGPathSeg.PATHSEG_CLOSEPATH:
  3773. this._skipOptionalSpaces();
  3774. return new window.SVGPathSegClosePath(owningPathSegList);
  3775. case window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL:
  3776. var points = {
  3777. x1: this._parseNumber(),
  3778. y1: this._parseNumber(),
  3779. x2: this._parseNumber(),
  3780. y2: this._parseNumber(),
  3781. x: this._parseNumber(),
  3782. y: this._parseNumber()
  3783. };
  3784. return new window.SVGPathSegCurvetoCubicRel(owningPathSegList, points.x, points.y, points.x1, points.y1, points.x2, points.y2);
  3785. case window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS:
  3786. var points = {
  3787. x1: this._parseNumber(),
  3788. y1: this._parseNumber(),
  3789. x2: this._parseNumber(),
  3790. y2: this._parseNumber(),
  3791. x: this._parseNumber(),
  3792. y: this._parseNumber()
  3793. };
  3794. return new window.SVGPathSegCurvetoCubicAbs(owningPathSegList, points.x, points.y, points.x1, points.y1, points.x2, points.y2);
  3795. case window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL:
  3796. var points = {
  3797. x2: this._parseNumber(),
  3798. y2: this._parseNumber(),
  3799. x: this._parseNumber(),
  3800. y: this._parseNumber()
  3801. };
  3802. return new window.SVGPathSegCurvetoCubicSmoothRel(owningPathSegList, points.x, points.y, points.x2, points.y2);
  3803. case window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS:
  3804. var points = {
  3805. x2: this._parseNumber(),
  3806. y2: this._parseNumber(),
  3807. x: this._parseNumber(),
  3808. y: this._parseNumber()
  3809. };
  3810. return new window.SVGPathSegCurvetoCubicSmoothAbs(owningPathSegList, points.x, points.y, points.x2, points.y2);
  3811. case window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL:
  3812. var points = {
  3813. x1: this._parseNumber(),
  3814. y1: this._parseNumber(),
  3815. x: this._parseNumber(),
  3816. y: this._parseNumber()
  3817. };
  3818. return new window.SVGPathSegCurvetoQuadraticRel(owningPathSegList, points.x, points.y, points.x1, points.y1);
  3819. case window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS:
  3820. var points = {
  3821. x1: this._parseNumber(),
  3822. y1: this._parseNumber(),
  3823. x: this._parseNumber(),
  3824. y: this._parseNumber()
  3825. };
  3826. return new window.SVGPathSegCurvetoQuadraticAbs(owningPathSegList, points.x, points.y, points.x1, points.y1);
  3827. case window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL:
  3828. return new window.SVGPathSegCurvetoQuadraticSmoothRel(owningPathSegList, this._parseNumber(), this._parseNumber());
  3829. case window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS:
  3830. return new window.SVGPathSegCurvetoQuadraticSmoothAbs(owningPathSegList, this._parseNumber(), this._parseNumber());
  3831. case window.SVGPathSeg.PATHSEG_ARC_REL:
  3832. var points = {
  3833. x1: this._parseNumber(),
  3834. y1: this._parseNumber(),
  3835. arcAngle: this._parseNumber(),
  3836. arcLarge: this._parseArcFlag(),
  3837. arcSweep: this._parseArcFlag(),
  3838. x: this._parseNumber(),
  3839. y: this._parseNumber()
  3840. };
  3841. return new window.SVGPathSegArcRel(owningPathSegList, points.x, points.y, points.x1, points.y1, points.arcAngle, points.arcLarge, points.arcSweep);
  3842. case window.SVGPathSeg.PATHSEG_ARC_ABS:
  3843. var points = {
  3844. x1: this._parseNumber(),
  3845. y1: this._parseNumber(),
  3846. arcAngle: this._parseNumber(),
  3847. arcLarge: this._parseArcFlag(),
  3848. arcSweep: this._parseArcFlag(),
  3849. x: this._parseNumber(),
  3850. y: this._parseNumber()
  3851. };
  3852. return new window.SVGPathSegArcAbs(owningPathSegList, points.x, points.y, points.x1, points.y1, points.arcAngle, points.arcLarge, points.arcSweep);
  3853. default:
  3854. throw 'Unknown path seg type.';
  3855. }
  3856. };
  3857. var builder = new Builder();
  3858. var source = new Source(string);
  3859. if (!source.initialCommandIsMoveTo())
  3860. return [];
  3861. while (source.hasMoreData()) {
  3862. var pathSeg = source.parseSegment();
  3863. if (!pathSeg)
  3864. return [];
  3865. builder.appendSegment(pathSeg);
  3866. }
  3867. return builder.pathSegList;
  3868. };
  3869. }
  3870. })();
  3871. // String.padEnd polyfill for IE11
  3872. //
  3873. // https://github.com/uxitten/polyfill/blob/master/string.polyfill.js
  3874. // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padEnd
  3875. if (!String.prototype.padEnd) {
  3876. String.prototype.padEnd = function padEnd(targetLength, padString) {
  3877. targetLength = targetLength >> 0; //floor if number or convert non-number to 0;
  3878. padString = String(typeof padString !== 'undefined' ? padString : ' ');
  3879. if (this.length > targetLength) {
  3880. return String(this);
  3881. }
  3882. else {
  3883. targetLength = targetLength - this.length;
  3884. if (targetLength > padString.length) {
  3885. padString += padString.repeat(targetLength / padString.length); //append to original to ensure we are longer than needed
  3886. }
  3887. return String(this) + padString.slice(0, targetLength);
  3888. }
  3889. };
  3890. }
  3891. // Object.assign polyfill for IE11
  3892. // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#Polyfill
  3893. if (typeof Object.assign !== 'function') {
  3894. // Must be writable: true, enumerable: false, configurable: true
  3895. Object.defineProperty(Object, 'assign', {
  3896. value: function assign(target, varArgs) {
  3897. if (target === null || target === undefined) {
  3898. throw new TypeError('Cannot convert undefined or null to object');
  3899. }
  3900. var to = Object(target);
  3901. for (var index = 1; index < arguments.length; index++) {
  3902. var nextSource = arguments[index];
  3903. if (nextSource !== null && nextSource !== undefined) {
  3904. for (var nextKey in nextSource) {
  3905. // Avoid bugs when hasOwnProperty is shadowed
  3906. if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
  3907. to[nextKey] = nextSource[nextKey];
  3908. }
  3909. }
  3910. }
  3911. }
  3912. return to;
  3913. },
  3914. writable: true,
  3915. configurable: true
  3916. });
  3917. }
  3918. /* jshint ignore:end */
  3919. Chart.prototype.axis = function () { };
  3920. Chart.prototype.axis.labels = function (labels) {
  3921. var $$ = this.internal;
  3922. if (arguments.length) {
  3923. Object.keys(labels).forEach(function (axisId) {
  3924. $$.axis.setLabelText(axisId, labels[axisId]);
  3925. });
  3926. $$.axis.updateLabels();
  3927. }
  3928. // TODO: return some values?
  3929. };
  3930. Chart.prototype.axis.max = function (max) {
  3931. var $$ = this.internal, config = $$.config;
  3932. if (arguments.length) {
  3933. if (typeof max === 'object') {
  3934. if (isValue(max.x)) {
  3935. config.axis_x_max = max.x;
  3936. }
  3937. if (isValue(max.y)) {
  3938. config.axis_y_max = max.y;
  3939. }
  3940. if (isValue(max.y2)) {
  3941. config.axis_y2_max = max.y2;
  3942. }
  3943. }
  3944. else {
  3945. config.axis_y_max = config.axis_y2_max = max;
  3946. }
  3947. $$.redraw({ withUpdateOrgXDomain: true, withUpdateXDomain: true });
  3948. }
  3949. else {
  3950. return {
  3951. x: config.axis_x_max,
  3952. y: config.axis_y_max,
  3953. y2: config.axis_y2_max
  3954. };
  3955. }
  3956. };
  3957. Chart.prototype.axis.min = function (min) {
  3958. var $$ = this.internal, config = $$.config;
  3959. if (arguments.length) {
  3960. if (typeof min === 'object') {
  3961. if (isValue(min.x)) {
  3962. config.axis_x_min = min.x;
  3963. }
  3964. if (isValue(min.y)) {
  3965. config.axis_y_min = min.y;
  3966. }
  3967. if (isValue(min.y2)) {
  3968. config.axis_y2_min = min.y2;
  3969. }
  3970. }
  3971. else {
  3972. config.axis_y_min = config.axis_y2_min = min;
  3973. }
  3974. $$.redraw({ withUpdateOrgXDomain: true, withUpdateXDomain: true });
  3975. }
  3976. else {
  3977. return {
  3978. x: config.axis_x_min,
  3979. y: config.axis_y_min,
  3980. y2: config.axis_y2_min
  3981. };
  3982. }
  3983. };
  3984. Chart.prototype.axis.range = function (range) {
  3985. if (arguments.length) {
  3986. if (isDefined(range.max)) {
  3987. this.axis.max(range.max);
  3988. }
  3989. if (isDefined(range.min)) {
  3990. this.axis.min(range.min);
  3991. }
  3992. }
  3993. else {
  3994. return {
  3995. max: this.axis.max(),
  3996. min: this.axis.min()
  3997. };
  3998. }
  3999. };
  4000. Chart.prototype.axis.types = function (types) {
  4001. var $$ = this.internal;
  4002. if (types === undefined) {
  4003. return {
  4004. y: $$.config.axis_y_type,
  4005. y2: $$.config.axis_y2_type
  4006. };
  4007. }
  4008. else {
  4009. if (isDefined(types.y)) {
  4010. $$.config.axis_y_type = types.y;
  4011. }
  4012. if (isDefined(types.y2)) {
  4013. $$.config.axis_y2_type = types.y2;
  4014. }
  4015. $$.updateScales();
  4016. $$.redraw();
  4017. }
  4018. };
  4019. Chart.prototype.category = function (i, category) {
  4020. var $$ = this.internal, config = $$.config;
  4021. if (arguments.length > 1) {
  4022. config.axis_x_categories[i] = category;
  4023. $$.redraw();
  4024. }
  4025. return config.axis_x_categories[i];
  4026. };
  4027. Chart.prototype.categories = function (categories) {
  4028. var $$ = this.internal, config = $$.config;
  4029. if (!arguments.length) {
  4030. return config.axis_x_categories;
  4031. }
  4032. config.axis_x_categories = categories;
  4033. $$.redraw();
  4034. return config.axis_x_categories;
  4035. };
  4036. Chart.prototype.resize = function (size) {
  4037. var $$ = this.internal, config = $$.config;
  4038. config.size_width = size ? size.width : null;
  4039. config.size_height = size ? size.height : null;
  4040. this.flush();
  4041. };
  4042. Chart.prototype.flush = function () {
  4043. var $$ = this.internal;
  4044. $$.updateAndRedraw({
  4045. withLegend: true,
  4046. withTransition: false,
  4047. withTransitionForTransform: false
  4048. });
  4049. };
  4050. Chart.prototype.destroy = function () {
  4051. var $$ = this.internal;
  4052. window.clearInterval($$.intervalForObserveInserted);
  4053. if ($$.resizeTimeout !== undefined) {
  4054. window.clearTimeout($$.resizeTimeout);
  4055. }
  4056. window.removeEventListener('resize', $$.resizeIfElementDisplayed);
  4057. // Removes the inner resize functions
  4058. $$.resizeFunction.remove();
  4059. // Unbinds from the window focus event
  4060. $$.unbindWindowFocus();
  4061. $$.selectChart.classed('c3', false).html('');
  4062. // MEMO: this is needed because the reference of some elements will not be released, then memory leak will happen.
  4063. Object.keys($$).forEach(function (key) {
  4064. $$[key] = null;
  4065. });
  4066. return null;
  4067. };
  4068. // TODO: fix
  4069. Chart.prototype.color = function (id) {
  4070. var $$ = this.internal;
  4071. return $$.color(id); // more patterns
  4072. };
  4073. Chart.prototype.data = function (targetIds) {
  4074. var targets = this.internal.data.targets;
  4075. return typeof targetIds === 'undefined'
  4076. ? targets
  4077. : targets.filter(function (t) {
  4078. return [].concat(targetIds).indexOf(t.id) >= 0;
  4079. });
  4080. };
  4081. Chart.prototype.data.shown = function (targetIds) {
  4082. return this.internal.filterTargetsToShow(this.data(targetIds));
  4083. };
  4084. /**
  4085. * Get values of the data loaded in the chart.
  4086. *
  4087. * @param {String|Array} targetId This API returns the value of specified target.
  4088. * @param flat
  4089. * @return {Array} Data values
  4090. */
  4091. Chart.prototype.data.values = function (targetId, flat) {
  4092. if (flat === void 0) { flat = true; }
  4093. var values = null;
  4094. if (targetId) {
  4095. var targets = this.data(targetId);
  4096. if (targets && isArray(targets)) {
  4097. values = targets.reduce(function (ret, v) {
  4098. var dataValue = v.values.map(function (d) { return d.value; });
  4099. if (flat) {
  4100. ret = ret.concat(dataValue);
  4101. }
  4102. else {
  4103. ret.push(dataValue);
  4104. }
  4105. return ret;
  4106. }, []);
  4107. }
  4108. }
  4109. return values;
  4110. };
  4111. Chart.prototype.data.names = function (names) {
  4112. this.internal.clearLegendItemTextBoxCache();
  4113. return this.internal.updateDataAttributes('names', names);
  4114. };
  4115. Chart.prototype.data.colors = function (colors) {
  4116. return this.internal.updateDataAttributes('colors', colors);
  4117. };
  4118. Chart.prototype.data.axes = function (axes) {
  4119. return this.internal.updateDataAttributes('axes', axes);
  4120. };
  4121. Chart.prototype.data.stackNormalized = function (normalized) {
  4122. if (normalized === undefined) {
  4123. return this.internal.isStackNormalized();
  4124. }
  4125. this.internal.config.data_stack_normalize = !!normalized;
  4126. this.internal.redraw();
  4127. };
  4128. Chart.prototype.donut = function () { };
  4129. Chart.prototype.donut.padAngle = function (padAngle) {
  4130. if (padAngle === undefined) {
  4131. return this.internal.config.donut_padAngle;
  4132. }
  4133. this.internal.config.donut_padAngle = padAngle;
  4134. this.flush();
  4135. };
  4136. Chart.prototype.flow = function (args) {
  4137. var $$ = this.internal, targets, data, notfoundIds = [], orgDataCount = $$.getMaxDataCount(), dataCount, domain, baseTarget, baseValue, length = 0, tail = 0, diff, to;
  4138. if (args.json) {
  4139. data = $$.convertJsonToData(args.json, args.keys);
  4140. }
  4141. else if (args.rows) {
  4142. data = $$.convertRowsToData(args.rows);
  4143. }
  4144. else if (args.columns) {
  4145. data = $$.convertColumnsToData(args.columns);
  4146. }
  4147. else {
  4148. return;
  4149. }
  4150. targets = $$.convertDataToTargets(data, true);
  4151. // Update/Add data
  4152. $$.data.targets.forEach(function (t) {
  4153. var found = false, i, j;
  4154. for (i = 0; i < targets.length; i++) {
  4155. if (t.id === targets[i].id) {
  4156. found = true;
  4157. if (t.values[t.values.length - 1]) {
  4158. tail = t.values[t.values.length - 1].index + 1;
  4159. }
  4160. length = targets[i].values.length;
  4161. for (j = 0; j < length; j++) {
  4162. targets[i].values[j].index = tail + j;
  4163. if (!$$.isTimeSeries()) {
  4164. targets[i].values[j].x = tail + j;
  4165. }
  4166. }
  4167. t.values = t.values.concat(targets[i].values);
  4168. targets.splice(i, 1);
  4169. break;
  4170. }
  4171. }
  4172. if (!found) {
  4173. notfoundIds.push(t.id);
  4174. }
  4175. });
  4176. // Append null for not found targets
  4177. $$.data.targets.forEach(function (t) {
  4178. var i, j;
  4179. for (i = 0; i < notfoundIds.length; i++) {
  4180. if (t.id === notfoundIds[i]) {
  4181. tail = t.values[t.values.length - 1].index + 1;
  4182. for (j = 0; j < length; j++) {
  4183. t.values.push({
  4184. id: t.id,
  4185. index: tail + j,
  4186. x: $$.isTimeSeries() ? $$.getOtherTargetX(tail + j) : tail + j,
  4187. value: null
  4188. });
  4189. }
  4190. }
  4191. }
  4192. });
  4193. // Generate null values for new target
  4194. if ($$.data.targets.length) {
  4195. targets.forEach(function (t) {
  4196. var i, missing = [];
  4197. for (i = $$.data.targets[0].values[0].index; i < tail; i++) {
  4198. missing.push({
  4199. id: t.id,
  4200. index: i,
  4201. x: $$.isTimeSeries() ? $$.getOtherTargetX(i) : i,
  4202. value: null
  4203. });
  4204. }
  4205. t.values.forEach(function (v) {
  4206. v.index += tail;
  4207. if (!$$.isTimeSeries()) {
  4208. v.x += tail;
  4209. }
  4210. });
  4211. t.values = missing.concat(t.values);
  4212. });
  4213. }
  4214. $$.data.targets = $$.data.targets.concat(targets); // add remained
  4215. // check data count because behavior needs to change when it's only one
  4216. dataCount = $$.getMaxDataCount();
  4217. baseTarget = $$.data.targets[0];
  4218. baseValue = baseTarget.values[0];
  4219. // Update length to flow if needed
  4220. if (isDefined(args.to)) {
  4221. length = 0;
  4222. to = $$.isTimeSeries() ? $$.parseDate(args.to) : args.to;
  4223. baseTarget.values.forEach(function (v) {
  4224. if (v.x < to) {
  4225. length++;
  4226. }
  4227. });
  4228. }
  4229. else if (isDefined(args.length)) {
  4230. length = args.length;
  4231. }
  4232. // If only one data, update the domain to flow from left edge of the chart
  4233. if (!orgDataCount) {
  4234. if ($$.isTimeSeries()) {
  4235. if (baseTarget.values.length > 1) {
  4236. diff = baseTarget.values[baseTarget.values.length - 1].x - baseValue.x;
  4237. }
  4238. else {
  4239. diff = baseValue.x - $$.getXDomain($$.data.targets)[0];
  4240. }
  4241. }
  4242. else {
  4243. diff = 1;
  4244. }
  4245. domain = [baseValue.x - diff, baseValue.x];
  4246. $$.updateXDomain(null, true, true, false, domain);
  4247. }
  4248. else if (orgDataCount === 1) {
  4249. if ($$.isTimeSeries()) {
  4250. diff =
  4251. (baseTarget.values[baseTarget.values.length - 1].x - baseValue.x) / 2;
  4252. domain = [new Date(+baseValue.x - diff), new Date(+baseValue.x + diff)];
  4253. $$.updateXDomain(null, true, true, false, domain);
  4254. }
  4255. }
  4256. // Set targets
  4257. $$.updateTargets($$.data.targets);
  4258. // Redraw with new targets
  4259. $$.redraw({
  4260. flow: {
  4261. index: baseValue.index,
  4262. length: length,
  4263. duration: isValue(args.duration)
  4264. ? args.duration
  4265. : $$.config.transition_duration,
  4266. done: args.done,
  4267. orgDataCount: orgDataCount
  4268. },
  4269. withLegend: true,
  4270. withTransition: orgDataCount > 1,
  4271. withTrimXDomain: false,
  4272. withUpdateXAxis: true
  4273. });
  4274. };
  4275. ChartInternal.prototype.generateFlow = function (args) {
  4276. var $$ = this, config = $$.config, d3 = $$.d3;
  4277. return function () {
  4278. var targets = args.targets, flow = args.flow, drawBar = args.drawBar, drawLine = args.drawLine, drawArea = args.drawArea, cx = args.cx, cy = args.cy, xv = args.xv, xForText = args.xForText, yForText = args.yForText, duration = args.duration;
  4279. var translateX, scaleX = 1, transform, flowIndex = flow.index, flowLength = flow.length, flowStart = $$.getValueOnIndex($$.data.targets[0].values, flowIndex), flowEnd = $$.getValueOnIndex($$.data.targets[0].values, flowIndex + flowLength), orgDomain = $$.x.domain(), domain, durationForFlow = flow.duration || duration, done = flow.done || function () { }, wait = $$.generateWait();
  4280. var xgrid, xgridLines, mainRegion, mainText, mainBar, mainLine, mainArea, mainCircle;
  4281. // set flag
  4282. $$.flowing = true;
  4283. // remove head data after rendered
  4284. $$.data.targets.forEach(function (d) {
  4285. d.values.splice(0, flowLength);
  4286. });
  4287. // update x domain to generate axis elements for flow
  4288. domain = $$.updateXDomain(targets, true, true);
  4289. // update elements related to x scale
  4290. if ($$.updateXGrid) {
  4291. $$.updateXGrid(true);
  4292. }
  4293. xgrid = $$.xgrid || d3.selectAll([]); // xgrid needs to be obtained after updateXGrid
  4294. xgridLines = $$.xgridLines || d3.selectAll([]);
  4295. mainRegion = $$.mainRegion || d3.selectAll([]);
  4296. mainText = $$.mainText || d3.selectAll([]);
  4297. mainBar = $$.mainBar || d3.selectAll([]);
  4298. mainLine = $$.mainLine || d3.selectAll([]);
  4299. mainArea = $$.mainArea || d3.selectAll([]);
  4300. mainCircle = $$.mainCircle || d3.selectAll([]);
  4301. // generate transform to flow
  4302. if (!flow.orgDataCount) {
  4303. // if empty
  4304. if ($$.data.targets[0].values.length !== 1) {
  4305. translateX = $$.x(orgDomain[0]) - $$.x(domain[0]);
  4306. }
  4307. else {
  4308. if ($$.isTimeSeries()) {
  4309. flowStart = $$.getValueOnIndex($$.data.targets[0].values, 0);
  4310. flowEnd = $$.getValueOnIndex($$.data.targets[0].values, $$.data.targets[0].values.length - 1);
  4311. translateX = $$.x(flowStart.x) - $$.x(flowEnd.x);
  4312. }
  4313. else {
  4314. translateX = diffDomain(domain) / 2;
  4315. }
  4316. }
  4317. }
  4318. else if (flow.orgDataCount === 1 ||
  4319. (flowStart && flowStart.x) === (flowEnd && flowEnd.x)) {
  4320. translateX = $$.x(orgDomain[0]) - $$.x(domain[0]);
  4321. }
  4322. else {
  4323. if ($$.isTimeSeries()) {
  4324. translateX = $$.x(orgDomain[0]) - $$.x(domain[0]);
  4325. }
  4326. else {
  4327. translateX = $$.x(flowStart.x) - $$.x(flowEnd.x);
  4328. }
  4329. }
  4330. scaleX = diffDomain(orgDomain) / diffDomain(domain);
  4331. transform = 'translate(' + translateX + ',0) scale(' + scaleX + ',1)';
  4332. $$.hideXGridFocus();
  4333. var flowTransition = d3
  4334. .transition()
  4335. .ease(d3.easeLinear)
  4336. .duration(durationForFlow);
  4337. wait.add($$.xAxis($$.axes.x, flowTransition));
  4338. wait.add(mainBar.transition(flowTransition).attr('transform', transform));
  4339. wait.add(mainLine.transition(flowTransition).attr('transform', transform));
  4340. wait.add(mainArea.transition(flowTransition).attr('transform', transform));
  4341. wait.add(mainCircle.transition(flowTransition).attr('transform', transform));
  4342. wait.add(mainText.transition(flowTransition).attr('transform', transform));
  4343. wait.add(mainRegion
  4344. .filter($$.isRegionOnX)
  4345. .transition(flowTransition)
  4346. .attr('transform', transform));
  4347. wait.add(xgrid.transition(flowTransition).attr('transform', transform));
  4348. wait.add(xgridLines.transition(flowTransition).attr('transform', transform));
  4349. wait(function () {
  4350. var i, shapes = [], texts = [];
  4351. // remove flowed elements
  4352. if (flowLength) {
  4353. for (i = 0; i < flowLength; i++) {
  4354. shapes.push('.' + CLASS.shape + '-' + (flowIndex + i));
  4355. texts.push('.' + CLASS.text + '-' + (flowIndex + i));
  4356. }
  4357. $$.svg
  4358. .selectAll('.' + CLASS.shapes)
  4359. .selectAll(shapes)
  4360. .remove();
  4361. $$.svg
  4362. .selectAll('.' + CLASS.texts)
  4363. .selectAll(texts)
  4364. .remove();
  4365. $$.svg.select('.' + CLASS.xgrid).remove();
  4366. }
  4367. // draw again for removing flowed elements and reverting attr
  4368. xgrid
  4369. .attr('transform', null)
  4370. .attr('x1', $$.xgridAttr.x1)
  4371. .attr('x2', $$.xgridAttr.x2)
  4372. .attr('y1', $$.xgridAttr.y1)
  4373. .attr('y2', $$.xgridAttr.y2)
  4374. .style('opacity', $$.xgridAttr.opacity);
  4375. xgridLines.attr('transform', null);
  4376. xgridLines
  4377. .select('line')
  4378. .attr('x1', config.axis_rotated ? 0 : xv)
  4379. .attr('x2', config.axis_rotated ? $$.width : xv);
  4380. xgridLines
  4381. .select('text')
  4382. .attr('x', config.axis_rotated ? $$.width : 0)
  4383. .attr('y', xv);
  4384. mainBar.attr('transform', null).attr('d', drawBar);
  4385. mainLine.attr('transform', null).attr('d', drawLine);
  4386. mainArea.attr('transform', null).attr('d', drawArea);
  4387. mainCircle
  4388. .attr('transform', null)
  4389. .attr('cx', cx)
  4390. .attr('cy', cy);
  4391. mainText
  4392. .attr('transform', null)
  4393. .attr('x', xForText)
  4394. .attr('y', yForText)
  4395. .style('fill-opacity', $$.opacityForText.bind($$));
  4396. mainRegion.attr('transform', null);
  4397. mainRegion
  4398. .filter($$.isRegionOnX)
  4399. .attr('x', $$.regionX.bind($$))
  4400. .attr('width', $$.regionWidth.bind($$));
  4401. // callback for end of flow
  4402. done();
  4403. $$.flowing = false;
  4404. });
  4405. };
  4406. };
  4407. Chart.prototype.focus = function (targetIds) {
  4408. var $$ = this.internal, candidates;
  4409. targetIds = $$.mapToTargetIds(targetIds);
  4410. (candidates = $$.svg.selectAll($$.selectorTargets(targetIds.filter($$.isTargetToShow, $$)))),
  4411. this.revert();
  4412. this.defocus();
  4413. candidates.classed(CLASS.focused, true).classed(CLASS.defocused, false);
  4414. if ($$.hasArcType()) {
  4415. $$.expandArc(targetIds);
  4416. }
  4417. $$.toggleFocusLegend(targetIds, true);
  4418. $$.focusedTargetIds = targetIds;
  4419. $$.defocusedTargetIds = $$.defocusedTargetIds.filter(function (id) {
  4420. return targetIds.indexOf(id) < 0;
  4421. });
  4422. };
  4423. Chart.prototype.defocus = function (targetIds) {
  4424. var $$ = this.internal, candidates;
  4425. targetIds = $$.mapToTargetIds(targetIds);
  4426. (candidates = $$.svg.selectAll($$.selectorTargets(targetIds.filter($$.isTargetToShow, $$)))),
  4427. candidates.classed(CLASS.focused, false).classed(CLASS.defocused, true);
  4428. if ($$.hasArcType()) {
  4429. $$.unexpandArc(targetIds);
  4430. }
  4431. $$.toggleFocusLegend(targetIds, false);
  4432. $$.focusedTargetIds = $$.focusedTargetIds.filter(function (id) {
  4433. return targetIds.indexOf(id) < 0;
  4434. });
  4435. $$.defocusedTargetIds = targetIds;
  4436. };
  4437. Chart.prototype.revert = function (targetIds) {
  4438. var $$ = this.internal, candidates;
  4439. targetIds = $$.mapToTargetIds(targetIds);
  4440. candidates = $$.svg.selectAll($$.selectorTargets(targetIds)); // should be for all targets
  4441. candidates.classed(CLASS.focused, false).classed(CLASS.defocused, false);
  4442. if ($$.hasArcType()) {
  4443. $$.unexpandArc(targetIds);
  4444. }
  4445. if ($$.config.legend_show) {
  4446. $$.showLegend(targetIds.filter($$.isLegendToShow.bind($$)));
  4447. $$.legend
  4448. .selectAll($$.selectorLegends(targetIds))
  4449. .filter(function () {
  4450. return $$.d3.select(this).classed(CLASS.legendItemFocused);
  4451. })
  4452. .classed(CLASS.legendItemFocused, false);
  4453. }
  4454. $$.focusedTargetIds = [];
  4455. $$.defocusedTargetIds = [];
  4456. };
  4457. Chart.prototype.xgrids = function (grids) {
  4458. var $$ = this.internal, config = $$.config;
  4459. if (!grids) {
  4460. return config.grid_x_lines;
  4461. }
  4462. config.grid_x_lines = grids;
  4463. $$.redrawWithoutRescale();
  4464. return config.grid_x_lines;
  4465. };
  4466. Chart.prototype.xgrids.add = function (grids) {
  4467. var $$ = this.internal;
  4468. return this.xgrids($$.config.grid_x_lines.concat(grids ? grids : []));
  4469. };
  4470. Chart.prototype.xgrids.remove = function (params) {
  4471. // TODO: multiple
  4472. var $$ = this.internal;
  4473. $$.removeGridLines(params, true);
  4474. };
  4475. Chart.prototype.ygrids = function (grids) {
  4476. var $$ = this.internal, config = $$.config;
  4477. if (!grids) {
  4478. return config.grid_y_lines;
  4479. }
  4480. config.grid_y_lines = grids;
  4481. $$.redrawWithoutRescale();
  4482. return config.grid_y_lines;
  4483. };
  4484. Chart.prototype.ygrids.add = function (grids) {
  4485. var $$ = this.internal;
  4486. return this.ygrids($$.config.grid_y_lines.concat(grids ? grids : []));
  4487. };
  4488. Chart.prototype.ygrids.remove = function (params) {
  4489. // TODO: multiple
  4490. var $$ = this.internal;
  4491. $$.removeGridLines(params, false);
  4492. };
  4493. Chart.prototype.groups = function (groups) {
  4494. var $$ = this.internal, config = $$.config;
  4495. if (isUndefined(groups)) {
  4496. return config.data_groups;
  4497. }
  4498. config.data_groups = groups;
  4499. $$.redraw();
  4500. return config.data_groups;
  4501. };
  4502. Chart.prototype.legend = function () { };
  4503. Chart.prototype.legend.show = function (targetIds) {
  4504. var $$ = this.internal;
  4505. $$.showLegend($$.mapToTargetIds(targetIds));
  4506. $$.updateAndRedraw({ withLegend: true });
  4507. };
  4508. Chart.prototype.legend.hide = function (targetIds) {
  4509. var $$ = this.internal;
  4510. $$.hideLegend($$.mapToTargetIds(targetIds));
  4511. $$.updateAndRedraw({ withLegend: false });
  4512. };
  4513. Chart.prototype.load = function (args) {
  4514. var $$ = this.internal, config = $$.config;
  4515. // update xs if specified
  4516. if (args.xs) {
  4517. $$.addXs(args.xs);
  4518. }
  4519. // update names if exists
  4520. if ('names' in args) {
  4521. Chart.prototype.data.names.bind(this)(args.names);
  4522. }
  4523. // update classes if exists
  4524. if ('classes' in args) {
  4525. Object.keys(args.classes).forEach(function (id) {
  4526. config.data_classes[id] = args.classes[id];
  4527. });
  4528. }
  4529. // update categories if exists
  4530. if ('categories' in args && $$.isCategorized()) {
  4531. config.axis_x_categories = args.categories;
  4532. }
  4533. // update axes if exists
  4534. if ('axes' in args) {
  4535. Object.keys(args.axes).forEach(function (id) {
  4536. config.data_axes[id] = args.axes[id];
  4537. });
  4538. }
  4539. // update colors if exists
  4540. if ('colors' in args) {
  4541. Object.keys(args.colors).forEach(function (id) {
  4542. config.data_colors[id] = args.colors[id];
  4543. });
  4544. }
  4545. // use cache if exists
  4546. if ('cacheIds' in args && $$.hasCaches(args.cacheIds)) {
  4547. $$.load($$.getCaches(args.cacheIds), args.done);
  4548. return;
  4549. }
  4550. // unload if needed
  4551. if (args.unload) {
  4552. // TODO: do not unload if target will load (included in url/rows/columns)
  4553. $$.unload($$.mapToTargetIds(args.unload === true ? null : args.unload), function () {
  4554. $$.loadFromArgs(args);
  4555. });
  4556. }
  4557. else {
  4558. $$.loadFromArgs(args);
  4559. }
  4560. };
  4561. Chart.prototype.unload = function (args) {
  4562. var $$ = this.internal;
  4563. args = args || {};
  4564. if (args instanceof Array) {
  4565. args = { ids: args };
  4566. }
  4567. else if (typeof args === 'string') {
  4568. args = { ids: [args] };
  4569. }
  4570. $$.unload($$.mapToTargetIds(args.ids), function () {
  4571. $$.redraw({
  4572. withUpdateOrgXDomain: true,
  4573. withUpdateXDomain: true,
  4574. withLegend: true
  4575. });
  4576. if (args.done) {
  4577. args.done();
  4578. }
  4579. });
  4580. };
  4581. Chart.prototype.pie = function () { };
  4582. Chart.prototype.pie.padAngle = function (padAngle) {
  4583. if (padAngle === undefined) {
  4584. return this.internal.config.pie_padAngle;
  4585. }
  4586. this.internal.config.pie_padAngle = padAngle;
  4587. this.flush();
  4588. };
  4589. Chart.prototype.regions = function (regions) {
  4590. var $$ = this.internal, config = $$.config;
  4591. if (!regions) {
  4592. return config.regions;
  4593. }
  4594. config.regions = regions;
  4595. $$.redrawWithoutRescale();
  4596. return config.regions;
  4597. };
  4598. Chart.prototype.regions.add = function (regions) {
  4599. var $$ = this.internal, config = $$.config;
  4600. if (!regions) {
  4601. return config.regions;
  4602. }
  4603. config.regions = config.regions.concat(regions);
  4604. $$.redrawWithoutRescale();
  4605. return config.regions;
  4606. };
  4607. Chart.prototype.regions.remove = function (options) {
  4608. var $$ = this.internal, config = $$.config, duration, classes, regions;
  4609. options = options || {};
  4610. duration = getOption(options, 'duration', config.transition_duration);
  4611. classes = getOption(options, 'classes', [CLASS.region]);
  4612. regions = $$.main.select('.' + CLASS.regions).selectAll(classes.map(function (c) {
  4613. return '.' + c;
  4614. }));
  4615. (duration ? regions.transition().duration(duration) : regions)
  4616. .style('opacity', 0)
  4617. .remove();
  4618. config.regions = config.regions.filter(function (region) {
  4619. var found = false;
  4620. if (!region['class']) {
  4621. return true;
  4622. }
  4623. region['class'].split(' ').forEach(function (c) {
  4624. if (classes.indexOf(c) >= 0) {
  4625. found = true;
  4626. }
  4627. });
  4628. return !found;
  4629. });
  4630. return config.regions;
  4631. };
  4632. Chart.prototype.selected = function (targetId) {
  4633. var $$ = this.internal, d3 = $$.d3;
  4634. return $$.main
  4635. .selectAll('.' + CLASS.shapes + $$.getTargetSelectorSuffix(targetId))
  4636. .selectAll('.' + CLASS.shape)
  4637. .filter(function () {
  4638. return d3.select(this).classed(CLASS.SELECTED);
  4639. })
  4640. .nodes()
  4641. .map(function (d) {
  4642. var data = d.__data__;
  4643. return data.data ? data.data : data;
  4644. });
  4645. };
  4646. Chart.prototype.select = function (ids, indices, resetOther) {
  4647. var $$ = this.internal, d3 = $$.d3, config = $$.config;
  4648. if (!config.data_selection_enabled) {
  4649. return;
  4650. }
  4651. $$.main
  4652. .selectAll('.' + CLASS.shapes)
  4653. .selectAll('.' + CLASS.shape)
  4654. .each(function (d, i) {
  4655. var shape = d3.select(this), id = d.data ? d.data.id : d.id, toggle = $$.getToggle(this, d).bind($$), isTargetId = config.data_selection_grouped || !ids || ids.indexOf(id) >= 0, isTargetIndex = !indices || indices.indexOf(i) >= 0, isSelected = shape.classed(CLASS.SELECTED);
  4656. // line/area selection not supported yet
  4657. if (shape.classed(CLASS.line) || shape.classed(CLASS.area)) {
  4658. return;
  4659. }
  4660. if (isTargetId && isTargetIndex) {
  4661. if (config.data_selection_isselectable(d) && !isSelected) {
  4662. toggle(true, shape.classed(CLASS.SELECTED, true), d, i);
  4663. }
  4664. }
  4665. else if (isDefined(resetOther) && resetOther) {
  4666. if (isSelected) {
  4667. toggle(false, shape.classed(CLASS.SELECTED, false), d, i);
  4668. }
  4669. }
  4670. });
  4671. };
  4672. Chart.prototype.unselect = function (ids, indices) {
  4673. var $$ = this.internal, d3 = $$.d3, config = $$.config;
  4674. if (!config.data_selection_enabled) {
  4675. return;
  4676. }
  4677. $$.main
  4678. .selectAll('.' + CLASS.shapes)
  4679. .selectAll('.' + CLASS.shape)
  4680. .each(function (d, i) {
  4681. var shape = d3.select(this), id = d.data ? d.data.id : d.id, toggle = $$.getToggle(this, d).bind($$), isTargetId = config.data_selection_grouped || !ids || ids.indexOf(id) >= 0, isTargetIndex = !indices || indices.indexOf(i) >= 0, isSelected = shape.classed(CLASS.SELECTED);
  4682. // line/area selection not supported yet
  4683. if (shape.classed(CLASS.line) || shape.classed(CLASS.area)) {
  4684. return;
  4685. }
  4686. if (isTargetId && isTargetIndex) {
  4687. if (config.data_selection_isselectable(d)) {
  4688. if (isSelected) {
  4689. toggle(false, shape.classed(CLASS.SELECTED, false), d, i);
  4690. }
  4691. }
  4692. }
  4693. });
  4694. };
  4695. Chart.prototype.show = function (targetIds, options) {
  4696. var $$ = this.internal, targets;
  4697. targetIds = $$.mapToTargetIds(targetIds);
  4698. options = options || {};
  4699. $$.removeHiddenTargetIds(targetIds);
  4700. targets = $$.svg.selectAll($$.selectorTargets(targetIds));
  4701. targets
  4702. .transition()
  4703. .style('display', isIE() ? 'block' : 'initial', 'important')
  4704. .style('opacity', 1, 'important')
  4705. .call($$.endall, function () {
  4706. targets.style('opacity', null).style('opacity', 1);
  4707. });
  4708. if (options.withLegend) {
  4709. $$.showLegend(targetIds);
  4710. }
  4711. $$.redraw({
  4712. withUpdateOrgXDomain: true,
  4713. withUpdateXDomain: true,
  4714. withLegend: true
  4715. });
  4716. };
  4717. Chart.prototype.hide = function (targetIds, options) {
  4718. var $$ = this.internal, targets;
  4719. targetIds = $$.mapToTargetIds(targetIds);
  4720. options = options || {};
  4721. $$.addHiddenTargetIds(targetIds);
  4722. targets = $$.svg.selectAll($$.selectorTargets(targetIds));
  4723. targets
  4724. .transition()
  4725. .style('opacity', 0, 'important')
  4726. .call($$.endall, function () {
  4727. targets.style('opacity', null).style('opacity', 0);
  4728. targets.style('display', 'none');
  4729. });
  4730. if (options.withLegend) {
  4731. $$.hideLegend(targetIds);
  4732. }
  4733. $$.redraw({
  4734. withUpdateOrgXDomain: true,
  4735. withUpdateXDomain: true,
  4736. withLegend: true
  4737. });
  4738. };
  4739. Chart.prototype.toggle = function (targetIds, options) {
  4740. var that = this, $$ = this.internal;
  4741. $$.mapToTargetIds(targetIds).forEach(function (targetId) {
  4742. $$.isTargetToShow(targetId)
  4743. ? that.hide(targetId, options)
  4744. : that.show(targetId, options);
  4745. });
  4746. };
  4747. Chart.prototype.subchart = function () { };
  4748. Chart.prototype.subchart.isShown = function () {
  4749. var $$ = this.internal;
  4750. return $$.config.subchart_show;
  4751. };
  4752. Chart.prototype.subchart.show = function () {
  4753. var $$ = this.internal;
  4754. if ($$.config.subchart_show) {
  4755. return;
  4756. }
  4757. $$.config.subchart_show = true;
  4758. // insert DOM
  4759. $$.initSubchart();
  4760. // update dimensions with sub chart now visible
  4761. $$.updateDimension();
  4762. // insert brush (depends on sizes previously updated)
  4763. $$.initSubchartBrush();
  4764. // attach data
  4765. $$.updateTargetsForSubchart($$.getTargets());
  4766. // reset fade-in state
  4767. $$.mapToIds($$.data.targets).forEach(function (id) {
  4768. $$.withoutFadeIn[id] = false;
  4769. });
  4770. // redraw chart !
  4771. $$.updateAndRedraw();
  4772. // update visible targets !
  4773. $$.showTargets();
  4774. };
  4775. Chart.prototype.subchart.hide = function () {
  4776. var $$ = this.internal;
  4777. if (!$$.config.subchart_show) {
  4778. return;
  4779. }
  4780. $$.config.subchart_show = false;
  4781. // remove DOM
  4782. $$.removeSubchart();
  4783. // re-render chart
  4784. $$.redraw();
  4785. };
  4786. Chart.prototype.tooltip = function () { };
  4787. Chart.prototype.tooltip.show = function (args) {
  4788. var $$ = this.internal, targets, data, mouse = {};
  4789. // determine mouse position on the chart
  4790. if (args.mouse) {
  4791. mouse = args.mouse;
  4792. }
  4793. else {
  4794. // determine focus data
  4795. if (args.data) {
  4796. data = args.data;
  4797. }
  4798. else if (typeof args.x !== 'undefined') {
  4799. if (args.id) {
  4800. targets = $$.data.targets.filter(function (t) {
  4801. return t.id === args.id;
  4802. });
  4803. }
  4804. else {
  4805. targets = $$.data.targets;
  4806. }
  4807. data = $$.filterByX(targets, args.x).slice(0, 1)[0];
  4808. }
  4809. mouse = data ? $$.getMousePosition(data) : null;
  4810. }
  4811. // emulate mouse events to show
  4812. $$.dispatchEvent('mousemove', mouse);
  4813. $$.config.tooltip_onshow.call($$, data);
  4814. };
  4815. Chart.prototype.tooltip.hide = function () {
  4816. // TODO: get target data by checking the state of focus
  4817. this.internal.dispatchEvent('mouseout', 0);
  4818. this.internal.config.tooltip_onhide.call(this);
  4819. };
  4820. Chart.prototype.transform = function (type, targetIds) {
  4821. var $$ = this.internal, options = ['pie', 'donut'].indexOf(type) >= 0 ? { withTransform: true } : null;
  4822. $$.transformTo(targetIds, type, options);
  4823. };
  4824. ChartInternal.prototype.transformTo = function (targetIds, type, optionsForRedraw) {
  4825. var $$ = this, withTransitionForAxis = !$$.hasArcType(), options = optionsForRedraw || {
  4826. withTransitionForAxis: withTransitionForAxis
  4827. };
  4828. options.withTransitionForTransform = false;
  4829. $$.transiting = false;
  4830. $$.setTargetType(targetIds, type);
  4831. $$.updateTargets($$.data.targets); // this is needed when transforming to arc
  4832. $$.updateAndRedraw(options);
  4833. };
  4834. Chart.prototype.x = function (x) {
  4835. var $$ = this.internal;
  4836. if (arguments.length) {
  4837. $$.updateTargetX($$.data.targets, x);
  4838. $$.redraw({ withUpdateOrgXDomain: true, withUpdateXDomain: true });
  4839. }
  4840. return $$.data.xs;
  4841. };
  4842. Chart.prototype.xs = function (xs) {
  4843. var $$ = this.internal;
  4844. if (arguments.length) {
  4845. $$.updateTargetXs($$.data.targets, xs);
  4846. $$.redraw({ withUpdateOrgXDomain: true, withUpdateXDomain: true });
  4847. }
  4848. return $$.data.xs;
  4849. };
  4850. Chart.prototype.zoom = function (domain) {
  4851. var $$ = this.internal;
  4852. if (domain) {
  4853. if ($$.isTimeSeries()) {
  4854. domain = domain.map(function (x) {
  4855. return $$.parseDate(x);
  4856. });
  4857. }
  4858. if ($$.config.subchart_show) {
  4859. $$.brush.selectionAsValue(domain, true);
  4860. }
  4861. else {
  4862. $$.updateXDomain(null, true, false, false, domain);
  4863. $$.redraw({ withY: $$.config.zoom_rescale, withSubchart: false });
  4864. }
  4865. $$.config.zoom_onzoom.call(this, $$.x.orgDomain());
  4866. return domain;
  4867. }
  4868. else {
  4869. return $$.x.domain();
  4870. }
  4871. };
  4872. Chart.prototype.zoom.enable = function (enabled) {
  4873. var $$ = this.internal;
  4874. $$.config.zoom_enabled = enabled;
  4875. $$.updateAndRedraw();
  4876. };
  4877. Chart.prototype.unzoom = function () {
  4878. var $$ = this.internal;
  4879. if ($$.config.subchart_show) {
  4880. $$.brush.clear();
  4881. }
  4882. else {
  4883. $$.updateXDomain(null, true, false, false, $$.subX.domain());
  4884. $$.redraw({ withY: $$.config.zoom_rescale, withSubchart: false });
  4885. }
  4886. };
  4887. Chart.prototype.zoom.max = function (max) {
  4888. var $$ = this.internal, config = $$.config, d3 = $$.d3;
  4889. if (max === 0 || max) {
  4890. config.zoom_x_max = d3.max([$$.orgXDomain[1], max]);
  4891. }
  4892. else {
  4893. return config.zoom_x_max;
  4894. }
  4895. };
  4896. Chart.prototype.zoom.min = function (min) {
  4897. var $$ = this.internal, config = $$.config, d3 = $$.d3;
  4898. if (min === 0 || min) {
  4899. config.zoom_x_min = d3.min([$$.orgXDomain[0], min]);
  4900. }
  4901. else {
  4902. return config.zoom_x_min;
  4903. }
  4904. };
  4905. Chart.prototype.zoom.range = function (range) {
  4906. if (arguments.length) {
  4907. if (isDefined(range.max)) {
  4908. this.domain.max(range.max);
  4909. }
  4910. if (isDefined(range.min)) {
  4911. this.domain.min(range.min);
  4912. }
  4913. }
  4914. else {
  4915. return {
  4916. max: this.domain.max(),
  4917. min: this.domain.min()
  4918. };
  4919. }
  4920. };
  4921. ChartInternal.prototype.initPie = function () {
  4922. var $$ = this, d3 = $$.d3;
  4923. $$.pie = d3
  4924. .pie()
  4925. .padAngle(this.getPadAngle.bind(this))
  4926. .value(function (d) {
  4927. return d.values.reduce(function (a, b) {
  4928. return a + b.value;
  4929. }, 0);
  4930. });
  4931. var orderFct = $$.getOrderFunction();
  4932. // we need to reverse the returned order if asc or desc to have the slice in expected order.
  4933. if (orderFct && ($$.isOrderAsc() || $$.isOrderDesc())) {
  4934. var defaultSort_1 = orderFct;
  4935. orderFct = function (t1, t2) { return defaultSort_1(t1, t2) * -1; };
  4936. }
  4937. $$.pie.sort(orderFct || null);
  4938. };
  4939. ChartInternal.prototype.updateRadius = function () {
  4940. var $$ = this, config = $$.config, w = config.gauge_width || config.donut_width, gaugeArcWidth = $$.filterTargetsToShow($$.data.targets).length *
  4941. $$.config.gauge_arcs_minWidth;
  4942. $$.radiusExpanded =
  4943. (Math.min($$.arcWidth, $$.arcHeight) / 2) * ($$.hasType('gauge') ? 0.85 : 1);
  4944. $$.radius = $$.radiusExpanded * 0.95;
  4945. $$.innerRadiusRatio = w ? ($$.radius - w) / $$.radius : 0.6;
  4946. $$.innerRadius =
  4947. $$.hasType('donut') || $$.hasType('gauge')
  4948. ? $$.radius * $$.innerRadiusRatio
  4949. : 0;
  4950. $$.gaugeArcWidth = w
  4951. ? w
  4952. : gaugeArcWidth <= $$.radius - $$.innerRadius
  4953. ? $$.radius - $$.innerRadius
  4954. : gaugeArcWidth <= $$.radius
  4955. ? gaugeArcWidth
  4956. : $$.radius;
  4957. };
  4958. ChartInternal.prototype.getPadAngle = function () {
  4959. if (this.hasType('pie')) {
  4960. return this.config.pie_padAngle || 0;
  4961. }
  4962. else if (this.hasType('donut')) {
  4963. return this.config.donut_padAngle || 0;
  4964. }
  4965. else {
  4966. return 0;
  4967. }
  4968. };
  4969. ChartInternal.prototype.updateArc = function () {
  4970. var $$ = this;
  4971. $$.svgArc = $$.getSvgArc();
  4972. $$.svgArcExpanded = $$.getSvgArcExpanded();
  4973. $$.svgArcExpandedSub = $$.getSvgArcExpanded(0.98);
  4974. };
  4975. ChartInternal.prototype.updateAngle = function (d) {
  4976. var $$ = this, config = $$.config, found = false, index = 0, gMin, gMax, gTic, gValue;
  4977. if (!config) {
  4978. return null;
  4979. }
  4980. $$.pie($$.filterTargetsToShow($$.data.targets)).forEach(function (t) {
  4981. if (!found && t.data.id === d.data.id) {
  4982. found = true;
  4983. d = t;
  4984. d.index = index;
  4985. }
  4986. index++;
  4987. });
  4988. if (isNaN(d.startAngle)) {
  4989. d.startAngle = 0;
  4990. }
  4991. if (isNaN(d.endAngle)) {
  4992. d.endAngle = d.startAngle;
  4993. }
  4994. if ($$.isGaugeType(d.data)) {
  4995. gMin = config.gauge_min;
  4996. gMax = config.gauge_max;
  4997. gTic = (Math.PI * (config.gauge_fullCircle ? 2 : 1)) / (gMax - gMin);
  4998. gValue = d.value < gMin ? 0 : d.value < gMax ? d.value - gMin : gMax - gMin;
  4999. d.startAngle = config.gauge_startingAngle;
  5000. d.endAngle = d.startAngle + gTic * gValue;
  5001. }
  5002. return found ? d : null;
  5003. };
  5004. ChartInternal.prototype.getSvgArc = function () {
  5005. var $$ = this, hasGaugeType = $$.hasType('gauge'), singleArcWidth = $$.gaugeArcWidth / $$.filterTargetsToShow($$.data.targets).length, arc = $$.d3
  5006. .arc()
  5007. .outerRadius(function (d) {
  5008. return hasGaugeType ? $$.radius - singleArcWidth * d.index : $$.radius;
  5009. })
  5010. .innerRadius(function (d) {
  5011. return hasGaugeType
  5012. ? $$.radius - singleArcWidth * (d.index + 1)
  5013. : $$.innerRadius;
  5014. }), newArc = function (d, withoutUpdate) {
  5015. var updated;
  5016. if (withoutUpdate) {
  5017. return arc(d);
  5018. } // for interpolate
  5019. updated = $$.updateAngle(d);
  5020. return updated ? arc(updated) : 'M 0 0';
  5021. };
  5022. newArc.centroid = arc.centroid;
  5023. return newArc;
  5024. };
  5025. ChartInternal.prototype.getSvgArcExpanded = function (rate) {
  5026. rate = rate || 1;
  5027. var $$ = this, hasGaugeType = $$.hasType('gauge'), singleArcWidth = $$.gaugeArcWidth / $$.filterTargetsToShow($$.data.targets).length, expandWidth = Math.min($$.radiusExpanded * rate - $$.radius, singleArcWidth * 0.8 - (1 - rate) * 100), arc = $$.d3
  5028. .arc()
  5029. .outerRadius(function (d) {
  5030. return hasGaugeType
  5031. ? $$.radius - singleArcWidth * d.index + expandWidth
  5032. : $$.radiusExpanded * rate;
  5033. })
  5034. .innerRadius(function (d) {
  5035. return hasGaugeType
  5036. ? $$.radius - singleArcWidth * (d.index + 1)
  5037. : $$.innerRadius;
  5038. });
  5039. return function (d) {
  5040. var updated = $$.updateAngle(d);
  5041. return updated ? arc(updated) : 'M 0 0';
  5042. };
  5043. };
  5044. ChartInternal.prototype.getArc = function (d, withoutUpdate, force) {
  5045. return force || this.isArcType(d.data)
  5046. ? this.svgArc(d, withoutUpdate)
  5047. : 'M 0 0';
  5048. };
  5049. ChartInternal.prototype.transformForArcLabel = function (d) {
  5050. var $$ = this, config = $$.config, updated = $$.updateAngle(d), c, x, y, h, ratio, translate = '', hasGauge = $$.hasType('gauge');
  5051. if (updated && !hasGauge) {
  5052. c = this.svgArc.centroid(updated);
  5053. x = isNaN(c[0]) ? 0 : c[0];
  5054. y = isNaN(c[1]) ? 0 : c[1];
  5055. h = Math.sqrt(x * x + y * y);
  5056. if ($$.hasType('donut') && config.donut_label_ratio) {
  5057. ratio = isFunction(config.donut_label_ratio)
  5058. ? config.donut_label_ratio(d, $$.radius, h)
  5059. : config.donut_label_ratio;
  5060. }
  5061. else if ($$.hasType('pie') && config.pie_label_ratio) {
  5062. ratio = isFunction(config.pie_label_ratio)
  5063. ? config.pie_label_ratio(d, $$.radius, h)
  5064. : config.pie_label_ratio;
  5065. }
  5066. else {
  5067. ratio =
  5068. $$.radius && h
  5069. ? ((36 / $$.radius > 0.375 ? 1.175 - 36 / $$.radius : 0.8) *
  5070. $$.radius) /
  5071. h
  5072. : 0;
  5073. }
  5074. translate = 'translate(' + x * ratio + ',' + y * ratio + ')';
  5075. }
  5076. else if (updated &&
  5077. hasGauge &&
  5078. $$.filterTargetsToShow($$.data.targets).length > 1) {
  5079. var y1 = Math.sin(updated.endAngle - Math.PI / 2);
  5080. x = Math.cos(updated.endAngle - Math.PI / 2) * ($$.radiusExpanded + 25);
  5081. y = y1 * ($$.radiusExpanded + 15 - Math.abs(y1 * 10)) + 3;
  5082. translate = 'translate(' + x + ',' + y + ')';
  5083. }
  5084. return translate;
  5085. };
  5086. /**
  5087. * @deprecated Use `getRatio('arc', d)` instead.
  5088. */
  5089. ChartInternal.prototype.getArcRatio = function (d) {
  5090. return this.getRatio('arc', d);
  5091. };
  5092. ChartInternal.prototype.convertToArcData = function (d) {
  5093. return this.addName({
  5094. id: d.data.id,
  5095. value: d.value,
  5096. ratio: this.getRatio('arc', d),
  5097. index: d.index
  5098. });
  5099. };
  5100. ChartInternal.prototype.textForArcLabel = function (d) {
  5101. var $$ = this, updated, value, ratio, id, format;
  5102. if (!$$.shouldShowArcLabel()) {
  5103. return '';
  5104. }
  5105. updated = $$.updateAngle(d);
  5106. value = updated ? updated.value : null;
  5107. ratio = $$.getRatio('arc', updated);
  5108. id = d.data.id;
  5109. if (!$$.hasType('gauge') && !$$.meetsArcLabelThreshold(ratio)) {
  5110. return '';
  5111. }
  5112. format = $$.getArcLabelFormat();
  5113. return format
  5114. ? format(value, ratio, id)
  5115. : $$.defaultArcValueFormat(value, ratio);
  5116. };
  5117. ChartInternal.prototype.textForGaugeMinMax = function (value, isMax) {
  5118. var $$ = this, format = $$.getGaugeLabelExtents();
  5119. return format ? format(value, isMax) : value;
  5120. };
  5121. ChartInternal.prototype.expandArc = function (targetIds) {
  5122. var $$ = this, interval;
  5123. // MEMO: avoid to cancel transition
  5124. if ($$.transiting) {
  5125. interval = window.setInterval(function () {
  5126. if (!$$.transiting) {
  5127. window.clearInterval(interval);
  5128. if ($$.legend.selectAll('.c3-legend-item-focused').size() > 0) {
  5129. $$.expandArc(targetIds);
  5130. }
  5131. }
  5132. }, 10);
  5133. return;
  5134. }
  5135. targetIds = $$.mapToTargetIds(targetIds);
  5136. $$.svg
  5137. .selectAll($$.selectorTargets(targetIds, '.' + CLASS.chartArc))
  5138. .each(function (d) {
  5139. if (!$$.shouldExpand(d.data.id)) {
  5140. return;
  5141. }
  5142. $$.d3
  5143. .select(this)
  5144. .selectAll('path')
  5145. .transition()
  5146. .duration($$.expandDuration(d.data.id))
  5147. .attr('d', $$.svgArcExpanded)
  5148. .transition()
  5149. .duration($$.expandDuration(d.data.id) * 2)
  5150. .attr('d', $$.svgArcExpandedSub)
  5151. .each(function (d) {
  5152. if ($$.isDonutType(d.data)) ;
  5153. });
  5154. });
  5155. };
  5156. ChartInternal.prototype.unexpandArc = function (targetIds) {
  5157. var $$ = this;
  5158. if ($$.transiting) {
  5159. return;
  5160. }
  5161. targetIds = $$.mapToTargetIds(targetIds);
  5162. $$.svg
  5163. .selectAll($$.selectorTargets(targetIds, '.' + CLASS.chartArc))
  5164. .selectAll('path')
  5165. .transition()
  5166. .duration(function (d) {
  5167. return $$.expandDuration(d.data.id);
  5168. })
  5169. .attr('d', $$.svgArc);
  5170. $$.svg.selectAll('.' + CLASS.arc);
  5171. };
  5172. ChartInternal.prototype.expandDuration = function (id) {
  5173. var $$ = this, config = $$.config;
  5174. if ($$.isDonutType(id)) {
  5175. return config.donut_expand_duration;
  5176. }
  5177. else if ($$.isGaugeType(id)) {
  5178. return config.gauge_expand_duration;
  5179. }
  5180. else if ($$.isPieType(id)) {
  5181. return config.pie_expand_duration;
  5182. }
  5183. else {
  5184. return 50;
  5185. }
  5186. };
  5187. ChartInternal.prototype.shouldExpand = function (id) {
  5188. var $$ = this, config = $$.config;
  5189. return (($$.isDonutType(id) && config.donut_expand) ||
  5190. ($$.isGaugeType(id) && config.gauge_expand) ||
  5191. ($$.isPieType(id) && config.pie_expand));
  5192. };
  5193. ChartInternal.prototype.shouldShowArcLabel = function () {
  5194. var $$ = this, config = $$.config, shouldShow = true;
  5195. if ($$.hasType('donut')) {
  5196. shouldShow = config.donut_label_show;
  5197. }
  5198. else if ($$.hasType('pie')) {
  5199. shouldShow = config.pie_label_show;
  5200. }
  5201. // when gauge, always true
  5202. return shouldShow;
  5203. };
  5204. ChartInternal.prototype.meetsArcLabelThreshold = function (ratio) {
  5205. var $$ = this, config = $$.config, threshold = $$.hasType('donut')
  5206. ? config.donut_label_threshold
  5207. : config.pie_label_threshold;
  5208. return ratio >= threshold;
  5209. };
  5210. ChartInternal.prototype.getArcLabelFormat = function () {
  5211. var $$ = this, config = $$.config, format = config.pie_label_format;
  5212. if ($$.hasType('gauge')) {
  5213. format = config.gauge_label_format;
  5214. }
  5215. else if ($$.hasType('donut')) {
  5216. format = config.donut_label_format;
  5217. }
  5218. return format;
  5219. };
  5220. ChartInternal.prototype.getGaugeLabelExtents = function () {
  5221. var $$ = this, config = $$.config;
  5222. return config.gauge_label_extents;
  5223. };
  5224. ChartInternal.prototype.getArcTitle = function () {
  5225. var $$ = this;
  5226. return $$.hasType('donut') ? $$.config.donut_title : '';
  5227. };
  5228. ChartInternal.prototype.updateTargetsForArc = function (targets) {
  5229. var $$ = this, main = $$.main, mainPies, mainPieEnter, classChartArc = $$.classChartArc.bind($$), classArcs = $$.classArcs.bind($$), classFocus = $$.classFocus.bind($$);
  5230. mainPies = main
  5231. .select('.' + CLASS.chartArcs)
  5232. .selectAll('.' + CLASS.chartArc)
  5233. .data($$.pie(targets))
  5234. .attr('class', function (d) {
  5235. return classChartArc(d) + classFocus(d.data);
  5236. });
  5237. mainPieEnter = mainPies
  5238. .enter()
  5239. .append('g')
  5240. .attr('class', classChartArc);
  5241. mainPieEnter.append('g').attr('class', classArcs);
  5242. mainPieEnter
  5243. .append('text')
  5244. .attr('dy', $$.hasType('gauge') ? '-.1em' : '.35em')
  5245. .style('opacity', 0)
  5246. .style('text-anchor', 'middle')
  5247. .style('pointer-events', 'none');
  5248. // MEMO: can not keep same color..., but not bad to update color in redraw
  5249. //mainPieUpdate.exit().remove();
  5250. };
  5251. ChartInternal.prototype.initArc = function () {
  5252. var $$ = this;
  5253. $$.arcs = $$.main
  5254. .select('.' + CLASS.chart)
  5255. .append('g')
  5256. .attr('class', CLASS.chartArcs)
  5257. .attr('transform', $$.getTranslate('arc'));
  5258. $$.arcs
  5259. .append('text')
  5260. .attr('class', CLASS.chartArcsTitle)
  5261. .style('text-anchor', 'middle')
  5262. .text($$.getArcTitle());
  5263. };
  5264. ChartInternal.prototype.redrawArc = function (duration, durationForExit, withTransform) {
  5265. var $$ = this, d3 = $$.d3, config = $$.config, main = $$.main, arcs, mainArc, arcLabelLines, mainArcLabelLine, hasGaugeType = $$.hasType('gauge');
  5266. arcs = main
  5267. .selectAll('.' + CLASS.arcs)
  5268. .selectAll('.' + CLASS.arc)
  5269. .data($$.arcData.bind($$));
  5270. mainArc = arcs
  5271. .enter()
  5272. .append('path')
  5273. .attr('class', $$.classArc.bind($$))
  5274. .style('fill', function (d) {
  5275. return $$.color(d.data);
  5276. })
  5277. .style('cursor', function (d) {
  5278. return config.interaction_enabled && config.data_selection_isselectable(d)
  5279. ? 'pointer'
  5280. : null;
  5281. })
  5282. .each(function (d) {
  5283. if ($$.isGaugeType(d.data)) {
  5284. d.startAngle = d.endAngle = config.gauge_startingAngle;
  5285. }
  5286. this._current = d;
  5287. })
  5288. .merge(arcs);
  5289. if (hasGaugeType) {
  5290. arcLabelLines = main
  5291. .selectAll('.' + CLASS.arcs)
  5292. .selectAll('.' + CLASS.arcLabelLine)
  5293. .data($$.arcData.bind($$));
  5294. mainArcLabelLine = arcLabelLines
  5295. .enter()
  5296. .append('rect')
  5297. .attr('class', function (d) {
  5298. return (CLASS.arcLabelLine +
  5299. ' ' +
  5300. CLASS.target +
  5301. ' ' +
  5302. CLASS.target +
  5303. '-' +
  5304. d.data.id);
  5305. })
  5306. .merge(arcLabelLines);
  5307. if ($$.filterTargetsToShow($$.data.targets).length === 1) {
  5308. mainArcLabelLine.style('display', 'none');
  5309. }
  5310. else {
  5311. mainArcLabelLine
  5312. .style('fill', function (d) {
  5313. return $$.levelColor
  5314. ? $$.levelColor(d.data.values.reduce(function (total, item) {
  5315. return total + item.value;
  5316. }, 0))
  5317. : $$.color(d.data);
  5318. })
  5319. .style('display', config.gauge_labelLine_show ? '' : 'none')
  5320. .each(function (d) {
  5321. var lineLength = 0, lineThickness = 2, x = 0, y = 0, transform = '';
  5322. if ($$.hiddenTargetIds.indexOf(d.data.id) < 0) {
  5323. var updated = $$.updateAngle(d), innerLineLength = ($$.gaugeArcWidth /
  5324. $$.filterTargetsToShow($$.data.targets).length) *
  5325. (updated.index + 1), lineAngle = updated.endAngle - Math.PI / 2, arcInnerRadius = $$.radius - innerLineLength, linePositioningAngle = lineAngle - (arcInnerRadius === 0 ? 0 : 1 / arcInnerRadius);
  5326. lineLength = $$.radiusExpanded - $$.radius + innerLineLength;
  5327. x = Math.cos(linePositioningAngle) * arcInnerRadius;
  5328. y = Math.sin(linePositioningAngle) * arcInnerRadius;
  5329. transform =
  5330. 'rotate(' +
  5331. (lineAngle * 180) / Math.PI +
  5332. ', ' +
  5333. x +
  5334. ', ' +
  5335. y +
  5336. ')';
  5337. }
  5338. d3.select(this)
  5339. .attr('x', x)
  5340. .attr('y', y)
  5341. .attr('width', lineLength)
  5342. .attr('height', lineThickness)
  5343. .attr('transform', transform)
  5344. .style('stroke-dasharray', '0, ' + (lineLength + lineThickness) + ', 0');
  5345. });
  5346. }
  5347. }
  5348. mainArc
  5349. .attr('transform', function (d) {
  5350. return !$$.isGaugeType(d.data) && withTransform ? 'scale(0)' : '';
  5351. })
  5352. .on('mouseover', config.interaction_enabled
  5353. ? function (d) {
  5354. var updated, arcData;
  5355. if ($$.transiting) {
  5356. // skip while transiting
  5357. return;
  5358. }
  5359. updated = $$.updateAngle(d);
  5360. if (updated) {
  5361. arcData = $$.convertToArcData(updated);
  5362. // transitions
  5363. $$.expandArc(updated.data.id);
  5364. $$.api.focus(updated.data.id);
  5365. $$.toggleFocusLegend(updated.data.id, true);
  5366. $$.config.data_onmouseover(arcData, this);
  5367. }
  5368. }
  5369. : null)
  5370. .on('mousemove', config.interaction_enabled
  5371. ? function (d) {
  5372. var updated = $$.updateAngle(d), arcData, selectedData;
  5373. if (updated) {
  5374. (arcData = $$.convertToArcData(updated)),
  5375. (selectedData = [arcData]);
  5376. $$.showTooltip(selectedData, this);
  5377. }
  5378. }
  5379. : null)
  5380. .on('mouseout', config.interaction_enabled
  5381. ? function (d) {
  5382. var updated, arcData;
  5383. if ($$.transiting) {
  5384. // skip while transiting
  5385. return;
  5386. }
  5387. updated = $$.updateAngle(d);
  5388. if (updated) {
  5389. arcData = $$.convertToArcData(updated);
  5390. // transitions
  5391. $$.unexpandArc(updated.data.id);
  5392. $$.api.revert();
  5393. $$.revertLegend();
  5394. $$.hideTooltip();
  5395. $$.config.data_onmouseout(arcData, this);
  5396. }
  5397. }
  5398. : null)
  5399. .on('click', config.interaction_enabled
  5400. ? function (d, i) {
  5401. var updated = $$.updateAngle(d), arcData;
  5402. if (updated) {
  5403. arcData = $$.convertToArcData(updated);
  5404. if ($$.toggleShape) {
  5405. $$.toggleShape(this, arcData, i);
  5406. }
  5407. $$.config.data_onclick.call($$.api, arcData, this);
  5408. }
  5409. }
  5410. : null)
  5411. .each(function () {
  5412. $$.transiting = true;
  5413. })
  5414. .transition()
  5415. .duration(duration)
  5416. .attrTween('d', function (d) {
  5417. var updated = $$.updateAngle(d), interpolate;
  5418. if (!updated) {
  5419. return function () {
  5420. return 'M 0 0';
  5421. };
  5422. }
  5423. // if (this._current === d) {
  5424. // this._current = {
  5425. // startAngle: Math.PI*2,
  5426. // endAngle: Math.PI*2,
  5427. // };
  5428. // }
  5429. if (isNaN(this._current.startAngle)) {
  5430. this._current.startAngle = 0;
  5431. }
  5432. if (isNaN(this._current.endAngle)) {
  5433. this._current.endAngle = this._current.startAngle;
  5434. }
  5435. interpolate = d3.interpolate(this._current, updated);
  5436. this._current = interpolate(0);
  5437. return function (t) {
  5438. // prevents crashing the charts once in transition and chart.destroy() has been called
  5439. if ($$.config === null) {
  5440. return 'M 0 0';
  5441. }
  5442. var interpolated = interpolate(t);
  5443. interpolated.data = d.data; // data.id will be updated by interporator
  5444. return $$.getArc(interpolated, true);
  5445. };
  5446. })
  5447. .attr('transform', withTransform ? 'scale(1)' : '')
  5448. .style('fill', function (d) {
  5449. return $$.levelColor
  5450. ? $$.levelColor(d.data.values.reduce(function (total, item) {
  5451. return total + item.value;
  5452. }, 0))
  5453. : $$.color(d.data.id);
  5454. }) // Where gauge reading color would receive customization.
  5455. .call($$.endall, function () {
  5456. $$.transiting = false;
  5457. });
  5458. arcs
  5459. .exit()
  5460. .transition()
  5461. .duration(durationForExit)
  5462. .style('opacity', 0)
  5463. .remove();
  5464. main
  5465. .selectAll('.' + CLASS.chartArc)
  5466. .select('text')
  5467. .style('opacity', 0)
  5468. .attr('class', function (d) {
  5469. return $$.isGaugeType(d.data) ? CLASS.gaugeValue : '';
  5470. })
  5471. .text($$.textForArcLabel.bind($$))
  5472. .attr('transform', $$.transformForArcLabel.bind($$))
  5473. .style('font-size', function (d) {
  5474. return $$.isGaugeType(d.data) &&
  5475. $$.filterTargetsToShow($$.data.targets).length === 1
  5476. ? Math.round($$.radius / 5) + 'px'
  5477. : '';
  5478. })
  5479. .transition()
  5480. .duration(duration)
  5481. .style('opacity', function (d) {
  5482. return $$.isTargetToShow(d.data.id) && $$.isArcType(d.data) ? 1 : 0;
  5483. });
  5484. main
  5485. .select('.' + CLASS.chartArcsTitle)
  5486. .style('opacity', $$.hasType('donut') || hasGaugeType ? 1 : 0);
  5487. if (hasGaugeType) {
  5488. var index_1 = 0;
  5489. var backgroundArc = $$.arcs
  5490. .select('g.' + CLASS.chartArcsBackground)
  5491. .selectAll('path.' + CLASS.chartArcsBackground)
  5492. .data($$.data.targets);
  5493. backgroundArc
  5494. .enter()
  5495. .append('path')
  5496. .attr('class', function (d, i) {
  5497. return CLASS.chartArcsBackground + ' ' + CLASS.chartArcsBackground + '-' + i;
  5498. })
  5499. .merge(backgroundArc)
  5500. .attr('d', function (d1) {
  5501. if ($$.hiddenTargetIds.indexOf(d1.id) >= 0) {
  5502. return 'M 0 0';
  5503. }
  5504. var d = {
  5505. data: [{ value: config.gauge_max }],
  5506. startAngle: config.gauge_startingAngle,
  5507. endAngle: -1 *
  5508. config.gauge_startingAngle *
  5509. (config.gauge_fullCircle ? Math.PI : 1),
  5510. index: index_1++
  5511. };
  5512. return $$.getArc(d, true, true);
  5513. });
  5514. backgroundArc.exit().remove();
  5515. $$.arcs
  5516. .select('.' + CLASS.chartArcsGaugeUnit)
  5517. .attr('dy', '.75em')
  5518. .text(config.gauge_label_show ? config.gauge_units : '');
  5519. $$.arcs
  5520. .select('.' + CLASS.chartArcsGaugeMin)
  5521. .attr('dx', -1 *
  5522. ($$.innerRadius +
  5523. ($$.radius - $$.innerRadius) / (config.gauge_fullCircle ? 1 : 2)) +
  5524. 'px')
  5525. .attr('dy', '1.2em')
  5526. .text(config.gauge_label_show
  5527. ? $$.textForGaugeMinMax(config.gauge_min, false)
  5528. : '');
  5529. $$.arcs
  5530. .select('.' + CLASS.chartArcsGaugeMax)
  5531. .attr('dx', $$.innerRadius +
  5532. ($$.radius - $$.innerRadius) / (config.gauge_fullCircle ? 1 : 2) +
  5533. 'px')
  5534. .attr('dy', '1.2em')
  5535. .text(config.gauge_label_show
  5536. ? $$.textForGaugeMinMax(config.gauge_max, true)
  5537. : '');
  5538. }
  5539. };
  5540. ChartInternal.prototype.initGauge = function () {
  5541. var arcs = this.arcs;
  5542. if (this.hasType('gauge')) {
  5543. arcs.append('g').attr('class', CLASS.chartArcsBackground);
  5544. arcs
  5545. .append('text')
  5546. .attr('class', CLASS.chartArcsGaugeUnit)
  5547. .style('text-anchor', 'middle')
  5548. .style('pointer-events', 'none');
  5549. arcs
  5550. .append('text')
  5551. .attr('class', CLASS.chartArcsGaugeMin)
  5552. .style('text-anchor', 'middle')
  5553. .style('pointer-events', 'none');
  5554. arcs
  5555. .append('text')
  5556. .attr('class', CLASS.chartArcsGaugeMax)
  5557. .style('text-anchor', 'middle')
  5558. .style('pointer-events', 'none');
  5559. }
  5560. };
  5561. ChartInternal.prototype.getGaugeLabelHeight = function () {
  5562. return this.config.gauge_label_show ? 20 : 0;
  5563. };
  5564. /**
  5565. * Store value into cache
  5566. *
  5567. * @param key
  5568. * @param value
  5569. */
  5570. ChartInternal.prototype.addToCache = function (key, value) {
  5571. this.cache["$" + key] = value;
  5572. };
  5573. /**
  5574. * Returns a cached value or undefined
  5575. *
  5576. * @param key
  5577. * @return {*}
  5578. */
  5579. ChartInternal.prototype.getFromCache = function (key) {
  5580. return this.cache["$" + key];
  5581. };
  5582. /**
  5583. * Reset cached data
  5584. */
  5585. ChartInternal.prototype.resetCache = function () {
  5586. var _this = this;
  5587. Object.keys(this.cache)
  5588. .filter(function (key) { return /^\$/.test(key); })
  5589. .forEach(function (key) {
  5590. delete _this.cache[key];
  5591. });
  5592. };
  5593. // Old API that stores Targets
  5594. ChartInternal.prototype.hasCaches = function (ids) {
  5595. for (var i = 0; i < ids.length; i++) {
  5596. if (!(ids[i] in this.cache)) {
  5597. return false;
  5598. }
  5599. }
  5600. return true;
  5601. };
  5602. ChartInternal.prototype.addCache = function (id, target) {
  5603. this.cache[id] = this.cloneTarget(target);
  5604. };
  5605. ChartInternal.prototype.getCaches = function (ids) {
  5606. var targets = [], i;
  5607. for (i = 0; i < ids.length; i++) {
  5608. if (ids[i] in this.cache) {
  5609. targets.push(this.cloneTarget(this.cache[ids[i]]));
  5610. }
  5611. }
  5612. return targets;
  5613. };
  5614. ChartInternal.prototype.categoryName = function (i) {
  5615. var config = this.config;
  5616. return i < config.axis_x_categories.length ? config.axis_x_categories[i] : i;
  5617. };
  5618. ChartInternal.prototype.generateTargetClass = function (targetId) {
  5619. return targetId || targetId === 0 ? ('-' + targetId).replace(/\s/g, '-') : '';
  5620. };
  5621. ChartInternal.prototype.generateClass = function (prefix, targetId) {
  5622. return ' ' + prefix + ' ' + prefix + this.generateTargetClass(targetId);
  5623. };
  5624. ChartInternal.prototype.classText = function (d) {
  5625. return this.generateClass(CLASS.text, d.index);
  5626. };
  5627. ChartInternal.prototype.classTexts = function (d) {
  5628. return this.generateClass(CLASS.texts, d.id);
  5629. };
  5630. ChartInternal.prototype.classShape = function (d) {
  5631. return this.generateClass(CLASS.shape, d.index);
  5632. };
  5633. ChartInternal.prototype.classShapes = function (d) {
  5634. return this.generateClass(CLASS.shapes, d.id);
  5635. };
  5636. ChartInternal.prototype.classLine = function (d) {
  5637. return this.classShape(d) + this.generateClass(CLASS.line, d.id);
  5638. };
  5639. ChartInternal.prototype.classLines = function (d) {
  5640. return this.classShapes(d) + this.generateClass(CLASS.lines, d.id);
  5641. };
  5642. ChartInternal.prototype.classCircle = function (d) {
  5643. return this.classShape(d) + this.generateClass(CLASS.circle, d.index);
  5644. };
  5645. ChartInternal.prototype.classCircles = function (d) {
  5646. return this.classShapes(d) + this.generateClass(CLASS.circles, d.id);
  5647. };
  5648. ChartInternal.prototype.classBar = function (d) {
  5649. return this.classShape(d) + this.generateClass(CLASS.bar, d.index);
  5650. };
  5651. ChartInternal.prototype.classBars = function (d) {
  5652. return this.classShapes(d) + this.generateClass(CLASS.bars, d.id);
  5653. };
  5654. ChartInternal.prototype.classArc = function (d) {
  5655. return this.classShape(d.data) + this.generateClass(CLASS.arc, d.data.id);
  5656. };
  5657. ChartInternal.prototype.classArcs = function (d) {
  5658. return this.classShapes(d.data) + this.generateClass(CLASS.arcs, d.data.id);
  5659. };
  5660. ChartInternal.prototype.classArea = function (d) {
  5661. return this.classShape(d) + this.generateClass(CLASS.area, d.id);
  5662. };
  5663. ChartInternal.prototype.classAreas = function (d) {
  5664. return this.classShapes(d) + this.generateClass(CLASS.areas, d.id);
  5665. };
  5666. ChartInternal.prototype.classRegion = function (d, i) {
  5667. return (this.generateClass(CLASS.region, i) + ' ' + ('class' in d ? d['class'] : ''));
  5668. };
  5669. ChartInternal.prototype.classEvent = function (d) {
  5670. return this.generateClass(CLASS.eventRect, d.index);
  5671. };
  5672. ChartInternal.prototype.classTarget = function (id) {
  5673. var $$ = this;
  5674. var additionalClassSuffix = $$.config.data_classes[id], additionalClass = '';
  5675. if (additionalClassSuffix) {
  5676. additionalClass = ' ' + CLASS.target + '-' + additionalClassSuffix;
  5677. }
  5678. return $$.generateClass(CLASS.target, id) + additionalClass;
  5679. };
  5680. ChartInternal.prototype.classFocus = function (d) {
  5681. return this.classFocused(d) + this.classDefocused(d);
  5682. };
  5683. ChartInternal.prototype.classFocused = function (d) {
  5684. return ' ' + (this.focusedTargetIds.indexOf(d.id) >= 0 ? CLASS.focused : '');
  5685. };
  5686. ChartInternal.prototype.classDefocused = function (d) {
  5687. return (' ' + (this.defocusedTargetIds.indexOf(d.id) >= 0 ? CLASS.defocused : ''));
  5688. };
  5689. ChartInternal.prototype.classChartText = function (d) {
  5690. return CLASS.chartText + this.classTarget(d.id);
  5691. };
  5692. ChartInternal.prototype.classChartLine = function (d) {
  5693. return CLASS.chartLine + this.classTarget(d.id);
  5694. };
  5695. ChartInternal.prototype.classChartBar = function (d) {
  5696. return CLASS.chartBar + this.classTarget(d.id);
  5697. };
  5698. ChartInternal.prototype.classChartArc = function (d) {
  5699. return CLASS.chartArc + this.classTarget(d.data.id);
  5700. };
  5701. ChartInternal.prototype.getTargetSelectorSuffix = function (targetId) {
  5702. var targetClass = this.generateTargetClass(targetId);
  5703. if (window.CSS && window.CSS.escape) {
  5704. return window.CSS.escape(targetClass);
  5705. }
  5706. // fallback on imperfect method for old browsers (does not handles unicode)
  5707. return targetClass.replace(/([?!@#$%^&*()=+,.<>'":;\[\]\/|~`{}\\])/g, '\\$1');
  5708. };
  5709. ChartInternal.prototype.selectorTarget = function (id, prefix) {
  5710. return (prefix || '') + '.' + CLASS.target + this.getTargetSelectorSuffix(id);
  5711. };
  5712. ChartInternal.prototype.selectorTargets = function (ids, prefix) {
  5713. var $$ = this;
  5714. ids = ids || [];
  5715. return ids.length
  5716. ? ids.map(function (id) {
  5717. return $$.selectorTarget(id, prefix);
  5718. })
  5719. : null;
  5720. };
  5721. ChartInternal.prototype.selectorLegend = function (id) {
  5722. return '.' + CLASS.legendItem + this.getTargetSelectorSuffix(id);
  5723. };
  5724. ChartInternal.prototype.selectorLegends = function (ids) {
  5725. var $$ = this;
  5726. return ids && ids.length
  5727. ? ids.map(function (id) {
  5728. return $$.selectorLegend(id);
  5729. })
  5730. : null;
  5731. };
  5732. ChartInternal.prototype.getClipPath = function (id) {
  5733. return 'url(' + (isIE(9) ? '' : document.URL.split('#')[0]) + '#' + id + ')';
  5734. };
  5735. ChartInternal.prototype.appendClip = function (parent, id) {
  5736. return parent
  5737. .append('clipPath')
  5738. .attr('id', id)
  5739. .append('rect');
  5740. };
  5741. ChartInternal.prototype.getAxisClipX = function (forHorizontal) {
  5742. // axis line width + padding for left
  5743. var left = Math.max(30, this.margin.left);
  5744. return forHorizontal ? -(1 + left) : -(left - 1);
  5745. };
  5746. ChartInternal.prototype.getAxisClipY = function (forHorizontal) {
  5747. return forHorizontal ? -20 : -this.margin.top;
  5748. };
  5749. ChartInternal.prototype.getXAxisClipX = function () {
  5750. var $$ = this;
  5751. return $$.getAxisClipX(!$$.config.axis_rotated);
  5752. };
  5753. ChartInternal.prototype.getXAxisClipY = function () {
  5754. var $$ = this;
  5755. return $$.getAxisClipY(!$$.config.axis_rotated);
  5756. };
  5757. ChartInternal.prototype.getYAxisClipX = function () {
  5758. var $$ = this;
  5759. return $$.config.axis_y_inner ? -1 : $$.getAxisClipX($$.config.axis_rotated);
  5760. };
  5761. ChartInternal.prototype.getYAxisClipY = function () {
  5762. var $$ = this;
  5763. return $$.getAxisClipY($$.config.axis_rotated);
  5764. };
  5765. ChartInternal.prototype.getAxisClipWidth = function (forHorizontal) {
  5766. var $$ = this, left = Math.max(30, $$.margin.left), right = Math.max(30, $$.margin.right);
  5767. // width + axis line width + padding for left/right
  5768. return forHorizontal ? $$.width + 2 + left + right : $$.margin.left + 20;
  5769. };
  5770. ChartInternal.prototype.getAxisClipHeight = function (forHorizontal) {
  5771. // less than 20 is not enough to show the axis label 'outer' without legend
  5772. return ((forHorizontal ? this.margin.bottom : this.margin.top + this.height) + 20);
  5773. };
  5774. ChartInternal.prototype.getXAxisClipWidth = function () {
  5775. var $$ = this;
  5776. return $$.getAxisClipWidth(!$$.config.axis_rotated);
  5777. };
  5778. ChartInternal.prototype.getXAxisClipHeight = function () {
  5779. var $$ = this;
  5780. return $$.getAxisClipHeight(!$$.config.axis_rotated);
  5781. };
  5782. ChartInternal.prototype.getYAxisClipWidth = function () {
  5783. var $$ = this;
  5784. return ($$.getAxisClipWidth($$.config.axis_rotated) +
  5785. ($$.config.axis_y_inner ? 20 : 0));
  5786. };
  5787. ChartInternal.prototype.getYAxisClipHeight = function () {
  5788. var $$ = this;
  5789. return $$.getAxisClipHeight($$.config.axis_rotated);
  5790. };
  5791. ChartInternal.prototype.generateColor = function () {
  5792. var $$ = this, config = $$.config, d3 = $$.d3, colors = config.data_colors, pattern = notEmpty(config.color_pattern)
  5793. ? config.color_pattern
  5794. : d3.schemeCategory10, callback = config.data_color, ids = [];
  5795. return function (d) {
  5796. var id = d.id || (d.data && d.data.id) || d, color;
  5797. // if callback function is provided
  5798. if (colors[id] instanceof Function) {
  5799. color = colors[id](d);
  5800. }
  5801. // if specified, choose that color
  5802. else if (colors[id]) {
  5803. color = colors[id];
  5804. }
  5805. // if not specified, choose from pattern
  5806. else {
  5807. if (ids.indexOf(id) < 0) {
  5808. ids.push(id);
  5809. }
  5810. color = pattern[ids.indexOf(id) % pattern.length];
  5811. colors[id] = color;
  5812. }
  5813. return callback instanceof Function ? callback(color, d) : color;
  5814. };
  5815. };
  5816. ChartInternal.prototype.generateLevelColor = function () {
  5817. var $$ = this, config = $$.config, colors = config.color_pattern, threshold = config.color_threshold, asValue = threshold.unit === 'value', values = threshold.values && threshold.values.length ? threshold.values : [], max = threshold.max || 100;
  5818. return notEmpty(threshold) && notEmpty(colors)
  5819. ? function (value) {
  5820. var i, v, color = colors[colors.length - 1];
  5821. for (i = 0; i < values.length; i++) {
  5822. v = asValue ? value : (value * 100) / max;
  5823. if (v < values[i]) {
  5824. color = colors[i];
  5825. break;
  5826. }
  5827. }
  5828. return color;
  5829. }
  5830. : null;
  5831. };
  5832. ChartInternal.prototype.getDefaultConfig = function () {
  5833. var config = {
  5834. bindto: '#chart',
  5835. svg_classname: undefined,
  5836. size_width: undefined,
  5837. size_height: undefined,
  5838. padding_left: undefined,
  5839. padding_right: undefined,
  5840. padding_top: undefined,
  5841. padding_bottom: undefined,
  5842. resize_auto: true,
  5843. zoom_enabled: false,
  5844. zoom_initialRange: undefined,
  5845. zoom_type: 'scroll',
  5846. zoom_disableDefaultBehavior: false,
  5847. zoom_privileged: false,
  5848. zoom_rescale: false,
  5849. zoom_onzoom: function () { },
  5850. zoom_onzoomstart: function () { },
  5851. zoom_onzoomend: function () { },
  5852. zoom_x_min: undefined,
  5853. zoom_x_max: undefined,
  5854. interaction_brighten: true,
  5855. interaction_enabled: true,
  5856. onmouseover: function () { },
  5857. onmouseout: function () { },
  5858. onresize: function () { },
  5859. onresized: function () { },
  5860. oninit: function () { },
  5861. onrendered: function () { },
  5862. transition_duration: 350,
  5863. data_epochs: 'epochs',
  5864. data_x: undefined,
  5865. data_xs: {},
  5866. data_xFormat: '%Y-%m-%d',
  5867. data_xLocaltime: true,
  5868. data_xSort: true,
  5869. data_idConverter: function (id) {
  5870. return id;
  5871. },
  5872. data_names: {},
  5873. data_classes: {},
  5874. data_groups: [],
  5875. data_axes: {},
  5876. data_type: undefined,
  5877. data_types: {},
  5878. data_labels: {},
  5879. data_order: 'desc',
  5880. data_regions: {},
  5881. data_color: undefined,
  5882. data_colors: {},
  5883. data_hide: false,
  5884. data_filter: undefined,
  5885. data_selection_enabled: false,
  5886. data_selection_grouped: false,
  5887. data_selection_isselectable: function () {
  5888. return true;
  5889. },
  5890. data_selection_multiple: true,
  5891. data_selection_draggable: false,
  5892. data_stack_normalize: false,
  5893. data_onclick: function () { },
  5894. data_onmouseover: function () { },
  5895. data_onmouseout: function () { },
  5896. data_onselected: function () { },
  5897. data_onunselected: function () { },
  5898. data_url: undefined,
  5899. data_headers: undefined,
  5900. data_json: undefined,
  5901. data_rows: undefined,
  5902. data_columns: undefined,
  5903. data_mimeType: undefined,
  5904. data_keys: undefined,
  5905. // configuration for no plot-able data supplied.
  5906. data_empty_label_text: '',
  5907. // subchart
  5908. subchart_show: false,
  5909. subchart_size_height: 60,
  5910. subchart_axis_x_show: true,
  5911. subchart_onbrush: function () { },
  5912. // color
  5913. color_pattern: [],
  5914. color_threshold: {},
  5915. // legend
  5916. legend_show: true,
  5917. legend_hide: false,
  5918. legend_position: 'bottom',
  5919. legend_inset_anchor: 'top-left',
  5920. legend_inset_x: 10,
  5921. legend_inset_y: 0,
  5922. legend_inset_step: undefined,
  5923. legend_item_onclick: undefined,
  5924. legend_item_onmouseover: undefined,
  5925. legend_item_onmouseout: undefined,
  5926. legend_equally: false,
  5927. legend_padding: 0,
  5928. legend_item_tile_width: 10,
  5929. legend_item_tile_height: 10,
  5930. // axis
  5931. axis_rotated: false,
  5932. axis_x_show: true,
  5933. axis_x_type: 'indexed',
  5934. axis_x_localtime: true,
  5935. axis_x_categories: [],
  5936. axis_x_tick_centered: false,
  5937. axis_x_tick_format: undefined,
  5938. axis_x_tick_culling: {},
  5939. axis_x_tick_culling_max: 10,
  5940. axis_x_tick_count: undefined,
  5941. axis_x_tick_fit: true,
  5942. axis_x_tick_values: null,
  5943. axis_x_tick_rotate: 0,
  5944. axis_x_tick_outer: true,
  5945. axis_x_tick_multiline: true,
  5946. axis_x_tick_multilineMax: 0,
  5947. axis_x_tick_width: null,
  5948. axis_x_max: undefined,
  5949. axis_x_min: undefined,
  5950. axis_x_padding: {},
  5951. axis_x_height: undefined,
  5952. axis_x_selection: undefined,
  5953. axis_x_label: {},
  5954. axis_x_inner: undefined,
  5955. axis_y_show: true,
  5956. axis_y_type: 'linear',
  5957. axis_y_max: undefined,
  5958. axis_y_min: undefined,
  5959. axis_y_inverted: false,
  5960. axis_y_center: undefined,
  5961. axis_y_inner: undefined,
  5962. axis_y_label: {},
  5963. axis_y_tick_format: undefined,
  5964. axis_y_tick_outer: true,
  5965. axis_y_tick_values: null,
  5966. axis_y_tick_rotate: 0,
  5967. axis_y_tick_count: undefined,
  5968. axis_y_tick_time_type: undefined,
  5969. axis_y_tick_time_interval: undefined,
  5970. axis_y_padding: {},
  5971. axis_y_default: undefined,
  5972. axis_y2_show: false,
  5973. axis_y2_type: 'linear',
  5974. axis_y2_max: undefined,
  5975. axis_y2_min: undefined,
  5976. axis_y2_inverted: false,
  5977. axis_y2_center: undefined,
  5978. axis_y2_inner: undefined,
  5979. axis_y2_label: {},
  5980. axis_y2_tick_format: undefined,
  5981. axis_y2_tick_outer: true,
  5982. axis_y2_tick_values: null,
  5983. axis_y2_tick_count: undefined,
  5984. axis_y2_padding: {},
  5985. axis_y2_default: undefined,
  5986. // grid
  5987. grid_x_show: false,
  5988. grid_x_type: 'tick',
  5989. grid_x_lines: [],
  5990. grid_y_show: false,
  5991. // not used
  5992. // grid_y_type: 'tick',
  5993. grid_y_lines: [],
  5994. grid_y_ticks: 10,
  5995. grid_focus_show: true,
  5996. grid_lines_front: true,
  5997. // point - point of each data
  5998. point_show: true,
  5999. point_r: 2.5,
  6000. point_sensitivity: 10,
  6001. point_focus_expand_enabled: true,
  6002. point_focus_expand_r: undefined,
  6003. point_select_r: undefined,
  6004. // line
  6005. line_connectNull: false,
  6006. line_step_type: 'step',
  6007. // bar
  6008. bar_width: undefined,
  6009. bar_width_ratio: 0.6,
  6010. bar_width_max: undefined,
  6011. bar_zerobased: true,
  6012. bar_space: 0,
  6013. // area
  6014. area_zerobased: true,
  6015. area_above: false,
  6016. // pie
  6017. pie_label_show: true,
  6018. pie_label_format: undefined,
  6019. pie_label_threshold: 0.05,
  6020. pie_label_ratio: undefined,
  6021. pie_expand: {},
  6022. pie_expand_duration: 50,
  6023. pie_padAngle: 0,
  6024. // gauge
  6025. gauge_fullCircle: false,
  6026. gauge_label_show: true,
  6027. gauge_labelLine_show: true,
  6028. gauge_label_format: undefined,
  6029. gauge_min: 0,
  6030. gauge_max: 100,
  6031. gauge_startingAngle: (-1 * Math.PI) / 2,
  6032. gauge_label_extents: undefined,
  6033. gauge_units: undefined,
  6034. gauge_width: undefined,
  6035. gauge_arcs_minWidth: 5,
  6036. gauge_expand: {},
  6037. gauge_expand_duration: 50,
  6038. // donut
  6039. donut_label_show: true,
  6040. donut_label_format: undefined,
  6041. donut_label_threshold: 0.05,
  6042. donut_label_ratio: undefined,
  6043. donut_width: undefined,
  6044. donut_title: '',
  6045. donut_expand: {},
  6046. donut_expand_duration: 50,
  6047. donut_padAngle: 0,
  6048. // spline
  6049. spline_interpolation_type: 'cardinal',
  6050. // stanford
  6051. stanford_lines: [],
  6052. stanford_regions: [],
  6053. stanford_texts: [],
  6054. stanford_scaleMin: undefined,
  6055. stanford_scaleMax: undefined,
  6056. stanford_scaleWidth: undefined,
  6057. stanford_scaleFormat: undefined,
  6058. stanford_scaleValues: undefined,
  6059. stanford_colors: undefined,
  6060. stanford_padding: {
  6061. top: 0,
  6062. right: 0,
  6063. bottom: 0,
  6064. left: 0
  6065. },
  6066. // region - region to change style
  6067. regions: [],
  6068. // tooltip - show when mouseover on each data
  6069. tooltip_show: true,
  6070. tooltip_grouped: true,
  6071. tooltip_order: undefined,
  6072. tooltip_format_title: undefined,
  6073. tooltip_format_name: undefined,
  6074. tooltip_format_value: undefined,
  6075. tooltip_horizontal: undefined,
  6076. tooltip_position: undefined,
  6077. tooltip_contents: function (d, defaultTitleFormat, defaultValueFormat, color) {
  6078. return this.getTooltipContent
  6079. ? this.getTooltipContent(d, defaultTitleFormat, defaultValueFormat, color)
  6080. : '';
  6081. },
  6082. tooltip_init_show: false,
  6083. tooltip_init_x: 0,
  6084. tooltip_init_position: { top: '0px', left: '50px' },
  6085. tooltip_onshow: function () { },
  6086. tooltip_onhide: function () { },
  6087. // title
  6088. title_text: undefined,
  6089. title_padding: {
  6090. top: 0,
  6091. right: 0,
  6092. bottom: 0,
  6093. left: 0
  6094. },
  6095. title_position: 'top-center'
  6096. };
  6097. Object.keys(this.additionalConfig).forEach(function (key) {
  6098. config[key] = this.additionalConfig[key];
  6099. }, this);
  6100. return config;
  6101. };
  6102. ChartInternal.prototype.additionalConfig = {};
  6103. ChartInternal.prototype.loadConfig = function (config) {
  6104. var this_config = this.config, target, keys, read;
  6105. function find() {
  6106. var key = keys.shift();
  6107. // console.log("key =>", key, ", target =>", target);
  6108. if (key && target && typeof target === 'object' && key in target) {
  6109. target = target[key];
  6110. return find();
  6111. }
  6112. else if (!key) {
  6113. return target;
  6114. }
  6115. else {
  6116. return undefined;
  6117. }
  6118. }
  6119. Object.keys(this_config).forEach(function (key) {
  6120. target = config;
  6121. keys = key.split('_');
  6122. read = find();
  6123. // console.log("CONFIG : ", key, read);
  6124. if (isDefined(read)) {
  6125. this_config[key] = read;
  6126. }
  6127. });
  6128. };
  6129. ChartInternal.prototype.convertUrlToData = function (url, mimeType, headers, keys, done) {
  6130. var $$ = this, type = mimeType ? mimeType : 'csv', f, converter;
  6131. if (type === 'json') {
  6132. f = $$.d3.json;
  6133. converter = $$.convertJsonToData;
  6134. }
  6135. else if (type === 'tsv') {
  6136. f = $$.d3.tsv;
  6137. converter = $$.convertXsvToData;
  6138. }
  6139. else {
  6140. f = $$.d3.csv;
  6141. converter = $$.convertXsvToData;
  6142. }
  6143. f(url, headers)
  6144. .then(function (data) {
  6145. done.call($$, converter.call($$, data, keys));
  6146. })
  6147. .catch(function (error) {
  6148. throw error;
  6149. });
  6150. };
  6151. ChartInternal.prototype.convertXsvToData = function (xsv) {
  6152. var keys = xsv.columns, rows = xsv;
  6153. if (rows.length === 0) {
  6154. return {
  6155. keys: keys,
  6156. rows: [keys.reduce(function (row, key) {
  6157. var _a;
  6158. return Object.assign(row, (_a = {}, _a[key] = null, _a));
  6159. }, {})]
  6160. };
  6161. }
  6162. else {
  6163. // [].concat() is to convert result into a plain array otherwise
  6164. // test is not happy because rows have properties.
  6165. return { keys: keys, rows: [].concat(xsv) };
  6166. }
  6167. };
  6168. ChartInternal.prototype.convertJsonToData = function (json, keys) {
  6169. var $$ = this, new_rows = [], targetKeys, data;
  6170. if (keys) {
  6171. // when keys specified, json would be an array that includes objects
  6172. if (keys.x) {
  6173. targetKeys = keys.value.concat(keys.x);
  6174. $$.config.data_x = keys.x;
  6175. }
  6176. else {
  6177. targetKeys = keys.value;
  6178. }
  6179. new_rows.push(targetKeys);
  6180. json.forEach(function (o) {
  6181. var new_row = [];
  6182. targetKeys.forEach(function (key) {
  6183. // convert undefined to null because undefined data will be removed in convertDataToTargets()
  6184. var v = $$.findValueInJson(o, key);
  6185. if (isUndefined(v)) {
  6186. v = null;
  6187. }
  6188. new_row.push(v);
  6189. });
  6190. new_rows.push(new_row);
  6191. });
  6192. data = $$.convertRowsToData(new_rows);
  6193. }
  6194. else {
  6195. Object.keys(json).forEach(function (key) {
  6196. new_rows.push([key].concat(json[key]));
  6197. });
  6198. data = $$.convertColumnsToData(new_rows);
  6199. }
  6200. return data;
  6201. };
  6202. /**
  6203. * Finds value from the given nested object by the given path.
  6204. * If it's not found, then this returns undefined.
  6205. * @param {Object} object the object
  6206. * @param {string} path the path
  6207. */
  6208. ChartInternal.prototype.findValueInJson = function (object, path) {
  6209. if (path in object) {
  6210. // If object has a key that contains . or [], return the key's value
  6211. // instead of searching for an inner object.
  6212. // See https://github.com/c3js/c3/issues/1691 for details.
  6213. return object[path];
  6214. }
  6215. path = path.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties (replace [] with .)
  6216. path = path.replace(/^\./, ''); // strip a leading dot
  6217. var pathArray = path.split('.');
  6218. for (var i = 0; i < pathArray.length; ++i) {
  6219. var k = pathArray[i];
  6220. if (k in object) {
  6221. object = object[k];
  6222. }
  6223. else {
  6224. return;
  6225. }
  6226. }
  6227. return object;
  6228. };
  6229. /**
  6230. * Converts the rows to normalized data.
  6231. * @param {any[][]} rows The row data
  6232. * @return {Object}
  6233. */
  6234. ChartInternal.prototype.convertRowsToData = function (rows) {
  6235. var newRows = [];
  6236. var keys = rows[0];
  6237. for (var i = 1; i < rows.length; i++) {
  6238. var newRow = {};
  6239. for (var j = 0; j < rows[i].length; j++) {
  6240. if (isUndefined(rows[i][j])) {
  6241. throw new Error('Source data is missing a component at (' + i + ',' + j + ')!');
  6242. }
  6243. newRow[keys[j]] = rows[i][j];
  6244. }
  6245. newRows.push(newRow);
  6246. }
  6247. return { keys: keys, rows: newRows };
  6248. };
  6249. /**
  6250. * Converts the columns to normalized data.
  6251. * @param {any[][]} columns The column data
  6252. * @return {Object}
  6253. */
  6254. ChartInternal.prototype.convertColumnsToData = function (columns) {
  6255. var newRows = [];
  6256. var keys = [];
  6257. for (var i = 0; i < columns.length; i++) {
  6258. var key = columns[i][0];
  6259. for (var j = 1; j < columns[i].length; j++) {
  6260. if (isUndefined(newRows[j - 1])) {
  6261. newRows[j - 1] = {};
  6262. }
  6263. if (isUndefined(columns[i][j])) {
  6264. throw new Error('Source data is missing a component at (' + i + ',' + j + ')!');
  6265. }
  6266. newRows[j - 1][key] = columns[i][j];
  6267. }
  6268. keys.push(key);
  6269. }
  6270. return { keys: keys, rows: newRows };
  6271. };
  6272. /**
  6273. * Converts the data format into the target format.
  6274. * @param {!Object} data
  6275. * @param {!Array} data.keys Ordered list of target IDs.
  6276. * @param {!Array} data.rows Rows of data to convert.
  6277. * @param {boolean} appendXs True to append to $$.data.xs, False to replace.
  6278. * @return {!Array}
  6279. */
  6280. ChartInternal.prototype.convertDataToTargets = function (data, appendXs) {
  6281. var $$ = this, config = $$.config, targets, ids, xs, keys, epochs;
  6282. // handles format where keys are not orderly provided
  6283. if (isArray(data)) {
  6284. keys = Object.keys(data[0]);
  6285. }
  6286. else {
  6287. keys = data.keys;
  6288. data = data.rows;
  6289. }
  6290. xs = keys.filter($$.isX, $$);
  6291. if (!$$.isStanfordGraphType()) {
  6292. ids = keys.filter($$.isNotX, $$);
  6293. }
  6294. else {
  6295. epochs = keys.filter($$.isEpochs, $$);
  6296. ids = keys.filter($$.isNotXAndNotEpochs, $$);
  6297. if (xs.length !== 1 || epochs.length !== 1 || ids.length !== 1) {
  6298. throw new Error("You must define the 'x' key name and the 'epochs' for Stanford Diagrams");
  6299. }
  6300. }
  6301. // save x for update data by load when custom x and c3.x API
  6302. ids.forEach(function (id) {
  6303. var xKey = $$.getXKey(id);
  6304. if ($$.isCustomX() || $$.isTimeSeries()) {
  6305. // if included in input data
  6306. if (xs.indexOf(xKey) >= 0) {
  6307. $$.data.xs[id] = (appendXs && $$.data.xs[id]
  6308. ? $$.data.xs[id]
  6309. : []).concat(data
  6310. .map(function (d) {
  6311. return d[xKey];
  6312. })
  6313. .filter(isValue)
  6314. .map(function (rawX, i) {
  6315. return $$.generateTargetX(rawX, id, i);
  6316. }));
  6317. }
  6318. // if not included in input data, find from preloaded data of other id's x
  6319. else if (config.data_x) {
  6320. $$.data.xs[id] = $$.getOtherTargetXs();
  6321. }
  6322. // if not included in input data, find from preloaded data
  6323. else if (notEmpty(config.data_xs)) {
  6324. $$.data.xs[id] = $$.getXValuesOfXKey(xKey, $$.data.targets);
  6325. }
  6326. // MEMO: if no x included, use same x of current will be used
  6327. }
  6328. else {
  6329. $$.data.xs[id] = data.map(function (d, i) {
  6330. return i;
  6331. });
  6332. }
  6333. });
  6334. // check x is defined
  6335. ids.forEach(function (id) {
  6336. if (!$$.data.xs[id]) {
  6337. throw new Error('x is not defined for id = "' + id + '".');
  6338. }
  6339. });
  6340. // convert to target
  6341. targets = ids.map(function (id, index) {
  6342. var convertedId = config.data_idConverter(id);
  6343. return {
  6344. id: convertedId,
  6345. id_org: id,
  6346. values: data
  6347. .map(function (d, i) {
  6348. var xKey = $$.getXKey(id), rawX = d[xKey], value = d[id] !== null && !isNaN(d[id]) ? +d[id] : null, x, returnData;
  6349. // use x as categories if custom x and categorized
  6350. if ($$.isCustomX() && $$.isCategorized() && !isUndefined(rawX)) {
  6351. if (index === 0 && i === 0) {
  6352. config.axis_x_categories = [];
  6353. }
  6354. x = config.axis_x_categories.indexOf(rawX);
  6355. if (x === -1) {
  6356. x = config.axis_x_categories.length;
  6357. config.axis_x_categories.push(rawX);
  6358. }
  6359. }
  6360. else {
  6361. x = $$.generateTargetX(rawX, id, i);
  6362. }
  6363. // mark as x = undefined if value is undefined and filter to remove after mapped
  6364. if (isUndefined(d[id]) || $$.data.xs[id].length <= i) {
  6365. x = undefined;
  6366. }
  6367. returnData = { x: x, value: value, id: convertedId };
  6368. if ($$.isStanfordGraphType()) {
  6369. returnData.epochs = d[epochs];
  6370. }
  6371. return returnData;
  6372. })
  6373. .filter(function (v) {
  6374. return isDefined(v.x);
  6375. })
  6376. };
  6377. });
  6378. // finish targets
  6379. targets.forEach(function (t) {
  6380. var i;
  6381. // sort values by its x
  6382. if (config.data_xSort) {
  6383. t.values = t.values.sort(function (v1, v2) {
  6384. var x1 = v1.x || v1.x === 0 ? v1.x : Infinity, x2 = v2.x || v2.x === 0 ? v2.x : Infinity;
  6385. return x1 - x2;
  6386. });
  6387. }
  6388. // indexing each value
  6389. i = 0;
  6390. t.values.forEach(function (v) {
  6391. v.index = i++;
  6392. });
  6393. // this needs to be sorted because its index and value.index is identical
  6394. $$.data.xs[t.id].sort(function (v1, v2) {
  6395. return v1 - v2;
  6396. });
  6397. });
  6398. // cache information about values
  6399. $$.hasNegativeValue = $$.hasNegativeValueInTargets(targets);
  6400. $$.hasPositiveValue = $$.hasPositiveValueInTargets(targets);
  6401. // set target types
  6402. if (config.data_type) {
  6403. $$.setTargetType($$.mapToIds(targets).filter(function (id) {
  6404. return !(id in config.data_types);
  6405. }), config.data_type);
  6406. }
  6407. // cache as original id keyed
  6408. targets.forEach(function (d) {
  6409. $$.addCache(d.id_org, d);
  6410. });
  6411. return targets;
  6412. };
  6413. ChartInternal.prototype.isEpochs = function (key) {
  6414. var $$ = this, config = $$.config;
  6415. return config.data_epochs && key === config.data_epochs;
  6416. };
  6417. ChartInternal.prototype.isX = function (key) {
  6418. var $$ = this, config = $$.config;
  6419. return ((config.data_x && key === config.data_x) ||
  6420. (notEmpty(config.data_xs) && hasValue(config.data_xs, key)));
  6421. };
  6422. ChartInternal.prototype.isNotX = function (key) {
  6423. return !this.isX(key);
  6424. };
  6425. ChartInternal.prototype.isNotXAndNotEpochs = function (key) {
  6426. return !this.isX(key) && !this.isEpochs(key);
  6427. };
  6428. /**
  6429. * Returns whether the normalized stack option is enabled or not.
  6430. *
  6431. * To be enabled it must also have data.groups defined.
  6432. *
  6433. * @return {boolean}
  6434. */
  6435. ChartInternal.prototype.isStackNormalized = function () {
  6436. return this.config.data_stack_normalize && this.config.data_groups.length > 0;
  6437. };
  6438. /**
  6439. * Returns whether the axis is normalized or not.
  6440. *
  6441. * An axis is normalized as long as one of its associated target
  6442. * is normalized.
  6443. *
  6444. * @param axisId Axis ID (y or y2)
  6445. * @return {Boolean}
  6446. */
  6447. ChartInternal.prototype.isAxisNormalized = function (axisId) {
  6448. var $$ = this;
  6449. if (!$$.isStackNormalized()) {
  6450. // shortcut
  6451. return false;
  6452. }
  6453. return $$.data.targets
  6454. .filter(function (target) { return $$.axis.getId(target.id) === axisId; })
  6455. .some(function (target) { return $$.isTargetNormalized(target.id); });
  6456. };
  6457. /**
  6458. * Returns whether the values for this target ID is normalized or not.
  6459. *
  6460. * To be normalized the option needs to be enabled and target needs
  6461. * to be defined in `data.groups`.
  6462. *
  6463. * @param targetId ID of the target
  6464. * @return {Boolean} True if the target is normalized, false otherwise.
  6465. */
  6466. ChartInternal.prototype.isTargetNormalized = function (targetId) {
  6467. var $$ = this;
  6468. return ($$.isStackNormalized() &&
  6469. $$.config.data_groups.some(function (group) { return group.includes(targetId); }));
  6470. };
  6471. ChartInternal.prototype.getXKey = function (id) {
  6472. var $$ = this, config = $$.config;
  6473. return config.data_x
  6474. ? config.data_x
  6475. : notEmpty(config.data_xs)
  6476. ? config.data_xs[id]
  6477. : null;
  6478. };
  6479. /**
  6480. * Get sum of visible data per index for given axis.
  6481. *
  6482. * Expect axisId to be either 'y' or 'y2'.
  6483. *
  6484. * @private
  6485. * @param axisId Compute sum for data associated to given axis.
  6486. * @return {Array}
  6487. */
  6488. ChartInternal.prototype.getTotalPerIndex = function (axisId) {
  6489. var $$ = this;
  6490. if (!$$.isStackNormalized()) {
  6491. return null;
  6492. }
  6493. var cached = $$.getFromCache('getTotalPerIndex');
  6494. if (cached !== undefined) {
  6495. return cached[axisId];
  6496. }
  6497. var sum = { y: [], y2: [] };
  6498. $$.data.targets
  6499. // keep only target that are normalized
  6500. .filter(function (target) { return $$.isTargetNormalized(target.id); })
  6501. // keep only target that are visible
  6502. .filter(function (target) { return $$.isTargetToShow(target.id); })
  6503. // compute sum per axis
  6504. .forEach(function (target) {
  6505. var sumByAxis = sum[$$.axis.getId(target.id)];
  6506. target.values.forEach(function (v, i) {
  6507. if (!sumByAxis[i]) {
  6508. sumByAxis[i] = 0;
  6509. }
  6510. sumByAxis[i] += isNumber(v.value) ? v.value : 0;
  6511. });
  6512. });
  6513. $$.addToCache('getTotalPerIndex', sum);
  6514. return sum[axisId];
  6515. };
  6516. /**
  6517. * Get sum of visible data.
  6518. *
  6519. * Should be used for normalised data only since all values
  6520. * are expected to be positive.
  6521. *
  6522. * @private
  6523. * @return {Number}
  6524. */
  6525. ChartInternal.prototype.getTotalDataSum = function () {
  6526. var $$ = this;
  6527. var cached = $$.getFromCache('getTotalDataSum');
  6528. if (cached !== undefined) {
  6529. return cached;
  6530. }
  6531. var totalDataSum = flattenArray($$.data.targets
  6532. .filter(function (target) { return $$.isTargetToShow(target.id); })
  6533. .map(function (target) { return target.values; }))
  6534. .map(function (d) { return d.value; })
  6535. .reduce(function (p, c) { return p + c; }, 0);
  6536. $$.addToCache('getTotalDataSum', totalDataSum);
  6537. return totalDataSum;
  6538. };
  6539. ChartInternal.prototype.getXValuesOfXKey = function (key, targets) {
  6540. var $$ = this, xValues, ids = targets && notEmpty(targets) ? $$.mapToIds(targets) : [];
  6541. ids.forEach(function (id) {
  6542. if ($$.getXKey(id) === key) {
  6543. xValues = $$.data.xs[id];
  6544. }
  6545. });
  6546. return xValues;
  6547. };
  6548. ChartInternal.prototype.getXValue = function (id, i) {
  6549. var $$ = this;
  6550. return id in $$.data.xs && $$.data.xs[id] && isValue($$.data.xs[id][i])
  6551. ? $$.data.xs[id][i]
  6552. : i;
  6553. };
  6554. ChartInternal.prototype.getOtherTargetXs = function () {
  6555. var $$ = this, idsForX = Object.keys($$.data.xs);
  6556. return idsForX.length ? $$.data.xs[idsForX[0]] : null;
  6557. };
  6558. ChartInternal.prototype.getOtherTargetX = function (index) {
  6559. var xs = this.getOtherTargetXs();
  6560. return xs && index < xs.length ? xs[index] : null;
  6561. };
  6562. ChartInternal.prototype.addXs = function (xs) {
  6563. var $$ = this;
  6564. Object.keys(xs).forEach(function (id) {
  6565. $$.config.data_xs[id] = xs[id];
  6566. });
  6567. };
  6568. ChartInternal.prototype.addName = function (data) {
  6569. var $$ = this, name;
  6570. if (data) {
  6571. name = $$.config.data_names[data.id];
  6572. data.name = name !== undefined ? name : data.id;
  6573. }
  6574. return data;
  6575. };
  6576. ChartInternal.prototype.getValueOnIndex = function (values, index) {
  6577. var valueOnIndex = values.filter(function (v) {
  6578. return v.index === index;
  6579. });
  6580. return valueOnIndex.length ? valueOnIndex[0] : null;
  6581. };
  6582. ChartInternal.prototype.updateTargetX = function (targets, x) {
  6583. var $$ = this;
  6584. targets.forEach(function (t) {
  6585. t.values.forEach(function (v, i) {
  6586. v.x = $$.generateTargetX(x[i], t.id, i);
  6587. });
  6588. $$.data.xs[t.id] = x;
  6589. });
  6590. };
  6591. ChartInternal.prototype.updateTargetXs = function (targets, xs) {
  6592. var $$ = this;
  6593. targets.forEach(function (t) {
  6594. if (xs[t.id]) {
  6595. $$.updateTargetX([t], xs[t.id]);
  6596. }
  6597. });
  6598. };
  6599. ChartInternal.prototype.generateTargetX = function (rawX, id, index) {
  6600. var $$ = this, x;
  6601. if ($$.isTimeSeries()) {
  6602. x = rawX ? $$.parseDate(rawX) : $$.parseDate($$.getXValue(id, index));
  6603. }
  6604. else if ($$.isCustomX() && !$$.isCategorized()) {
  6605. x = isValue(rawX) ? +rawX : $$.getXValue(id, index);
  6606. }
  6607. else {
  6608. x = index;
  6609. }
  6610. return x;
  6611. };
  6612. ChartInternal.prototype.cloneTarget = function (target) {
  6613. return {
  6614. id: target.id,
  6615. id_org: target.id_org,
  6616. values: target.values.map(function (d) {
  6617. return {
  6618. x: d.x,
  6619. value: d.value,
  6620. id: d.id
  6621. };
  6622. })
  6623. };
  6624. };
  6625. ChartInternal.prototype.getMaxDataCount = function () {
  6626. var $$ = this;
  6627. return $$.d3.max($$.data.targets, function (t) {
  6628. return t.values.length;
  6629. });
  6630. };
  6631. ChartInternal.prototype.mapToIds = function (targets) {
  6632. return targets.map(function (d) {
  6633. return d.id;
  6634. });
  6635. };
  6636. ChartInternal.prototype.mapToTargetIds = function (ids) {
  6637. var $$ = this;
  6638. return ids ? [].concat(ids) : $$.mapToIds($$.data.targets);
  6639. };
  6640. ChartInternal.prototype.hasTarget = function (targets, id) {
  6641. var ids = this.mapToIds(targets), i;
  6642. for (i = 0; i < ids.length; i++) {
  6643. if (ids[i] === id) {
  6644. return true;
  6645. }
  6646. }
  6647. return false;
  6648. };
  6649. ChartInternal.prototype.isTargetToShow = function (targetId) {
  6650. return this.hiddenTargetIds.indexOf(targetId) < 0;
  6651. };
  6652. ChartInternal.prototype.isLegendToShow = function (targetId) {
  6653. return this.hiddenLegendIds.indexOf(targetId) < 0;
  6654. };
  6655. /**
  6656. * Returns only visible targets.
  6657. *
  6658. * This is the same as calling {@link filterTargetsToShow} on $$.data.targets.
  6659. *
  6660. * @return {Array}
  6661. */
  6662. ChartInternal.prototype.getTargetsToShow = function () {
  6663. var $$ = this;
  6664. return $$.filterTargetsToShow($$.data.targets);
  6665. };
  6666. ChartInternal.prototype.filterTargetsToShow = function (targets) {
  6667. var $$ = this;
  6668. return targets.filter(function (t) {
  6669. return $$.isTargetToShow(t.id);
  6670. });
  6671. };
  6672. /**
  6673. * @return {Array} Returns all the targets attached to the chart, visible or not
  6674. */
  6675. ChartInternal.prototype.getTargets = function () {
  6676. var $$ = this;
  6677. return $$.data.targets;
  6678. };
  6679. ChartInternal.prototype.mapTargetsToUniqueXs = function (targets) {
  6680. var $$ = this;
  6681. var xs = $$.d3
  6682. .set($$.d3.merge(targets.map(function (t) {
  6683. return t.values.map(function (v) {
  6684. return +v.x;
  6685. });
  6686. })))
  6687. .values();
  6688. xs = $$.isTimeSeries()
  6689. ? xs.map(function (x) {
  6690. return new Date(+x);
  6691. })
  6692. : xs.map(function (x) {
  6693. return +x;
  6694. });
  6695. return xs.sort(function (a, b) {
  6696. return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
  6697. });
  6698. };
  6699. ChartInternal.prototype.addHiddenTargetIds = function (targetIds) {
  6700. targetIds = targetIds instanceof Array ? targetIds : new Array(targetIds);
  6701. for (var i = 0; i < targetIds.length; i++) {
  6702. if (this.hiddenTargetIds.indexOf(targetIds[i]) < 0) {
  6703. this.hiddenTargetIds = this.hiddenTargetIds.concat(targetIds[i]);
  6704. }
  6705. }
  6706. this.resetCache();
  6707. };
  6708. ChartInternal.prototype.removeHiddenTargetIds = function (targetIds) {
  6709. this.hiddenTargetIds = this.hiddenTargetIds.filter(function (id) {
  6710. return targetIds.indexOf(id) < 0;
  6711. });
  6712. this.resetCache();
  6713. };
  6714. ChartInternal.prototype.addHiddenLegendIds = function (targetIds) {
  6715. targetIds = targetIds instanceof Array ? targetIds : new Array(targetIds);
  6716. for (var i = 0; i < targetIds.length; i++) {
  6717. if (this.hiddenLegendIds.indexOf(targetIds[i]) < 0) {
  6718. this.hiddenLegendIds = this.hiddenLegendIds.concat(targetIds[i]);
  6719. }
  6720. }
  6721. };
  6722. ChartInternal.prototype.removeHiddenLegendIds = function (targetIds) {
  6723. this.hiddenLegendIds = this.hiddenLegendIds.filter(function (id) {
  6724. return targetIds.indexOf(id) < 0;
  6725. });
  6726. };
  6727. ChartInternal.prototype.getValuesAsIdKeyed = function (targets) {
  6728. var ys = {};
  6729. targets.forEach(function (t) {
  6730. ys[t.id] = [];
  6731. t.values.forEach(function (v) {
  6732. ys[t.id].push(v.value);
  6733. });
  6734. });
  6735. return ys;
  6736. };
  6737. ChartInternal.prototype.checkValueInTargets = function (targets, checker) {
  6738. var ids = Object.keys(targets), i, j, values;
  6739. for (i = 0; i < ids.length; i++) {
  6740. values = targets[ids[i]].values;
  6741. for (j = 0; j < values.length; j++) {
  6742. if (checker(values[j].value)) {
  6743. return true;
  6744. }
  6745. }
  6746. }
  6747. return false;
  6748. };
  6749. ChartInternal.prototype.hasNegativeValueInTargets = function (targets) {
  6750. return this.checkValueInTargets(targets, function (v) {
  6751. return v < 0;
  6752. });
  6753. };
  6754. ChartInternal.prototype.hasPositiveValueInTargets = function (targets) {
  6755. return this.checkValueInTargets(targets, function (v) {
  6756. return v > 0;
  6757. });
  6758. };
  6759. ChartInternal.prototype.isOrderDesc = function () {
  6760. var config = this.config;
  6761. return (typeof config.data_order === 'string' &&
  6762. config.data_order.toLowerCase() === 'desc');
  6763. };
  6764. ChartInternal.prototype.isOrderAsc = function () {
  6765. var config = this.config;
  6766. return (typeof config.data_order === 'string' &&
  6767. config.data_order.toLowerCase() === 'asc');
  6768. };
  6769. ChartInternal.prototype.getOrderFunction = function () {
  6770. var $$ = this, config = $$.config, orderAsc = $$.isOrderAsc(), orderDesc = $$.isOrderDesc();
  6771. if (orderAsc || orderDesc) {
  6772. var reducer = function (p, c) {
  6773. return p + Math.abs(c.value);
  6774. };
  6775. return function (t1, t2) {
  6776. var t1Sum = t1.values.reduce(reducer, 0), t2Sum = t2.values.reduce(reducer, 0);
  6777. return orderAsc ? t2Sum - t1Sum : t1Sum - t2Sum;
  6778. };
  6779. }
  6780. else if (isFunction(config.data_order)) {
  6781. return config.data_order;
  6782. }
  6783. else if (isArray(config.data_order)) {
  6784. var order = config.data_order;
  6785. return function (t1, t2) {
  6786. return order.indexOf(t1.id) - order.indexOf(t2.id);
  6787. };
  6788. }
  6789. };
  6790. ChartInternal.prototype.orderTargets = function (targets) {
  6791. var fct = this.getOrderFunction();
  6792. if (fct) {
  6793. targets.sort(fct);
  6794. }
  6795. return targets;
  6796. };
  6797. /**
  6798. * Returns all the values from the given targets at the given index.
  6799. *
  6800. * @param {Array} targets
  6801. * @param {Number} index
  6802. * @return {Array}
  6803. */
  6804. ChartInternal.prototype.filterByIndex = function (targets, index) {
  6805. return this.d3.merge(targets.map(function (t) { return t.values.filter(function (v) { return v.index === index; }); }));
  6806. };
  6807. ChartInternal.prototype.filterByX = function (targets, x) {
  6808. return this.d3
  6809. .merge(targets.map(function (t) {
  6810. return t.values;
  6811. }))
  6812. .filter(function (v) {
  6813. return v.x - x === 0;
  6814. });
  6815. };
  6816. ChartInternal.prototype.filterRemoveNull = function (data) {
  6817. return data.filter(function (d) {
  6818. return isValue(d.value);
  6819. });
  6820. };
  6821. ChartInternal.prototype.filterByXDomain = function (targets, xDomain) {
  6822. return targets.map(function (t) {
  6823. return {
  6824. id: t.id,
  6825. id_org: t.id_org,
  6826. values: t.values.filter(function (v) {
  6827. return xDomain[0] <= v.x && v.x <= xDomain[1];
  6828. })
  6829. };
  6830. });
  6831. };
  6832. ChartInternal.prototype.hasDataLabel = function () {
  6833. var config = this.config;
  6834. if (typeof config.data_labels === 'boolean' && config.data_labels) {
  6835. return true;
  6836. }
  6837. else if (typeof config.data_labels === 'object' &&
  6838. notEmpty(config.data_labels)) {
  6839. return true;
  6840. }
  6841. return false;
  6842. };
  6843. ChartInternal.prototype.getDataLabelLength = function (min, max, key) {
  6844. var $$ = this, lengths = [0, 0], paddingCoef = 1.3;
  6845. $$.selectChart
  6846. .select('svg')
  6847. .selectAll('.dummy')
  6848. .data([min, max])
  6849. .enter()
  6850. .append('text')
  6851. .text(function (d) {
  6852. return $$.dataLabelFormat(d.id)(d);
  6853. })
  6854. .each(function (d, i) {
  6855. lengths[i] = getBBox(this)[key] * paddingCoef;
  6856. })
  6857. .remove();
  6858. return lengths;
  6859. };
  6860. /**
  6861. * Returns true if the given data point is not arc type, otherwise false.
  6862. * @param {Object} d The data point
  6863. * @return {boolean}
  6864. */
  6865. ChartInternal.prototype.isNoneArc = function (d) {
  6866. return this.hasTarget(this.data.targets, d.id);
  6867. };
  6868. /**
  6869. * Returns true if the given data point is arc type, otherwise false.
  6870. * @param {Object} d The data point
  6871. * @return {boolean}
  6872. */
  6873. ChartInternal.prototype.isArc = function (d) {
  6874. return 'data' in d && this.hasTarget(this.data.targets, d.data.id);
  6875. };
  6876. /**
  6877. * Find the closest point from the given pos among the given targets or
  6878. * undefined if none satisfies conditions.
  6879. *
  6880. * @param {Array} targets
  6881. * @param {Array} pos An [x,y] coordinate
  6882. * @return {Object|undefined}
  6883. */
  6884. ChartInternal.prototype.findClosestFromTargets = function (targets, pos) {
  6885. var $$ = this;
  6886. // for each target, find the closest point
  6887. var candidates = targets
  6888. .map(function (t) {
  6889. return $$.findClosest(t.values, pos, $$.config.tooltip_horizontal
  6890. ? $$.horizontalDistance.bind($$)
  6891. : $$.dist.bind($$), $$.config.point_sensitivity);
  6892. })
  6893. .filter(function (v) { return v; });
  6894. // returns the closest of candidates
  6895. if (candidates.length === 0) {
  6896. return undefined;
  6897. }
  6898. else if (candidates.length === 1) {
  6899. return candidates[0];
  6900. }
  6901. else {
  6902. return $$.findClosest(candidates, pos, $$.dist.bind($$));
  6903. }
  6904. };
  6905. /**
  6906. * Find the closest point from the x value or undefined if none satisfies conditions.
  6907. *
  6908. * @param {Array} targets
  6909. * @param {Array} x A value on X axis
  6910. * @return {Object|undefined}
  6911. */
  6912. ChartInternal.prototype.findClosestFromTargetsByX = function (targets, x) {
  6913. var closest;
  6914. var diff;
  6915. targets.forEach(function (t) {
  6916. t.values.forEach(function (d) {
  6917. var newDiff = Math.abs(x - d.x);
  6918. if (diff === undefined || newDiff < diff) {
  6919. closest = d;
  6920. diff = newDiff;
  6921. }
  6922. });
  6923. });
  6924. return closest;
  6925. };
  6926. /**
  6927. * Using given compute distance method, returns the closest data point from the
  6928. * given position.
  6929. *
  6930. * Giving optionally a minimum distance to satisfy.
  6931. *
  6932. * @param {Array} dataPoints List of DataPoints
  6933. * @param {Array} pos An [x,y] coordinate
  6934. * @param {Function} computeDist Function to compute distance between 2 points
  6935. * @param {Number} minDist Minimal distance to satisfy
  6936. * @return {Object|undefined} Closest data point
  6937. */
  6938. ChartInternal.prototype.findClosest = function (dataPoints, pos, computeDist, minDist) {
  6939. if (minDist === void 0) { minDist = Infinity; }
  6940. var $$ = this;
  6941. var closest;
  6942. // find closest bar
  6943. dataPoints
  6944. .filter(function (v) { return v && $$.isBarType(v.id); })
  6945. .forEach(function (v) {
  6946. if (!closest) {
  6947. var shape = $$.main
  6948. .select('.' +
  6949. CLASS.bars +
  6950. $$.getTargetSelectorSuffix(v.id) +
  6951. ' .' +
  6952. CLASS.bar +
  6953. '-' +
  6954. v.index)
  6955. .node();
  6956. if ($$.isWithinBar(pos, shape)) {
  6957. closest = v;
  6958. }
  6959. }
  6960. });
  6961. // find closest point from non-bar
  6962. dataPoints
  6963. .filter(function (v) { return v && !$$.isBarType(v.id); })
  6964. .forEach(function (v) {
  6965. var d = computeDist(v, pos);
  6966. if (d < minDist) {
  6967. minDist = d;
  6968. closest = v;
  6969. }
  6970. });
  6971. return closest;
  6972. };
  6973. ChartInternal.prototype.dist = function (data, pos) {
  6974. var $$ = this, config = $$.config, xIndex = config.axis_rotated ? 1 : 0, yIndex = config.axis_rotated ? 0 : 1, y = $$.circleY(data, data.index), x = $$.x(data.x);
  6975. return Math.sqrt(Math.pow(x - pos[xIndex], 2) + Math.pow(y - pos[yIndex], 2));
  6976. };
  6977. ChartInternal.prototype.horizontalDistance = function (data, pos) {
  6978. var $$ = this, config = $$.config, xIndex = config.axis_rotated ? 1 : 0, x = $$.x(data.x);
  6979. return Math.abs(x - pos[xIndex]);
  6980. };
  6981. ChartInternal.prototype.convertValuesToStep = function (values) {
  6982. var converted = [].concat(values), i;
  6983. if (!this.isCategorized()) {
  6984. return values;
  6985. }
  6986. for (i = values.length + 1; 0 < i; i--) {
  6987. converted[i] = converted[i - 1];
  6988. }
  6989. converted[0] = {
  6990. x: converted[0].x - 1,
  6991. value: converted[0].value,
  6992. id: converted[0].id
  6993. };
  6994. converted[values.length + 1] = {
  6995. x: converted[values.length].x + 1,
  6996. value: converted[values.length].value,
  6997. id: converted[values.length].id
  6998. };
  6999. return converted;
  7000. };
  7001. /**
  7002. * Get ratio value
  7003. *
  7004. * @param {String} type Ratio for given type
  7005. * @param {Object} d Data value object
  7006. * @param {Boolean} asPercent Convert the return as percent or not
  7007. * @return {Number} Ratio value
  7008. * @private
  7009. */
  7010. ChartInternal.prototype.getRatio = function (type, d, asPercent) {
  7011. if (asPercent === void 0) { asPercent = false; }
  7012. var $$ = this;
  7013. var api = $$.api;
  7014. var ratio = 0;
  7015. if (d && api.data.shown.call(api).length) {
  7016. ratio = d.ratio || d.value;
  7017. if (type === 'arc') {
  7018. if ($$.hasType('gauge')) {
  7019. ratio =
  7020. (d.endAngle - d.startAngle) /
  7021. (Math.PI * ($$.config.gauge_fullCircle ? 2 : 1));
  7022. }
  7023. else {
  7024. var total = $$.getTotalDataSum();
  7025. ratio = d.value / total;
  7026. }
  7027. }
  7028. else if (type === 'index') {
  7029. var total = $$.getTotalPerIndex($$.axis.getId(d.id));
  7030. d.ratio =
  7031. isNumber(d.value) && total && total[d.index] > 0
  7032. ? d.value / total[d.index]
  7033. : 0;
  7034. ratio = d.ratio;
  7035. }
  7036. }
  7037. return asPercent && ratio ? ratio * 100 : ratio;
  7038. };
  7039. ChartInternal.prototype.updateDataAttributes = function (name, attrs) {
  7040. var $$ = this, config = $$.config, current = config['data_' + name];
  7041. if (typeof attrs === 'undefined') {
  7042. return current;
  7043. }
  7044. Object.keys(attrs).forEach(function (id) {
  7045. current[id] = attrs[id];
  7046. });
  7047. $$.redraw({
  7048. withLegend: true
  7049. });
  7050. return current;
  7051. };
  7052. ChartInternal.prototype.load = function (targets, args) {
  7053. var $$ = this;
  7054. if (targets) {
  7055. // filter loading targets if needed
  7056. if (args.filter) {
  7057. targets = targets.filter(args.filter);
  7058. }
  7059. // set type if args.types || args.type specified
  7060. if (args.type || args.types) {
  7061. targets.forEach(function (t) {
  7062. var type = args.types && args.types[t.id] ? args.types[t.id] : args.type;
  7063. $$.setTargetType(t.id, type);
  7064. });
  7065. }
  7066. // Update/Add data
  7067. $$.data.targets.forEach(function (d) {
  7068. for (var i = 0; i < targets.length; i++) {
  7069. if (d.id === targets[i].id) {
  7070. d.values = targets[i].values;
  7071. targets.splice(i, 1);
  7072. break;
  7073. }
  7074. }
  7075. });
  7076. $$.data.targets = $$.data.targets.concat(targets); // add remained
  7077. }
  7078. // Set targets
  7079. $$.updateTargets($$.data.targets);
  7080. // Redraw with new targets
  7081. $$.redraw({
  7082. withUpdateOrgXDomain: true,
  7083. withUpdateXDomain: true,
  7084. withLegend: true
  7085. });
  7086. if (args.done) {
  7087. args.done();
  7088. }
  7089. };
  7090. ChartInternal.prototype.loadFromArgs = function (args) {
  7091. var $$ = this;
  7092. $$.resetCache();
  7093. if (args.data) {
  7094. $$.load($$.convertDataToTargets(args.data), args);
  7095. }
  7096. else if (args.url) {
  7097. $$.convertUrlToData(args.url, args.mimeType, args.headers, args.keys, function (data) {
  7098. $$.load($$.convertDataToTargets(data), args);
  7099. });
  7100. }
  7101. else if (args.json) {
  7102. $$.load($$.convertDataToTargets($$.convertJsonToData(args.json, args.keys)), args);
  7103. }
  7104. else if (args.rows) {
  7105. $$.load($$.convertDataToTargets($$.convertRowsToData(args.rows)), args);
  7106. }
  7107. else if (args.columns) {
  7108. $$.load($$.convertDataToTargets($$.convertColumnsToData(args.columns)), args);
  7109. }
  7110. else {
  7111. $$.load(null, args);
  7112. }
  7113. };
  7114. ChartInternal.prototype.unload = function (targetIds, done) {
  7115. var $$ = this;
  7116. $$.resetCache();
  7117. if (!done) {
  7118. done = function () { };
  7119. }
  7120. // filter existing target
  7121. targetIds = targetIds.filter(function (id) {
  7122. return $$.hasTarget($$.data.targets, id);
  7123. });
  7124. // If no target, call done and return
  7125. if (!targetIds || targetIds.length === 0) {
  7126. done();
  7127. return;
  7128. }
  7129. $$.svg
  7130. .selectAll(targetIds.map(function (id) {
  7131. return $$.selectorTarget(id);
  7132. }))
  7133. .transition()
  7134. .style('opacity', 0)
  7135. .remove()
  7136. .call($$.endall, done);
  7137. targetIds.forEach(function (id) {
  7138. // Reset fadein for future load
  7139. $$.withoutFadeIn[id] = false;
  7140. // Remove target's elements
  7141. if ($$.legend) {
  7142. $$.legend
  7143. .selectAll('.' + CLASS.legendItem + $$.getTargetSelectorSuffix(id))
  7144. .remove();
  7145. }
  7146. // Remove target
  7147. $$.data.targets = $$.data.targets.filter(function (t) {
  7148. return t.id !== id;
  7149. });
  7150. });
  7151. };
  7152. ChartInternal.prototype.getYDomainMin = function (targets) {
  7153. var $$ = this, config = $$.config, ids = $$.mapToIds(targets), ys = $$.getValuesAsIdKeyed(targets), j, k, baseId, idsInGroup, id, hasNegativeValue;
  7154. if (config.data_groups.length > 0) {
  7155. hasNegativeValue = $$.hasNegativeValueInTargets(targets);
  7156. for (j = 0; j < config.data_groups.length; j++) {
  7157. // Determine baseId
  7158. idsInGroup = config.data_groups[j].filter(function (id) {
  7159. return ids.indexOf(id) >= 0;
  7160. });
  7161. if (idsInGroup.length === 0) {
  7162. continue;
  7163. }
  7164. baseId = idsInGroup[0];
  7165. // Consider negative values
  7166. if (hasNegativeValue && ys[baseId]) {
  7167. ys[baseId].forEach(function (v, i) {
  7168. ys[baseId][i] = v < 0 ? v : 0;
  7169. });
  7170. }
  7171. // Compute min
  7172. for (k = 1; k < idsInGroup.length; k++) {
  7173. id = idsInGroup[k];
  7174. if (!ys[id]) {
  7175. continue;
  7176. }
  7177. ys[id].forEach(function (v, i) {
  7178. if ($$.axis.getId(id) === $$.axis.getId(baseId) &&
  7179. ys[baseId] &&
  7180. !(hasNegativeValue && +v > 0)) {
  7181. ys[baseId][i] += +v;
  7182. }
  7183. });
  7184. }
  7185. }
  7186. }
  7187. return $$.d3.min(Object.keys(ys).map(function (key) {
  7188. return $$.d3.min(ys[key]);
  7189. }));
  7190. };
  7191. ChartInternal.prototype.getYDomainMax = function (targets) {
  7192. var $$ = this, config = $$.config, ids = $$.mapToIds(targets), ys = $$.getValuesAsIdKeyed(targets), j, k, baseId, idsInGroup, id, hasPositiveValue;
  7193. if (config.data_groups.length > 0) {
  7194. hasPositiveValue = $$.hasPositiveValueInTargets(targets);
  7195. for (j = 0; j < config.data_groups.length; j++) {
  7196. // Determine baseId
  7197. idsInGroup = config.data_groups[j].filter(function (id) {
  7198. return ids.indexOf(id) >= 0;
  7199. });
  7200. if (idsInGroup.length === 0) {
  7201. continue;
  7202. }
  7203. baseId = idsInGroup[0];
  7204. // Consider positive values
  7205. if (hasPositiveValue && ys[baseId]) {
  7206. ys[baseId].forEach(function (v, i) {
  7207. ys[baseId][i] = v > 0 ? v : 0;
  7208. });
  7209. }
  7210. // Compute max
  7211. for (k = 1; k < idsInGroup.length; k++) {
  7212. id = idsInGroup[k];
  7213. if (!ys[id]) {
  7214. continue;
  7215. }
  7216. ys[id].forEach(function (v, i) {
  7217. if ($$.axis.getId(id) === $$.axis.getId(baseId) &&
  7218. ys[baseId] &&
  7219. !(hasPositiveValue && +v < 0)) {
  7220. ys[baseId][i] += +v;
  7221. }
  7222. });
  7223. }
  7224. }
  7225. }
  7226. return $$.d3.max(Object.keys(ys).map(function (key) {
  7227. return $$.d3.max(ys[key]);
  7228. }));
  7229. };
  7230. ChartInternal.prototype.getYDomain = function (targets, axisId, xDomain) {
  7231. var $$ = this, config = $$.config;
  7232. if ($$.isAxisNormalized(axisId)) {
  7233. return [0, 100];
  7234. }
  7235. var targetsByAxisId = targets.filter(function (t) {
  7236. return $$.axis.getId(t.id) === axisId;
  7237. }), yTargets = xDomain
  7238. ? $$.filterByXDomain(targetsByAxisId, xDomain)
  7239. : targetsByAxisId, yMin = axisId === 'y2' ? config.axis_y2_min : config.axis_y_min, yMax = axisId === 'y2' ? config.axis_y2_max : config.axis_y_max, yDomainMin = $$.getYDomainMin(yTargets), yDomainMax = $$.getYDomainMax(yTargets), domain, domainLength, padding_top, padding_bottom, center = axisId === 'y2' ? config.axis_y2_center : config.axis_y_center, yDomainAbs, lengths, diff, ratio, isAllPositive, isAllNegative, isZeroBased = ($$.hasType('bar', yTargets) && config.bar_zerobased) ||
  7240. ($$.hasType('area', yTargets) && config.area_zerobased), isInverted = axisId === 'y2' ? config.axis_y2_inverted : config.axis_y_inverted, showHorizontalDataLabel = $$.hasDataLabel() && config.axis_rotated, showVerticalDataLabel = $$.hasDataLabel() && !config.axis_rotated;
  7241. // MEMO: avoid inverting domain unexpectedly
  7242. yDomainMin = isValue(yMin)
  7243. ? yMin
  7244. : isValue(yMax)
  7245. ? yDomainMin < yMax
  7246. ? yDomainMin
  7247. : yMax - 10
  7248. : yDomainMin;
  7249. yDomainMax = isValue(yMax)
  7250. ? yMax
  7251. : isValue(yMin)
  7252. ? yMin < yDomainMax
  7253. ? yDomainMax
  7254. : yMin + 10
  7255. : yDomainMax;
  7256. if (yTargets.length === 0) {
  7257. // use current domain if target of axisId is none
  7258. return axisId === 'y2' ? $$.y2.domain() : $$.y.domain();
  7259. }
  7260. if (isNaN(yDomainMin)) {
  7261. // set minimum to zero when not number
  7262. yDomainMin = 0;
  7263. }
  7264. if (isNaN(yDomainMax)) {
  7265. // set maximum to have same value as yDomainMin
  7266. yDomainMax = yDomainMin;
  7267. }
  7268. if (yDomainMin === yDomainMax) {
  7269. yDomainMin < 0 ? (yDomainMax = 0) : (yDomainMin = 0);
  7270. }
  7271. isAllPositive = yDomainMin >= 0 && yDomainMax >= 0;
  7272. isAllNegative = yDomainMin <= 0 && yDomainMax <= 0;
  7273. // Cancel zerobased if axis_*_min / axis_*_max specified
  7274. if ((isValue(yMin) && isAllPositive) || (isValue(yMax) && isAllNegative)) {
  7275. isZeroBased = false;
  7276. }
  7277. // Bar/Area chart should be 0-based if all positive|negative
  7278. if (isZeroBased) {
  7279. if (isAllPositive) {
  7280. yDomainMin = 0;
  7281. }
  7282. if (isAllNegative) {
  7283. yDomainMax = 0;
  7284. }
  7285. }
  7286. domainLength = Math.abs(yDomainMax - yDomainMin);
  7287. padding_top = padding_bottom = domainLength * 0.1;
  7288. if (typeof center !== 'undefined') {
  7289. yDomainAbs = Math.max(Math.abs(yDomainMin), Math.abs(yDomainMax));
  7290. yDomainMax = center + yDomainAbs;
  7291. yDomainMin = center - yDomainAbs;
  7292. }
  7293. // add padding for data label
  7294. if (showHorizontalDataLabel) {
  7295. lengths = $$.getDataLabelLength(yDomainMin, yDomainMax, 'width');
  7296. diff = diffDomain($$.y.range());
  7297. ratio = [lengths[0] / diff, lengths[1] / diff];
  7298. padding_top += domainLength * (ratio[1] / (1 - ratio[0] - ratio[1]));
  7299. padding_bottom += domainLength * (ratio[0] / (1 - ratio[0] - ratio[1]));
  7300. }
  7301. else if (showVerticalDataLabel) {
  7302. lengths = $$.getDataLabelLength(yDomainMin, yDomainMax, 'height');
  7303. var pixelsToAxisPadding = $$.getY(config["axis_" + axisId + "_type"],
  7304. // input domain as pixels
  7305. [0, config.axis_rotated ? $$.width : $$.height],
  7306. // output range as axis padding
  7307. [0, domainLength]);
  7308. padding_top += pixelsToAxisPadding(lengths[1]);
  7309. padding_bottom += pixelsToAxisPadding(lengths[0]);
  7310. }
  7311. if (axisId === 'y' && notEmpty(config.axis_y_padding)) {
  7312. padding_top = $$.axis.getPadding(config.axis_y_padding, 'top', padding_top, domainLength);
  7313. padding_bottom = $$.axis.getPadding(config.axis_y_padding, 'bottom', padding_bottom, domainLength);
  7314. }
  7315. if (axisId === 'y2' && notEmpty(config.axis_y2_padding)) {
  7316. padding_top = $$.axis.getPadding(config.axis_y2_padding, 'top', padding_top, domainLength);
  7317. padding_bottom = $$.axis.getPadding(config.axis_y2_padding, 'bottom', padding_bottom, domainLength);
  7318. }
  7319. // Bar/Area chart should be 0-based if all positive|negative
  7320. if (isZeroBased) {
  7321. if (isAllPositive) {
  7322. padding_bottom = yDomainMin;
  7323. }
  7324. if (isAllNegative) {
  7325. padding_top = -yDomainMax;
  7326. }
  7327. }
  7328. domain = [yDomainMin - padding_bottom, yDomainMax + padding_top];
  7329. return isInverted ? domain.reverse() : domain;
  7330. };
  7331. ChartInternal.prototype.getXDomainMin = function (targets) {
  7332. var $$ = this, config = $$.config;
  7333. return isDefined(config.axis_x_min)
  7334. ? $$.isTimeSeries()
  7335. ? this.parseDate(config.axis_x_min)
  7336. : config.axis_x_min
  7337. : $$.d3.min(targets, function (t) {
  7338. return $$.d3.min(t.values, function (v) {
  7339. return v.x;
  7340. });
  7341. });
  7342. };
  7343. ChartInternal.prototype.getXDomainMax = function (targets) {
  7344. var $$ = this, config = $$.config;
  7345. return isDefined(config.axis_x_max)
  7346. ? $$.isTimeSeries()
  7347. ? this.parseDate(config.axis_x_max)
  7348. : config.axis_x_max
  7349. : $$.d3.max(targets, function (t) {
  7350. return $$.d3.max(t.values, function (v) {
  7351. return v.x;
  7352. });
  7353. });
  7354. };
  7355. ChartInternal.prototype.getXDomainPadding = function (domain) {
  7356. var $$ = this, config = $$.config, diff = domain[1] - domain[0], maxDataCount, padding, paddingLeft, paddingRight;
  7357. if ($$.isCategorized()) {
  7358. padding = 0;
  7359. }
  7360. else if ($$.hasType('bar')) {
  7361. maxDataCount = $$.getMaxDataCount();
  7362. padding = maxDataCount > 1 ? diff / (maxDataCount - 1) / 2 : 0.5;
  7363. }
  7364. else {
  7365. padding = diff * 0.01;
  7366. }
  7367. if (typeof config.axis_x_padding === 'object' &&
  7368. notEmpty(config.axis_x_padding)) {
  7369. paddingLeft = isValue(config.axis_x_padding.left)
  7370. ? config.axis_x_padding.left
  7371. : padding;
  7372. paddingRight = isValue(config.axis_x_padding.right)
  7373. ? config.axis_x_padding.right
  7374. : padding;
  7375. }
  7376. else if (typeof config.axis_x_padding === 'number') {
  7377. paddingLeft = paddingRight = config.axis_x_padding;
  7378. }
  7379. else {
  7380. paddingLeft = paddingRight = padding;
  7381. }
  7382. return { left: paddingLeft, right: paddingRight };
  7383. };
  7384. ChartInternal.prototype.getXDomain = function (targets) {
  7385. var $$ = this, xDomain = [$$.getXDomainMin(targets), $$.getXDomainMax(targets)], firstX = xDomain[0], lastX = xDomain[1], padding = $$.getXDomainPadding(xDomain), min = 0, max = 0;
  7386. // show center of x domain if min and max are the same
  7387. if (firstX - lastX === 0 && !$$.isCategorized()) {
  7388. if ($$.isTimeSeries()) {
  7389. firstX = new Date(firstX.getTime() * 0.5);
  7390. lastX = new Date(lastX.getTime() * 1.5);
  7391. }
  7392. else {
  7393. firstX = firstX === 0 ? 1 : firstX * 0.5;
  7394. lastX = lastX === 0 ? -1 : lastX * 1.5;
  7395. }
  7396. }
  7397. if (firstX || firstX === 0) {
  7398. min = $$.isTimeSeries()
  7399. ? new Date(firstX.getTime() - padding.left)
  7400. : firstX - padding.left;
  7401. }
  7402. if (lastX || lastX === 0) {
  7403. max = $$.isTimeSeries()
  7404. ? new Date(lastX.getTime() + padding.right)
  7405. : lastX + padding.right;
  7406. }
  7407. return [min, max];
  7408. };
  7409. ChartInternal.prototype.updateXDomain = function (targets, withUpdateXDomain, withUpdateOrgXDomain, withTrim, domain) {
  7410. var $$ = this, config = $$.config;
  7411. if (withUpdateOrgXDomain) {
  7412. $$.x.domain(domain ? domain : $$.d3.extent($$.getXDomain(targets)));
  7413. $$.orgXDomain = $$.x.domain();
  7414. if (config.zoom_enabled) {
  7415. $$.zoom.update();
  7416. }
  7417. $$.subX.domain($$.x.domain());
  7418. if ($$.brush) {
  7419. $$.brush.updateScale($$.subX);
  7420. }
  7421. }
  7422. if (withUpdateXDomain) {
  7423. $$.x.domain(domain
  7424. ? domain
  7425. : !$$.brush || $$.brush.empty()
  7426. ? $$.orgXDomain
  7427. : $$.brush.selectionAsValue());
  7428. }
  7429. // Trim domain when too big by zoom mousemove event
  7430. if (withTrim) {
  7431. $$.x.domain($$.trimXDomain($$.x.orgDomain()));
  7432. }
  7433. return $$.x.domain();
  7434. };
  7435. ChartInternal.prototype.trimXDomain = function (domain) {
  7436. var zoomDomain = this.getZoomDomain(), min = zoomDomain[0], max = zoomDomain[1];
  7437. if (domain[0] <= min) {
  7438. domain[1] = +domain[1] + (min - domain[0]);
  7439. domain[0] = min;
  7440. }
  7441. if (max <= domain[1]) {
  7442. domain[0] = +domain[0] - (domain[1] - max);
  7443. domain[1] = max;
  7444. }
  7445. return domain;
  7446. };
  7447. ChartInternal.prototype.drag = function (mouse) {
  7448. var $$ = this, config = $$.config, main = $$.main, d3 = $$.d3;
  7449. var sx, sy, mx, my, minX, maxX, minY, maxY;
  7450. if ($$.hasArcType()) {
  7451. return;
  7452. }
  7453. if (!config.data_selection_enabled) {
  7454. return;
  7455. } // do nothing if not selectable
  7456. if (!config.data_selection_multiple) {
  7457. return;
  7458. } // skip when single selection because drag is used for multiple selection
  7459. sx = $$.dragStart[0];
  7460. sy = $$.dragStart[1];
  7461. mx = mouse[0];
  7462. my = mouse[1];
  7463. minX = Math.min(sx, mx);
  7464. maxX = Math.max(sx, mx);
  7465. minY = config.data_selection_grouped ? $$.margin.top : Math.min(sy, my);
  7466. maxY = config.data_selection_grouped ? $$.height : Math.max(sy, my);
  7467. main
  7468. .select('.' + CLASS.dragarea)
  7469. .attr('x', minX)
  7470. .attr('y', minY)
  7471. .attr('width', maxX - minX)
  7472. .attr('height', maxY - minY);
  7473. // TODO: binary search when multiple xs
  7474. main
  7475. .selectAll('.' + CLASS.shapes)
  7476. .selectAll('.' + CLASS.shape)
  7477. .each(function (d, i) {
  7478. if (!config.data_selection_isselectable(d)) {
  7479. return;
  7480. }
  7481. var shape = d3.select(this), isSelected = shape.classed(CLASS.SELECTED), isIncluded = shape.classed(CLASS.INCLUDED), _x, _y, _w, _h, toggle, isWithin = false, box;
  7482. if (shape.classed(CLASS.circle)) {
  7483. _x = shape.attr('cx') * 1;
  7484. _y = shape.attr('cy') * 1;
  7485. toggle = $$.togglePoint;
  7486. isWithin = minX < _x && _x < maxX && minY < _y && _y < maxY;
  7487. }
  7488. else if (shape.classed(CLASS.bar)) {
  7489. box = getPathBox(this);
  7490. _x = box.x;
  7491. _y = box.y;
  7492. _w = box.width;
  7493. _h = box.height;
  7494. toggle = $$.togglePath;
  7495. isWithin =
  7496. !(maxX < _x || _x + _w < minX) && !(maxY < _y || _y + _h < minY);
  7497. }
  7498. else {
  7499. // line/area selection not supported yet
  7500. return;
  7501. }
  7502. if (isWithin ^ isIncluded) {
  7503. shape.classed(CLASS.INCLUDED, !isIncluded);
  7504. // TODO: included/unincluded callback here
  7505. shape.classed(CLASS.SELECTED, !isSelected);
  7506. toggle.call($$, !isSelected, shape, d, i);
  7507. }
  7508. });
  7509. };
  7510. ChartInternal.prototype.dragstart = function (mouse) {
  7511. var $$ = this, config = $$.config;
  7512. if ($$.hasArcType()) {
  7513. return;
  7514. }
  7515. if (!config.data_selection_enabled) {
  7516. return;
  7517. } // do nothing if not selectable
  7518. $$.dragStart = mouse;
  7519. $$.main
  7520. .select('.' + CLASS.chart)
  7521. .append('rect')
  7522. .attr('class', CLASS.dragarea)
  7523. .style('opacity', 0.1);
  7524. $$.dragging = true;
  7525. };
  7526. ChartInternal.prototype.dragend = function () {
  7527. var $$ = this, config = $$.config;
  7528. if ($$.hasArcType()) {
  7529. return;
  7530. }
  7531. if (!config.data_selection_enabled) {
  7532. return;
  7533. } // do nothing if not selectable
  7534. $$.main
  7535. .select('.' + CLASS.dragarea)
  7536. .transition()
  7537. .duration(100)
  7538. .style('opacity', 0)
  7539. .remove();
  7540. $$.main.selectAll('.' + CLASS.shape).classed(CLASS.INCLUDED, false);
  7541. $$.dragging = false;
  7542. };
  7543. ChartInternal.prototype.getYFormat = function (forArc) {
  7544. var $$ = this, formatForY = forArc && !$$.hasType('gauge') ? $$.defaultArcValueFormat : $$.yFormat, formatForY2 = forArc && !$$.hasType('gauge') ? $$.defaultArcValueFormat : $$.y2Format;
  7545. return function (v, ratio, id) {
  7546. var format = $$.axis.getId(id) === 'y2' ? formatForY2 : formatForY;
  7547. return format.call($$, v, ratio);
  7548. };
  7549. };
  7550. ChartInternal.prototype.yFormat = function (v) {
  7551. var $$ = this, config = $$.config, format = config.axis_y_tick_format
  7552. ? config.axis_y_tick_format
  7553. : $$.defaultValueFormat;
  7554. return format(v);
  7555. };
  7556. ChartInternal.prototype.y2Format = function (v) {
  7557. var $$ = this, config = $$.config, format = config.axis_y2_tick_format
  7558. ? config.axis_y2_tick_format
  7559. : $$.defaultValueFormat;
  7560. return format(v);
  7561. };
  7562. ChartInternal.prototype.defaultValueFormat = function (v) {
  7563. return isValue(v) ? +v : '';
  7564. };
  7565. ChartInternal.prototype.defaultArcValueFormat = function (v, ratio) {
  7566. return (ratio * 100).toFixed(1) + '%';
  7567. };
  7568. ChartInternal.prototype.dataLabelFormat = function (targetId) {
  7569. var $$ = this, data_labels = $$.config.data_labels, format, defaultFormat = function (v) {
  7570. return isValue(v) ? +v : '';
  7571. };
  7572. // find format according to axis id
  7573. if (typeof data_labels.format === 'function') {
  7574. format = data_labels.format;
  7575. }
  7576. else if (typeof data_labels.format === 'object') {
  7577. if (data_labels.format[targetId]) {
  7578. format =
  7579. data_labels.format[targetId] === true
  7580. ? defaultFormat
  7581. : data_labels.format[targetId];
  7582. }
  7583. else {
  7584. format = function () {
  7585. return '';
  7586. };
  7587. }
  7588. }
  7589. else {
  7590. format = defaultFormat;
  7591. }
  7592. return format;
  7593. };
  7594. ChartInternal.prototype.initGrid = function () {
  7595. var $$ = this, config = $$.config, d3 = $$.d3;
  7596. $$.grid = $$.main
  7597. .append('g')
  7598. .attr('clip-path', $$.clipPathForGrid)
  7599. .attr('class', CLASS.grid);
  7600. if (config.grid_x_show) {
  7601. $$.grid.append('g').attr('class', CLASS.xgrids);
  7602. }
  7603. if (config.grid_y_show) {
  7604. $$.grid.append('g').attr('class', CLASS.ygrids);
  7605. }
  7606. if (config.grid_focus_show) {
  7607. $$.grid
  7608. .append('g')
  7609. .attr('class', CLASS.xgridFocus)
  7610. .append('line')
  7611. .attr('class', CLASS.xgridFocus);
  7612. }
  7613. $$.xgrid = d3.selectAll([]);
  7614. if (!config.grid_lines_front) {
  7615. $$.initGridLines();
  7616. }
  7617. };
  7618. ChartInternal.prototype.initGridLines = function () {
  7619. var $$ = this, d3 = $$.d3;
  7620. $$.gridLines = $$.main
  7621. .append('g')
  7622. .attr('clip-path', $$.clipPathForGrid)
  7623. .attr('class', CLASS.grid + ' ' + CLASS.gridLines);
  7624. $$.gridLines.append('g').attr('class', CLASS.xgridLines);
  7625. $$.gridLines.append('g').attr('class', CLASS.ygridLines);
  7626. $$.xgridLines = d3.selectAll([]);
  7627. };
  7628. ChartInternal.prototype.updateXGrid = function (withoutUpdate) {
  7629. var $$ = this, config = $$.config, d3 = $$.d3, xgridData = $$.generateGridData(config.grid_x_type, $$.x), tickOffset = $$.isCategorized() ? $$.xAxis.tickOffset() : 0;
  7630. $$.xgridAttr = config.axis_rotated
  7631. ? {
  7632. x1: 0,
  7633. x2: $$.width,
  7634. y1: function (d) {
  7635. return $$.x(d) - tickOffset;
  7636. },
  7637. y2: function (d) {
  7638. return $$.x(d) - tickOffset;
  7639. }
  7640. }
  7641. : {
  7642. x1: function (d) {
  7643. return $$.x(d) + tickOffset;
  7644. },
  7645. x2: function (d) {
  7646. return $$.x(d) + tickOffset;
  7647. },
  7648. y1: 0,
  7649. y2: $$.height
  7650. };
  7651. $$.xgridAttr.opacity = function () {
  7652. var pos = +d3.select(this).attr(config.axis_rotated ? 'y1' : 'x1');
  7653. return pos === (config.axis_rotated ? $$.height : 0) ? 0 : 1;
  7654. };
  7655. var xgrid = $$.main
  7656. .select('.' + CLASS.xgrids)
  7657. .selectAll('.' + CLASS.xgrid)
  7658. .data(xgridData);
  7659. var xgridEnter = xgrid
  7660. .enter()
  7661. .append('line')
  7662. .attr('class', CLASS.xgrid)
  7663. .attr('x1', $$.xgridAttr.x1)
  7664. .attr('x2', $$.xgridAttr.x2)
  7665. .attr('y1', $$.xgridAttr.y1)
  7666. .attr('y2', $$.xgridAttr.y2)
  7667. .style('opacity', 0);
  7668. $$.xgrid = xgridEnter.merge(xgrid);
  7669. if (!withoutUpdate) {
  7670. $$.xgrid
  7671. .attr('x1', $$.xgridAttr.x1)
  7672. .attr('x2', $$.xgridAttr.x2)
  7673. .attr('y1', $$.xgridAttr.y1)
  7674. .attr('y2', $$.xgridAttr.y2)
  7675. .style('opacity', $$.xgridAttr.opacity);
  7676. }
  7677. xgrid.exit().remove();
  7678. };
  7679. ChartInternal.prototype.updateYGrid = function () {
  7680. var $$ = this, config = $$.config, gridValues = $$.yAxis.tickValues() || $$.y.ticks(config.grid_y_ticks);
  7681. var ygrid = $$.main
  7682. .select('.' + CLASS.ygrids)
  7683. .selectAll('.' + CLASS.ygrid)
  7684. .data(gridValues);
  7685. var ygridEnter = ygrid
  7686. .enter()
  7687. .append('line')
  7688. // TODO: x1, x2, y1, y2, opacity need to be set here maybe
  7689. .attr('class', CLASS.ygrid);
  7690. $$.ygrid = ygridEnter.merge(ygrid);
  7691. $$.ygrid
  7692. .attr('x1', config.axis_rotated ? $$.y : 0)
  7693. .attr('x2', config.axis_rotated ? $$.y : $$.width)
  7694. .attr('y1', config.axis_rotated ? 0 : $$.y)
  7695. .attr('y2', config.axis_rotated ? $$.height : $$.y);
  7696. ygrid.exit().remove();
  7697. $$.smoothLines($$.ygrid, 'grid');
  7698. };
  7699. ChartInternal.prototype.gridTextAnchor = function (d) {
  7700. return d.position ? d.position : 'end';
  7701. };
  7702. ChartInternal.prototype.gridTextDx = function (d) {
  7703. return d.position === 'start' ? 4 : d.position === 'middle' ? 0 : -4;
  7704. };
  7705. ChartInternal.prototype.xGridTextX = function (d) {
  7706. return d.position === 'start'
  7707. ? -this.height
  7708. : d.position === 'middle'
  7709. ? -this.height / 2
  7710. : 0;
  7711. };
  7712. ChartInternal.prototype.yGridTextX = function (d) {
  7713. return d.position === 'start'
  7714. ? 0
  7715. : d.position === 'middle'
  7716. ? this.width / 2
  7717. : this.width;
  7718. };
  7719. ChartInternal.prototype.updateGrid = function (duration) {
  7720. var $$ = this, main = $$.main, config = $$.config, xgridLine, xgridLineEnter, ygridLine, ygridLineEnter, xv = $$.xv.bind($$), yv = $$.yv.bind($$), xGridTextX = $$.xGridTextX.bind($$), yGridTextX = $$.yGridTextX.bind($$);
  7721. // hide if arc type
  7722. $$.grid.style('visibility', $$.hasArcType() ? 'hidden' : 'visible');
  7723. main.select('line.' + CLASS.xgridFocus).style('visibility', 'hidden');
  7724. if (config.grid_x_show) {
  7725. $$.updateXGrid();
  7726. }
  7727. xgridLine = main
  7728. .select('.' + CLASS.xgridLines)
  7729. .selectAll('.' + CLASS.xgridLine)
  7730. .data(config.grid_x_lines);
  7731. // enter
  7732. xgridLineEnter = xgridLine
  7733. .enter()
  7734. .append('g')
  7735. .attr('class', function (d) {
  7736. return CLASS.xgridLine + (d['class'] ? ' ' + d['class'] : '');
  7737. });
  7738. xgridLineEnter
  7739. .append('line')
  7740. .attr('x1', config.axis_rotated ? 0 : xv)
  7741. .attr('x2', config.axis_rotated ? $$.width : xv)
  7742. .attr('y1', config.axis_rotated ? xv : 0)
  7743. .attr('y2', config.axis_rotated ? xv : $$.height)
  7744. .style('opacity', 0);
  7745. xgridLineEnter
  7746. .append('text')
  7747. .attr('text-anchor', $$.gridTextAnchor)
  7748. .attr('transform', config.axis_rotated ? '' : 'rotate(-90)')
  7749. .attr('x', config.axis_rotated ? yGridTextX : xGridTextX)
  7750. .attr('y', xv)
  7751. .attr('dx', $$.gridTextDx)
  7752. .attr('dy', -5)
  7753. .style('opacity', 0);
  7754. // udpate
  7755. $$.xgridLines = xgridLineEnter.merge(xgridLine);
  7756. // done in d3.transition() of the end of this function
  7757. // exit
  7758. xgridLine
  7759. .exit()
  7760. .transition()
  7761. .duration(duration)
  7762. .style('opacity', 0)
  7763. .remove();
  7764. // Y-Grid
  7765. if (config.grid_y_show) {
  7766. $$.updateYGrid();
  7767. }
  7768. ygridLine = main
  7769. .select('.' + CLASS.ygridLines)
  7770. .selectAll('.' + CLASS.ygridLine)
  7771. .data(config.grid_y_lines);
  7772. // enter
  7773. ygridLineEnter = ygridLine
  7774. .enter()
  7775. .append('g')
  7776. .attr('class', function (d) {
  7777. return CLASS.ygridLine + (d['class'] ? ' ' + d['class'] : '');
  7778. });
  7779. ygridLineEnter
  7780. .append('line')
  7781. .attr('x1', config.axis_rotated ? yv : 0)
  7782. .attr('x2', config.axis_rotated ? yv : $$.width)
  7783. .attr('y1', config.axis_rotated ? 0 : yv)
  7784. .attr('y2', config.axis_rotated ? $$.height : yv)
  7785. .style('opacity', 0);
  7786. ygridLineEnter
  7787. .append('text')
  7788. .attr('text-anchor', $$.gridTextAnchor)
  7789. .attr('transform', config.axis_rotated ? 'rotate(-90)' : '')
  7790. .attr('x', config.axis_rotated ? xGridTextX : yGridTextX)
  7791. .attr('y', yv)
  7792. .attr('dx', $$.gridTextDx)
  7793. .attr('dy', -5)
  7794. .style('opacity', 0);
  7795. // update
  7796. $$.ygridLines = ygridLineEnter.merge(ygridLine);
  7797. $$.ygridLines
  7798. .select('line')
  7799. .transition()
  7800. .duration(duration)
  7801. .attr('x1', config.axis_rotated ? yv : 0)
  7802. .attr('x2', config.axis_rotated ? yv : $$.width)
  7803. .attr('y1', config.axis_rotated ? 0 : yv)
  7804. .attr('y2', config.axis_rotated ? $$.height : yv)
  7805. .style('opacity', 1);
  7806. $$.ygridLines
  7807. .select('text')
  7808. .transition()
  7809. .duration(duration)
  7810. .attr('x', config.axis_rotated ? $$.xGridTextX.bind($$) : $$.yGridTextX.bind($$))
  7811. .attr('y', yv)
  7812. .text(function (d) {
  7813. return d.text;
  7814. })
  7815. .style('opacity', 1);
  7816. // exit
  7817. ygridLine
  7818. .exit()
  7819. .transition()
  7820. .duration(duration)
  7821. .style('opacity', 0)
  7822. .remove();
  7823. };
  7824. ChartInternal.prototype.redrawGrid = function (withTransition, transition) {
  7825. var $$ = this, config = $$.config, xv = $$.xv.bind($$), lines = $$.xgridLines.select('line'), texts = $$.xgridLines.select('text');
  7826. return [
  7827. (withTransition ? lines.transition(transition) : lines)
  7828. .attr('x1', config.axis_rotated ? 0 : xv)
  7829. .attr('x2', config.axis_rotated ? $$.width : xv)
  7830. .attr('y1', config.axis_rotated ? xv : 0)
  7831. .attr('y2', config.axis_rotated ? xv : $$.height)
  7832. .style('opacity', 1),
  7833. (withTransition ? texts.transition(transition) : texts)
  7834. .attr('x', config.axis_rotated ? $$.yGridTextX.bind($$) : $$.xGridTextX.bind($$))
  7835. .attr('y', xv)
  7836. .text(function (d) {
  7837. return d.text;
  7838. })
  7839. .style('opacity', 1)
  7840. ];
  7841. };
  7842. ChartInternal.prototype.showXGridFocus = function (selectedData) {
  7843. var $$ = this, config = $$.config, dataToShow = selectedData.filter(function (d) {
  7844. return d && isValue(d.value);
  7845. }), focusEl = $$.main.selectAll('line.' + CLASS.xgridFocus), xx = $$.xx.bind($$);
  7846. if (!config.tooltip_show) {
  7847. return;
  7848. }
  7849. // Hide when stanford plot exists
  7850. if ($$.hasType('stanford') || $$.hasArcType()) {
  7851. return;
  7852. }
  7853. focusEl
  7854. .style('visibility', 'visible')
  7855. .data([dataToShow[0]])
  7856. .attr(config.axis_rotated ? 'y1' : 'x1', xx)
  7857. .attr(config.axis_rotated ? 'y2' : 'x2', xx);
  7858. $$.smoothLines(focusEl, 'grid');
  7859. };
  7860. ChartInternal.prototype.hideXGridFocus = function () {
  7861. this.main.select('line.' + CLASS.xgridFocus).style('visibility', 'hidden');
  7862. };
  7863. ChartInternal.prototype.updateXgridFocus = function () {
  7864. var $$ = this, config = $$.config;
  7865. $$.main
  7866. .select('line.' + CLASS.xgridFocus)
  7867. .attr('x1', config.axis_rotated ? 0 : -10)
  7868. .attr('x2', config.axis_rotated ? $$.width : -10)
  7869. .attr('y1', config.axis_rotated ? -10 : 0)
  7870. .attr('y2', config.axis_rotated ? -10 : $$.height);
  7871. };
  7872. ChartInternal.prototype.generateGridData = function (type, scale) {
  7873. var $$ = this, gridData = [], xDomain, firstYear, lastYear, i, tickNum = $$.main
  7874. .select('.' + CLASS.axisX)
  7875. .selectAll('.tick')
  7876. .size();
  7877. if (type === 'year') {
  7878. xDomain = $$.getXDomain();
  7879. firstYear = xDomain[0].getFullYear();
  7880. lastYear = xDomain[1].getFullYear();
  7881. for (i = firstYear; i <= lastYear; i++) {
  7882. gridData.push(new Date(i + '-01-01 00:00:00'));
  7883. }
  7884. }
  7885. else {
  7886. gridData = scale.ticks(10);
  7887. if (gridData.length > tickNum) {
  7888. // use only int
  7889. gridData = gridData.filter(function (d) {
  7890. return ('' + d).indexOf('.') < 0;
  7891. });
  7892. }
  7893. }
  7894. return gridData;
  7895. };
  7896. ChartInternal.prototype.getGridFilterToRemove = function (params) {
  7897. return params
  7898. ? function (line) {
  7899. var found = false;
  7900. [].concat(params).forEach(function (param) {
  7901. if (('value' in param && line.value === param.value) ||
  7902. ('class' in param && line['class'] === param['class'])) {
  7903. found = true;
  7904. }
  7905. });
  7906. return found;
  7907. }
  7908. : function () {
  7909. return true;
  7910. };
  7911. };
  7912. ChartInternal.prototype.removeGridLines = function (params, forX) {
  7913. var $$ = this, config = $$.config, toRemove = $$.getGridFilterToRemove(params), toShow = function (line) {
  7914. return !toRemove(line);
  7915. }, classLines = forX ? CLASS.xgridLines : CLASS.ygridLines, classLine = forX ? CLASS.xgridLine : CLASS.ygridLine;
  7916. $$.main
  7917. .select('.' + classLines)
  7918. .selectAll('.' + classLine)
  7919. .filter(toRemove)
  7920. .transition()
  7921. .duration(config.transition_duration)
  7922. .style('opacity', 0)
  7923. .remove();
  7924. if (forX) {
  7925. config.grid_x_lines = config.grid_x_lines.filter(toShow);
  7926. }
  7927. else {
  7928. config.grid_y_lines = config.grid_y_lines.filter(toShow);
  7929. }
  7930. };
  7931. ChartInternal.prototype.initEventRect = function () {
  7932. var $$ = this, config = $$.config;
  7933. $$.main
  7934. .select('.' + CLASS.chart)
  7935. .append('g')
  7936. .attr('class', CLASS.eventRects)
  7937. .style('fill-opacity', 0);
  7938. $$.eventRect = $$.main
  7939. .select('.' + CLASS.eventRects)
  7940. .append('rect')
  7941. .attr('class', CLASS.eventRect);
  7942. // event rect handle zoom event as well
  7943. if (config.zoom_enabled && $$.zoom) {
  7944. $$.eventRect.call($$.zoom).on('dblclick.zoom', null);
  7945. if (config.zoom_initialRange) {
  7946. // WORKAROUND: Add transition to apply transform immediately when no subchart
  7947. $$.eventRect
  7948. .transition()
  7949. .duration(0)
  7950. .call($$.zoom.transform, $$.zoomTransform(config.zoom_initialRange));
  7951. }
  7952. }
  7953. };
  7954. ChartInternal.prototype.redrawEventRect = function () {
  7955. var $$ = this, d3 = $$.d3, config = $$.config;
  7956. function mouseout() {
  7957. $$.svg.select('.' + CLASS.eventRect).style('cursor', null);
  7958. $$.hideXGridFocus();
  7959. $$.hideTooltip();
  7960. $$.unexpandCircles();
  7961. $$.unexpandBars();
  7962. }
  7963. var isHoveringDataPoint = function (mouse, closest) {
  7964. return closest &&
  7965. ($$.isBarType(closest.id) ||
  7966. $$.dist(closest, mouse) < config.point_sensitivity);
  7967. };
  7968. var withName = function (d) { return (d ? $$.addName(Object.assign({}, d)) : null); };
  7969. // rects for mouseover
  7970. $$.main
  7971. .select('.' + CLASS.eventRects)
  7972. .style('cursor', config.zoom_enabled
  7973. ? config.axis_rotated
  7974. ? 'ns-resize'
  7975. : 'ew-resize'
  7976. : null);
  7977. $$.eventRect
  7978. .attr('x', 0)
  7979. .attr('y', 0)
  7980. .attr('width', $$.width)
  7981. .attr('height', $$.height)
  7982. .on('mouseout', config.interaction_enabled
  7983. ? function () {
  7984. if (!config) {
  7985. return;
  7986. } // chart is destroyed
  7987. if ($$.hasArcType()) {
  7988. return;
  7989. }
  7990. if ($$.mouseover) {
  7991. config.data_onmouseout.call($$.api, $$.mouseover);
  7992. $$.mouseover = undefined;
  7993. }
  7994. mouseout();
  7995. }
  7996. : null)
  7997. .on('mousemove', config.interaction_enabled
  7998. ? function () {
  7999. // do nothing when dragging
  8000. if ($$.dragging) {
  8001. return;
  8002. }
  8003. var targetsToShow = $$.getTargetsToShow();
  8004. // do nothing if arc type
  8005. if ($$.hasArcType(targetsToShow)) {
  8006. return;
  8007. }
  8008. var mouse = d3.mouse(this);
  8009. var closest = withName($$.findClosestFromTargets(targetsToShow, mouse));
  8010. var isMouseCloseToDataPoint = isHoveringDataPoint(mouse, closest);
  8011. // ensure onmouseout is always called if mousemove switch between 2 targets
  8012. if ($$.mouseover &&
  8013. (!closest ||
  8014. closest.id !== $$.mouseover.id ||
  8015. closest.index !== $$.mouseover.index)) {
  8016. config.data_onmouseout.call($$.api, $$.mouseover);
  8017. $$.mouseover = undefined;
  8018. }
  8019. if (closest && !$$.mouseover) {
  8020. config.data_onmouseover.call($$.api, closest);
  8021. $$.mouseover = closest;
  8022. }
  8023. // show cursor as pointer if we're hovering a data point close enough
  8024. $$.svg
  8025. .select('.' + CLASS.eventRect)
  8026. .style('cursor', isMouseCloseToDataPoint ? 'pointer' : null);
  8027. // if tooltip not grouped, we want to display only data from closest data point
  8028. var showSingleDataPoint = !config.tooltip_grouped || $$.hasType('stanford', targetsToShow);
  8029. // find data to highlight
  8030. var selectedData;
  8031. if (showSingleDataPoint) {
  8032. if (closest) {
  8033. selectedData = [closest];
  8034. }
  8035. }
  8036. else {
  8037. var closestByX = void 0;
  8038. if (closest) {
  8039. // reuse closest value
  8040. closestByX = closest;
  8041. }
  8042. else {
  8043. // try to find the closest value by X values from the mouse position
  8044. var mouseX = config.axis_rotated ? mouse[1] : mouse[0];
  8045. closestByX = $$.findClosestFromTargetsByX(targetsToShow, $$.x.invert(mouseX));
  8046. }
  8047. // highlight all data for this 'x' value
  8048. if (closestByX) {
  8049. selectedData = $$.filterByX(targetsToShow, closestByX.x);
  8050. }
  8051. }
  8052. // ensure we have data to show
  8053. if (!selectedData || selectedData.length === 0) {
  8054. return mouseout();
  8055. }
  8056. // inject names for each point
  8057. selectedData = selectedData.map(withName);
  8058. // show tooltip
  8059. $$.showTooltip(selectedData, this);
  8060. // expand points
  8061. if (config.point_focus_expand_enabled) {
  8062. $$.unexpandCircles();
  8063. selectedData.forEach(function (d) {
  8064. $$.expandCircles(d.index, d.id, false);
  8065. });
  8066. }
  8067. // expand bars
  8068. $$.unexpandBars();
  8069. selectedData.forEach(function (d) {
  8070. $$.expandBars(d.index, d.id, false);
  8071. });
  8072. // Show xgrid focus line
  8073. $$.showXGridFocus(selectedData);
  8074. }
  8075. : null)
  8076. .on('click', config.interaction_enabled
  8077. ? function () {
  8078. var targetsToShow = $$.getTargetsToShow();
  8079. if ($$.hasArcType(targetsToShow)) {
  8080. return;
  8081. }
  8082. var mouse = d3.mouse(this);
  8083. var closest = withName($$.findClosestFromTargets(targetsToShow, mouse));
  8084. if (!isHoveringDataPoint(mouse, closest)) {
  8085. return;
  8086. }
  8087. // select if selection enabled
  8088. var sameXData;
  8089. if (!config.data_selection_grouped || $$.isStanfordType(closest)) {
  8090. sameXData = [closest];
  8091. }
  8092. else {
  8093. sameXData = $$.filterByX(targetsToShow, closest.x);
  8094. }
  8095. // toggle selected state
  8096. sameXData.forEach(function (d) {
  8097. $$.main
  8098. .selectAll('.' + CLASS.shapes + $$.getTargetSelectorSuffix(d.id))
  8099. .selectAll('.' + CLASS.shape + '-' + d.index)
  8100. .each(function () {
  8101. if (config.data_selection_grouped ||
  8102. $$.isWithinShape(this, d)) {
  8103. $$.toggleShape(this, d, d.index);
  8104. }
  8105. });
  8106. });
  8107. // call data_onclick on the closest data point
  8108. if (closest) {
  8109. var shape = $$.main
  8110. .selectAll('.' + CLASS.shapes + $$.getTargetSelectorSuffix(closest.id))
  8111. .select('.' + CLASS.shape + '-' + closest.index);
  8112. config.data_onclick.call($$.api, closest, shape.node());
  8113. }
  8114. }
  8115. : null)
  8116. .call(config.interaction_enabled && config.data_selection_draggable && $$.drag
  8117. ? d3
  8118. .drag()
  8119. .on('drag', function () {
  8120. $$.drag(d3.mouse(this));
  8121. })
  8122. .on('start', function () {
  8123. $$.dragstart(d3.mouse(this));
  8124. })
  8125. .on('end', function () {
  8126. $$.dragend();
  8127. })
  8128. : function () { });
  8129. };
  8130. ChartInternal.prototype.getMousePosition = function (data) {
  8131. var $$ = this;
  8132. return [$$.x(data.x), $$.getYScale(data.id)(data.value)];
  8133. };
  8134. ChartInternal.prototype.dispatchEvent = function (type, mouse) {
  8135. var $$ = this, selector = '.' + CLASS.eventRect, eventRect = $$.main.select(selector).node(), box = eventRect.getBoundingClientRect(), x = box.left + (mouse ? mouse[0] : 0), y = box.top + (mouse ? mouse[1] : 0), event = document.createEvent('MouseEvents');
  8136. event.initMouseEvent(type, true, true, window, 0, x, y, x, y, false, false, false, false, 0, null);
  8137. eventRect.dispatchEvent(event);
  8138. };
  8139. ChartInternal.prototype.initLegend = function () {
  8140. var $$ = this;
  8141. $$.legendItemTextBox = {};
  8142. $$.legendHasRendered = false;
  8143. $$.legend = $$.svg.append('g').attr('transform', $$.getTranslate('legend'));
  8144. if (!$$.config.legend_show) {
  8145. $$.legend.style('visibility', 'hidden');
  8146. $$.hiddenLegendIds = $$.mapToIds($$.data.targets);
  8147. return;
  8148. }
  8149. // MEMO: call here to update legend box and tranlate for all
  8150. // MEMO: translate will be updated by this, so transform not needed in updateLegend()
  8151. $$.updateLegendWithDefaults();
  8152. };
  8153. ChartInternal.prototype.updateLegendWithDefaults = function () {
  8154. var $$ = this;
  8155. $$.updateLegend($$.mapToIds($$.data.targets), {
  8156. withTransform: false,
  8157. withTransitionForTransform: false,
  8158. withTransition: false
  8159. });
  8160. };
  8161. ChartInternal.prototype.updateSizeForLegend = function (legendHeight, legendWidth) {
  8162. var $$ = this, config = $$.config, insetLegendPosition = {
  8163. top: $$.isLegendTop
  8164. ? $$.getCurrentPaddingTop() + config.legend_inset_y + 5.5
  8165. : $$.currentHeight -
  8166. legendHeight -
  8167. $$.getCurrentPaddingBottom() -
  8168. config.legend_inset_y,
  8169. left: $$.isLegendLeft
  8170. ? $$.getCurrentPaddingLeft() + config.legend_inset_x + 0.5
  8171. : $$.currentWidth -
  8172. legendWidth -
  8173. $$.getCurrentPaddingRight() -
  8174. config.legend_inset_x +
  8175. 0.5
  8176. };
  8177. $$.margin3 = {
  8178. top: $$.isLegendRight
  8179. ? 0
  8180. : $$.isLegendInset
  8181. ? insetLegendPosition.top
  8182. : $$.currentHeight - legendHeight,
  8183. right: NaN,
  8184. bottom: 0,
  8185. left: $$.isLegendRight
  8186. ? $$.currentWidth - legendWidth
  8187. : $$.isLegendInset
  8188. ? insetLegendPosition.left
  8189. : 0
  8190. };
  8191. };
  8192. ChartInternal.prototype.transformLegend = function (withTransition) {
  8193. var $$ = this;
  8194. (withTransition ? $$.legend.transition() : $$.legend).attr('transform', $$.getTranslate('legend'));
  8195. };
  8196. ChartInternal.prototype.updateLegendStep = function (step) {
  8197. this.legendStep = step;
  8198. };
  8199. ChartInternal.prototype.updateLegendItemWidth = function (w) {
  8200. this.legendItemWidth = w;
  8201. };
  8202. ChartInternal.prototype.updateLegendItemHeight = function (h) {
  8203. this.legendItemHeight = h;
  8204. };
  8205. ChartInternal.prototype.getLegendWidth = function () {
  8206. var $$ = this;
  8207. return $$.config.legend_show
  8208. ? $$.isLegendRight || $$.isLegendInset
  8209. ? $$.legendItemWidth * ($$.legendStep + 1)
  8210. : $$.currentWidth
  8211. : 0;
  8212. };
  8213. ChartInternal.prototype.getLegendHeight = function () {
  8214. var $$ = this, h = 0;
  8215. if ($$.config.legend_show) {
  8216. if ($$.isLegendRight) {
  8217. h = $$.currentHeight;
  8218. }
  8219. else {
  8220. h = Math.max(20, $$.legendItemHeight) * ($$.legendStep + 1);
  8221. }
  8222. }
  8223. return h;
  8224. };
  8225. ChartInternal.prototype.opacityForLegend = function (legendItem) {
  8226. return legendItem.classed(CLASS.legendItemHidden) ? null : 1;
  8227. };
  8228. ChartInternal.prototype.opacityForUnfocusedLegend = function (legendItem) {
  8229. return legendItem.classed(CLASS.legendItemHidden) ? null : 0.3;
  8230. };
  8231. ChartInternal.prototype.toggleFocusLegend = function (targetIds, focus) {
  8232. var $$ = this;
  8233. targetIds = $$.mapToTargetIds(targetIds);
  8234. $$.legend
  8235. .selectAll('.' + CLASS.legendItem)
  8236. .filter(function (id) {
  8237. return targetIds.indexOf(id) >= 0;
  8238. })
  8239. .classed(CLASS.legendItemFocused, focus)
  8240. .transition()
  8241. .duration(100)
  8242. .style('opacity', function () {
  8243. var opacity = focus ? $$.opacityForLegend : $$.opacityForUnfocusedLegend;
  8244. return opacity.call($$, $$.d3.select(this));
  8245. });
  8246. };
  8247. ChartInternal.prototype.revertLegend = function () {
  8248. var $$ = this, d3 = $$.d3;
  8249. $$.legend
  8250. .selectAll('.' + CLASS.legendItem)
  8251. .classed(CLASS.legendItemFocused, false)
  8252. .transition()
  8253. .duration(100)
  8254. .style('opacity', function () {
  8255. return $$.opacityForLegend(d3.select(this));
  8256. });
  8257. };
  8258. ChartInternal.prototype.showLegend = function (targetIds) {
  8259. var $$ = this, config = $$.config;
  8260. if (!config.legend_show) {
  8261. config.legend_show = true;
  8262. $$.legend.style('visibility', 'visible');
  8263. if (!$$.legendHasRendered) {
  8264. $$.updateLegendWithDefaults();
  8265. }
  8266. }
  8267. $$.removeHiddenLegendIds(targetIds);
  8268. $$.legend
  8269. .selectAll($$.selectorLegends(targetIds))
  8270. .style('visibility', 'visible')
  8271. .transition()
  8272. .style('opacity', function () {
  8273. return $$.opacityForLegend($$.d3.select(this));
  8274. });
  8275. };
  8276. ChartInternal.prototype.hideLegend = function (targetIds) {
  8277. var $$ = this, config = $$.config;
  8278. if (config.legend_show && isEmpty(targetIds)) {
  8279. config.legend_show = false;
  8280. $$.legend.style('visibility', 'hidden');
  8281. }
  8282. $$.addHiddenLegendIds(targetIds);
  8283. $$.legend
  8284. .selectAll($$.selectorLegends(targetIds))
  8285. .style('opacity', 0)
  8286. .style('visibility', 'hidden');
  8287. };
  8288. ChartInternal.prototype.clearLegendItemTextBoxCache = function () {
  8289. this.legendItemTextBox = {};
  8290. };
  8291. ChartInternal.prototype.updateLegend = function (targetIds, options, transitions) {
  8292. var $$ = this, config = $$.config;
  8293. var xForLegend, xForLegendText, xForLegendRect, yForLegend, yForLegendText, yForLegendRect, x1ForLegendTile, x2ForLegendTile, yForLegendTile;
  8294. var paddingTop = 4, paddingRight = 10, maxWidth = 0, maxHeight = 0, posMin = 10, tileWidth = config.legend_item_tile_width + 5;
  8295. var l, totalLength = 0, offsets = {}, widths = {}, heights = {}, margins = [0], steps = {}, step = 0;
  8296. var withTransition, withTransitionForTransform;
  8297. var texts, rects, tiles, background;
  8298. // Skip elements when their name is set to null
  8299. targetIds = targetIds.filter(function (id) {
  8300. return !isDefined(config.data_names[id]) || config.data_names[id] !== null;
  8301. });
  8302. options = options || {};
  8303. withTransition = getOption(options, 'withTransition', true);
  8304. withTransitionForTransform = getOption(options, 'withTransitionForTransform', true);
  8305. function getTextBox(textElement, id) {
  8306. if (!$$.legendItemTextBox[id]) {
  8307. $$.legendItemTextBox[id] = $$.getTextRect(textElement.textContent, CLASS.legendItem, textElement);
  8308. }
  8309. return $$.legendItemTextBox[id];
  8310. }
  8311. function updatePositions(textElement, id, index) {
  8312. var reset = index === 0, isLast = index === targetIds.length - 1, box = getTextBox(textElement, id), itemWidth = box.width +
  8313. tileWidth +
  8314. (isLast && !($$.isLegendRight || $$.isLegendInset) ? 0 : paddingRight) +
  8315. config.legend_padding, itemHeight = box.height + paddingTop, itemLength = $$.isLegendRight || $$.isLegendInset ? itemHeight : itemWidth, areaLength = $$.isLegendRight || $$.isLegendInset
  8316. ? $$.getLegendHeight()
  8317. : $$.getLegendWidth(), margin, maxLength;
  8318. // MEMO: care about condifion of step, totalLength
  8319. function updateValues(id, withoutStep) {
  8320. if (!withoutStep) {
  8321. margin = (areaLength - totalLength - itemLength) / 2;
  8322. if (margin < posMin) {
  8323. margin = (areaLength - itemLength) / 2;
  8324. totalLength = 0;
  8325. step++;
  8326. }
  8327. }
  8328. steps[id] = step;
  8329. margins[step] = $$.isLegendInset ? 10 : margin;
  8330. offsets[id] = totalLength;
  8331. totalLength += itemLength;
  8332. }
  8333. if (reset) {
  8334. totalLength = 0;
  8335. step = 0;
  8336. maxWidth = 0;
  8337. maxHeight = 0;
  8338. }
  8339. if (config.legend_show && !$$.isLegendToShow(id)) {
  8340. widths[id] = heights[id] = steps[id] = offsets[id] = 0;
  8341. return;
  8342. }
  8343. widths[id] = itemWidth;
  8344. heights[id] = itemHeight;
  8345. if (!maxWidth || itemWidth >= maxWidth) {
  8346. maxWidth = itemWidth;
  8347. }
  8348. if (!maxHeight || itemHeight >= maxHeight) {
  8349. maxHeight = itemHeight;
  8350. }
  8351. maxLength = $$.isLegendRight || $$.isLegendInset ? maxHeight : maxWidth;
  8352. if (config.legend_equally) {
  8353. Object.keys(widths).forEach(function (id) {
  8354. widths[id] = maxWidth;
  8355. });
  8356. Object.keys(heights).forEach(function (id) {
  8357. heights[id] = maxHeight;
  8358. });
  8359. margin = (areaLength - maxLength * targetIds.length) / 2;
  8360. if (margin < posMin) {
  8361. totalLength = 0;
  8362. step = 0;
  8363. targetIds.forEach(function (id) {
  8364. updateValues(id);
  8365. });
  8366. }
  8367. else {
  8368. updateValues(id, true);
  8369. }
  8370. }
  8371. else {
  8372. updateValues(id);
  8373. }
  8374. }
  8375. if ($$.isLegendInset) {
  8376. step = config.legend_inset_step
  8377. ? config.legend_inset_step
  8378. : targetIds.length;
  8379. $$.updateLegendStep(step);
  8380. }
  8381. if ($$.isLegendRight) {
  8382. xForLegend = function (id) {
  8383. return maxWidth * steps[id];
  8384. };
  8385. yForLegend = function (id) {
  8386. return margins[steps[id]] + offsets[id];
  8387. };
  8388. }
  8389. else if ($$.isLegendInset) {
  8390. xForLegend = function (id) {
  8391. return maxWidth * steps[id] + 10;
  8392. };
  8393. yForLegend = function (id) {
  8394. return margins[steps[id]] + offsets[id];
  8395. };
  8396. }
  8397. else {
  8398. xForLegend = function (id) {
  8399. return margins[steps[id]] + offsets[id];
  8400. };
  8401. yForLegend = function (id) {
  8402. return maxHeight * steps[id];
  8403. };
  8404. }
  8405. xForLegendText = function (id, i) {
  8406. return xForLegend(id, i) + 4 + config.legend_item_tile_width;
  8407. };
  8408. yForLegendText = function (id, i) {
  8409. return yForLegend(id, i) + 9;
  8410. };
  8411. xForLegendRect = function (id, i) {
  8412. return xForLegend(id, i);
  8413. };
  8414. yForLegendRect = function (id, i) {
  8415. return yForLegend(id, i) - 5;
  8416. };
  8417. x1ForLegendTile = function (id, i) {
  8418. return xForLegend(id, i) - 2;
  8419. };
  8420. x2ForLegendTile = function (id, i) {
  8421. return xForLegend(id, i) - 2 + config.legend_item_tile_width;
  8422. };
  8423. yForLegendTile = function (id, i) {
  8424. return yForLegend(id, i) + 4;
  8425. };
  8426. // Define g for legend area
  8427. l = $$.legend
  8428. .selectAll('.' + CLASS.legendItem)
  8429. .data(targetIds)
  8430. .enter()
  8431. .append('g')
  8432. .attr('class', function (id) {
  8433. return $$.generateClass(CLASS.legendItem, id);
  8434. })
  8435. .style('visibility', function (id) {
  8436. return $$.isLegendToShow(id) ? 'visible' : 'hidden';
  8437. })
  8438. .style('cursor', function () {
  8439. return config.interaction_enabled ? 'pointer' : 'auto';
  8440. })
  8441. .on('click', config.interaction_enabled
  8442. ? function (id) {
  8443. if (config.legend_item_onclick) {
  8444. config.legend_item_onclick.call($$, id);
  8445. }
  8446. else {
  8447. if ($$.d3.event.altKey) {
  8448. $$.api.hide();
  8449. $$.api.show(id);
  8450. }
  8451. else {
  8452. $$.api.toggle(id);
  8453. $$.isTargetToShow(id) ? $$.api.focus(id) : $$.api.revert();
  8454. }
  8455. }
  8456. }
  8457. : null)
  8458. .on('mouseover', config.interaction_enabled
  8459. ? function (id) {
  8460. if (config.legend_item_onmouseover) {
  8461. config.legend_item_onmouseover.call($$, id);
  8462. }
  8463. else {
  8464. $$.d3.select(this).classed(CLASS.legendItemFocused, true);
  8465. if (!$$.transiting && $$.isTargetToShow(id)) {
  8466. $$.api.focus(id);
  8467. }
  8468. }
  8469. }
  8470. : null)
  8471. .on('mouseout', config.interaction_enabled
  8472. ? function (id) {
  8473. if (config.legend_item_onmouseout) {
  8474. config.legend_item_onmouseout.call($$, id);
  8475. }
  8476. else {
  8477. $$.d3.select(this).classed(CLASS.legendItemFocused, false);
  8478. $$.api.revert();
  8479. }
  8480. }
  8481. : null);
  8482. l.append('text')
  8483. .text(function (id) {
  8484. return isDefined(config.data_names[id]) ? config.data_names[id] : id;
  8485. })
  8486. .each(function (id, i) {
  8487. updatePositions(this, id, i);
  8488. })
  8489. .style('pointer-events', 'none')
  8490. .attr('x', $$.isLegendRight || $$.isLegendInset ? xForLegendText : -200)
  8491. .attr('y', $$.isLegendRight || $$.isLegendInset ? -200 : yForLegendText);
  8492. l.append('rect')
  8493. .attr('class', CLASS.legendItemEvent)
  8494. .style('fill-opacity', 0)
  8495. .attr('x', $$.isLegendRight || $$.isLegendInset ? xForLegendRect : -200)
  8496. .attr('y', $$.isLegendRight || $$.isLegendInset ? -200 : yForLegendRect);
  8497. l.append('line')
  8498. .attr('class', CLASS.legendItemTile)
  8499. .style('stroke', $$.color)
  8500. .style('pointer-events', 'none')
  8501. .attr('x1', $$.isLegendRight || $$.isLegendInset ? x1ForLegendTile : -200)
  8502. .attr('y1', $$.isLegendRight || $$.isLegendInset ? -200 : yForLegendTile)
  8503. .attr('x2', $$.isLegendRight || $$.isLegendInset ? x2ForLegendTile : -200)
  8504. .attr('y2', $$.isLegendRight || $$.isLegendInset ? -200 : yForLegendTile)
  8505. .attr('stroke-width', config.legend_item_tile_height);
  8506. // Set background for inset legend
  8507. background = $$.legend.select('.' + CLASS.legendBackground + ' rect');
  8508. if ($$.isLegendInset && maxWidth > 0 && background.size() === 0) {
  8509. background = $$.legend
  8510. .insert('g', '.' + CLASS.legendItem)
  8511. .attr('class', CLASS.legendBackground)
  8512. .append('rect');
  8513. }
  8514. texts = $$.legend
  8515. .selectAll('text')
  8516. .data(targetIds)
  8517. .text(function (id) {
  8518. return isDefined(config.data_names[id]) ? config.data_names[id] : id;
  8519. }) // MEMO: needed for update
  8520. .each(function (id, i) {
  8521. updatePositions(this, id, i);
  8522. });
  8523. (withTransition ? texts.transition() : texts)
  8524. .attr('x', xForLegendText)
  8525. .attr('y', yForLegendText);
  8526. rects = $$.legend.selectAll('rect.' + CLASS.legendItemEvent).data(targetIds);
  8527. (withTransition ? rects.transition() : rects)
  8528. .attr('width', function (id) {
  8529. return widths[id];
  8530. })
  8531. .attr('height', function (id) {
  8532. return heights[id];
  8533. })
  8534. .attr('x', xForLegendRect)
  8535. .attr('y', yForLegendRect);
  8536. tiles = $$.legend.selectAll('line.' + CLASS.legendItemTile).data(targetIds);
  8537. (withTransition ? tiles.transition() : tiles)
  8538. .style('stroke', $$.levelColor
  8539. ? function (id) {
  8540. return $$.levelColor($$.cache[id].values.reduce(function (total, item) {
  8541. return total + item.value;
  8542. }, 0));
  8543. }
  8544. : $$.color)
  8545. .attr('x1', x1ForLegendTile)
  8546. .attr('y1', yForLegendTile)
  8547. .attr('x2', x2ForLegendTile)
  8548. .attr('y2', yForLegendTile);
  8549. if (background) {
  8550. (withTransition ? background.transition() : background)
  8551. .attr('height', $$.getLegendHeight() - 12)
  8552. .attr('width', maxWidth * (step + 1) + 10);
  8553. }
  8554. // toggle legend state
  8555. $$.legend
  8556. .selectAll('.' + CLASS.legendItem)
  8557. .classed(CLASS.legendItemHidden, function (id) {
  8558. return !$$.isTargetToShow(id);
  8559. });
  8560. // Update all to reflect change of legend
  8561. $$.updateLegendItemWidth(maxWidth);
  8562. $$.updateLegendItemHeight(maxHeight);
  8563. $$.updateLegendStep(step);
  8564. // Update size and scale
  8565. $$.updateSizes();
  8566. $$.updateScales();
  8567. $$.updateSvgSize();
  8568. // Update g positions
  8569. $$.transformAll(withTransitionForTransform, transitions);
  8570. $$.legendHasRendered = true;
  8571. };
  8572. ChartInternal.prototype.initRegion = function () {
  8573. var $$ = this;
  8574. $$.region = $$.main
  8575. .append('g')
  8576. .attr('clip-path', $$.clipPath)
  8577. .attr('class', CLASS.regions);
  8578. };
  8579. ChartInternal.prototype.updateRegion = function (duration) {
  8580. var $$ = this, config = $$.config;
  8581. // hide if arc type
  8582. $$.region.style('visibility', $$.hasArcType() ? 'hidden' : 'visible');
  8583. var mainRegion = $$.main
  8584. .select('.' + CLASS.regions)
  8585. .selectAll('.' + CLASS.region)
  8586. .data(config.regions);
  8587. var g = mainRegion.enter().append('g');
  8588. g.append('rect')
  8589. .attr('x', $$.regionX.bind($$))
  8590. .attr('y', $$.regionY.bind($$))
  8591. .attr('width', $$.regionWidth.bind($$))
  8592. .attr('height', $$.regionHeight.bind($$))
  8593. .style('fill-opacity', function (d) {
  8594. return isValue(d.opacity) ? d.opacity : 0.1;
  8595. });
  8596. g.append('text').text($$.labelRegion.bind($$));
  8597. $$.mainRegion = g.merge(mainRegion).attr('class', $$.classRegion.bind($$));
  8598. mainRegion
  8599. .exit()
  8600. .transition()
  8601. .duration(duration)
  8602. .style('opacity', 0)
  8603. .remove();
  8604. };
  8605. ChartInternal.prototype.redrawRegion = function (withTransition, transition) {
  8606. var $$ = this, regions = $$.mainRegion, regionLabels = $$.mainRegion.selectAll('text');
  8607. return [
  8608. (withTransition ? regions.transition(transition) : regions)
  8609. .attr('x', $$.regionX.bind($$))
  8610. .attr('y', $$.regionY.bind($$))
  8611. .attr('width', $$.regionWidth.bind($$))
  8612. .attr('height', $$.regionHeight.bind($$))
  8613. .style('fill-opacity', function (d) {
  8614. return isValue(d.opacity) ? d.opacity : 0.1;
  8615. }),
  8616. (withTransition ? regionLabels.transition(transition) : regionLabels)
  8617. .attr('x', $$.labelOffsetX.bind($$))
  8618. .attr('y', $$.labelOffsetY.bind($$))
  8619. .attr('transform', $$.labelTransform.bind($$))
  8620. .attr('style', 'text-anchor: left;')
  8621. ];
  8622. };
  8623. ChartInternal.prototype.regionX = function (d) {
  8624. var $$ = this, config = $$.config, xPos, yScale = d.axis === 'y' ? $$.y : $$.y2;
  8625. if (d.axis === 'y' || d.axis === 'y2') {
  8626. xPos = config.axis_rotated ? ('start' in d ? yScale(d.start) : 0) : 0;
  8627. }
  8628. else {
  8629. xPos = config.axis_rotated
  8630. ? 0
  8631. : 'start' in d
  8632. ? $$.x($$.isTimeSeries() ? $$.parseDate(d.start) : d.start)
  8633. : 0;
  8634. }
  8635. return xPos;
  8636. };
  8637. ChartInternal.prototype.regionY = function (d) {
  8638. var $$ = this, config = $$.config, yPos, yScale = d.axis === 'y' ? $$.y : $$.y2;
  8639. if (d.axis === 'y' || d.axis === 'y2') {
  8640. yPos = config.axis_rotated ? 0 : 'end' in d ? yScale(d.end) : 0;
  8641. }
  8642. else {
  8643. yPos = config.axis_rotated
  8644. ? 'start' in d
  8645. ? $$.x($$.isTimeSeries() ? $$.parseDate(d.start) : d.start)
  8646. : 0
  8647. : 0;
  8648. }
  8649. return yPos;
  8650. };
  8651. ChartInternal.prototype.regionWidth = function (d) {
  8652. var $$ = this, config = $$.config, start = $$.regionX(d), end, yScale = d.axis === 'y' ? $$.y : $$.y2;
  8653. if (d.axis === 'y' || d.axis === 'y2') {
  8654. end = config.axis_rotated
  8655. ? 'end' in d
  8656. ? yScale(d.end)
  8657. : $$.width
  8658. : $$.width;
  8659. }
  8660. else {
  8661. end = config.axis_rotated
  8662. ? $$.width
  8663. : 'end' in d
  8664. ? $$.x($$.isTimeSeries() ? $$.parseDate(d.end) : d.end)
  8665. : $$.width;
  8666. }
  8667. return end < start ? 0 : end - start;
  8668. };
  8669. ChartInternal.prototype.regionHeight = function (d) {
  8670. var $$ = this, config = $$.config, start = this.regionY(d), end, yScale = d.axis === 'y' ? $$.y : $$.y2;
  8671. if (d.axis === 'y' || d.axis === 'y2') {
  8672. end = config.axis_rotated
  8673. ? $$.height
  8674. : 'start' in d
  8675. ? yScale(d.start)
  8676. : $$.height;
  8677. }
  8678. else {
  8679. end = config.axis_rotated
  8680. ? 'end' in d
  8681. ? $$.x($$.isTimeSeries() ? $$.parseDate(d.end) : d.end)
  8682. : $$.height
  8683. : $$.height;
  8684. }
  8685. return end < start ? 0 : end - start;
  8686. };
  8687. ChartInternal.prototype.isRegionOnX = function (d) {
  8688. return !d.axis || d.axis === 'x';
  8689. };
  8690. ChartInternal.prototype.labelRegion = function (d) {
  8691. return 'label' in d ? d.label : '';
  8692. };
  8693. ChartInternal.prototype.labelTransform = function (d) {
  8694. return 'vertical' in d && d.vertical ? 'rotate(90)' : '';
  8695. };
  8696. ChartInternal.prototype.labelOffsetX = function (d) {
  8697. var paddingX = 'paddingX' in d ? d.paddingX : 3;
  8698. var paddingY = 'paddingY' in d ? d.paddingY : 3;
  8699. return 'vertical' in d && d.vertical
  8700. ? this.regionY(d) + paddingY
  8701. : this.regionX(d) + paddingX;
  8702. };
  8703. ChartInternal.prototype.labelOffsetY = function (d) {
  8704. var paddingX = 'paddingX' in d ? d.paddingX : 3;
  8705. var paddingY = 'paddingY' in d ? d.paddingY : 3;
  8706. return 'vertical' in d && d.vertical
  8707. ? -(this.regionX(d) + paddingX)
  8708. : this.regionY(d) + 10 + paddingY;
  8709. };
  8710. function c3LogScale(d3, linearScale, logScale) {
  8711. var PROJECTION = [0.01, 10];
  8712. if (!linearScale) {
  8713. linearScale = d3.scaleLinear();
  8714. linearScale.range(PROJECTION);
  8715. }
  8716. if (!logScale) {
  8717. logScale = d3.scaleLog();
  8718. logScale.domain(PROJECTION);
  8719. logScale.nice();
  8720. }
  8721. // copied from https://github.com/compute-io/logspace
  8722. function logspace(a, b, len) {
  8723. var arr, end, tmp, d;
  8724. if (arguments.length < 3) {
  8725. len = 10;
  8726. }
  8727. else {
  8728. if (len === 0) {
  8729. return [];
  8730. }
  8731. }
  8732. // Calculate the increment:
  8733. end = len - 1;
  8734. d = (b - a) / end;
  8735. // Build the output array...
  8736. arr = new Array(len);
  8737. tmp = a;
  8738. arr[0] = Math.pow(10, tmp);
  8739. for (var i = 1; i < end; i++) {
  8740. tmp += d;
  8741. arr[i] = Math.pow(10, tmp);
  8742. }
  8743. arr[end] = Math.pow(10, b);
  8744. return arr;
  8745. }
  8746. function scale(x) {
  8747. return logScale(linearScale(x));
  8748. }
  8749. scale.domain = function (x) {
  8750. if (!arguments.length) {
  8751. return linearScale.domain();
  8752. }
  8753. linearScale.domain(x);
  8754. return scale;
  8755. };
  8756. scale.range = function (x) {
  8757. if (!arguments.length) {
  8758. return logScale.range();
  8759. }
  8760. logScale.range(x);
  8761. return scale;
  8762. };
  8763. scale.ticks = function (m) {
  8764. return logspace(-2, 1, m || 10).map(function (v) {
  8765. return linearScale.invert(v);
  8766. });
  8767. };
  8768. scale.copy = function () {
  8769. return c3LogScale(d3, linearScale.copy(), logScale.copy());
  8770. };
  8771. return scale;
  8772. }
  8773. ChartInternal.prototype.getScale = function (min, max, forTimeseries) {
  8774. return (forTimeseries ? this.d3.scaleTime() : this.d3.scaleLinear()).range([
  8775. min,
  8776. max
  8777. ]);
  8778. };
  8779. ChartInternal.prototype.getX = function (min, max, domain, offset) {
  8780. var $$ = this, scale = $$.getScale(min, max, $$.isTimeSeries()), _scale = domain ? scale.domain(domain) : scale, key;
  8781. // Define customized scale if categorized axis
  8782. if ($$.isCategorized()) {
  8783. offset =
  8784. offset ||
  8785. function () {
  8786. return 0;
  8787. };
  8788. scale = function (d, raw) {
  8789. var v = _scale(d) + offset(d);
  8790. return raw ? v : Math.ceil(v);
  8791. };
  8792. }
  8793. else {
  8794. scale = function (d, raw) {
  8795. var v = _scale(d);
  8796. return raw ? v : Math.ceil(v);
  8797. };
  8798. }
  8799. // define functions
  8800. for (key in _scale) {
  8801. scale[key] = _scale[key];
  8802. }
  8803. scale.orgDomain = function () {
  8804. return _scale.domain();
  8805. };
  8806. // define custom domain() for categorized axis
  8807. if ($$.isCategorized()) {
  8808. scale.domain = function (domain) {
  8809. if (!arguments.length) {
  8810. domain = this.orgDomain();
  8811. return [domain[0], domain[1] + 1];
  8812. }
  8813. _scale.domain(domain);
  8814. return scale;
  8815. };
  8816. }
  8817. return scale;
  8818. };
  8819. /**
  8820. * Creates and configures a D3 scale instance for the given type.
  8821. *
  8822. * By defaults it returns a Linear scale.
  8823. *
  8824. * @param {String} type Type of d3-scale to create. Type can be 'linear', 'time', 'timeseries' or 'log'.
  8825. * @param {Array} domain The scale domain such as [from, to]
  8826. * @param {Array} range The scale's range such as [from, to]
  8827. *
  8828. * @return A d3-scale instance
  8829. */
  8830. ChartInternal.prototype.getY = function (type, domain, range) {
  8831. var scale;
  8832. if (type === 'timeseries' || type === 'time') {
  8833. scale = this.d3.scaleTime();
  8834. }
  8835. else if (type === 'log') {
  8836. scale = c3LogScale(this.d3);
  8837. }
  8838. else if (type === 'linear' || type === undefined) {
  8839. scale = this.d3.scaleLinear();
  8840. }
  8841. else {
  8842. throw new Error("Invalid Y axis type: \"" + type + "\"");
  8843. }
  8844. if (domain) {
  8845. scale.domain(domain);
  8846. }
  8847. if (range) {
  8848. scale.range(range);
  8849. }
  8850. return scale;
  8851. };
  8852. ChartInternal.prototype.getYScale = function (id) {
  8853. return this.axis.getId(id) === 'y2' ? this.y2 : this.y;
  8854. };
  8855. ChartInternal.prototype.getSubYScale = function (id) {
  8856. return this.axis.getId(id) === 'y2' ? this.subY2 : this.subY;
  8857. };
  8858. ChartInternal.prototype.updateScales = function () {
  8859. var $$ = this, config = $$.config, forInit = !$$.x;
  8860. // update edges
  8861. $$.xMin = config.axis_rotated ? 1 : 0;
  8862. $$.xMax = config.axis_rotated ? $$.height : $$.width;
  8863. $$.yMin = config.axis_rotated ? 0 : $$.height;
  8864. $$.yMax = config.axis_rotated ? $$.width : 1;
  8865. $$.subXMin = $$.xMin;
  8866. $$.subXMax = $$.xMax;
  8867. $$.subYMin = config.axis_rotated ? 0 : $$.height2;
  8868. $$.subYMax = config.axis_rotated ? $$.width2 : 1;
  8869. // update scales
  8870. $$.x = $$.getX($$.xMin, $$.xMax, forInit ? undefined : $$.x.orgDomain(), function () {
  8871. return $$.xAxis.tickOffset();
  8872. });
  8873. $$.y = $$.getY(config.axis_y_type, forInit ? config.axis_y_default : $$.y.domain(), [$$.yMin, $$.yMax]);
  8874. $$.y2 = $$.getY(config.axis_y2_type, forInit ? config.axis_y2_default : $$.y2.domain(), [$$.yMin, $$.yMax]);
  8875. $$.subX = $$.getX($$.xMin, $$.xMax, $$.orgXDomain, function (d) {
  8876. return d % 1 ? 0 : $$.subXAxis.tickOffset();
  8877. });
  8878. $$.subY = $$.getY(config.axis_y_type, forInit ? config.axis_y_default : $$.subY.domain(), [$$.subYMin, $$.subYMax]);
  8879. $$.subY2 = $$.getY(config.axis_y2_type, forInit ? config.axis_y2_default : $$.subY2.domain(), [$$.subYMin, $$.subYMax]);
  8880. // update axes
  8881. $$.xAxisTickFormat = $$.axis.getXAxisTickFormat();
  8882. $$.xAxisTickValues = $$.axis.getXAxisTickValues();
  8883. $$.yAxisTickValues = $$.axis.getYAxisTickValues();
  8884. $$.y2AxisTickValues = $$.axis.getY2AxisTickValues();
  8885. $$.xAxis = $$.axis.getXAxis($$.x, $$.xOrient, $$.xAxisTickFormat, $$.xAxisTickValues, config.axis_x_tick_outer);
  8886. $$.subXAxis = $$.axis.getXAxis($$.subX, $$.subXOrient, $$.xAxisTickFormat, $$.xAxisTickValues, config.axis_x_tick_outer);
  8887. $$.yAxis = $$.axis.getYAxis('y', $$.y, $$.yOrient, $$.yAxisTickValues, config.axis_y_tick_outer);
  8888. $$.y2Axis = $$.axis.getYAxis('y2', $$.y2, $$.y2Orient, $$.y2AxisTickValues, config.axis_y2_tick_outer);
  8889. // Set initialized scales to brush and zoom
  8890. if (!forInit) {
  8891. if ($$.brush) {
  8892. $$.brush.updateScale($$.subX);
  8893. }
  8894. }
  8895. // update for arc
  8896. if ($$.updateArc) {
  8897. $$.updateArc();
  8898. }
  8899. };
  8900. ChartInternal.prototype.selectPoint = function (target, d, i) {
  8901. var $$ = this, config = $$.config, cx = (config.axis_rotated ? $$.circleY : $$.circleX).bind($$), cy = (config.axis_rotated ? $$.circleX : $$.circleY).bind($$), r = $$.pointSelectR.bind($$);
  8902. config.data_onselected.call($$.api, d, target.node());
  8903. // add selected-circle on low layer g
  8904. $$.main
  8905. .select('.' + CLASS.selectedCircles + $$.getTargetSelectorSuffix(d.id))
  8906. .selectAll('.' + CLASS.selectedCircle + '-' + i)
  8907. .data([d])
  8908. .enter()
  8909. .append('circle')
  8910. .attr('class', function () {
  8911. return $$.generateClass(CLASS.selectedCircle, i);
  8912. })
  8913. .attr('cx', cx)
  8914. .attr('cy', cy)
  8915. .attr('stroke', function () {
  8916. return $$.color(d);
  8917. })
  8918. .attr('r', function (d) {
  8919. return $$.pointSelectR(d) * 1.4;
  8920. })
  8921. .transition()
  8922. .duration(100)
  8923. .attr('r', r);
  8924. };
  8925. ChartInternal.prototype.unselectPoint = function (target, d, i) {
  8926. var $$ = this;
  8927. $$.config.data_onunselected.call($$.api, d, target.node());
  8928. // remove selected-circle from low layer g
  8929. $$.main
  8930. .select('.' + CLASS.selectedCircles + $$.getTargetSelectorSuffix(d.id))
  8931. .selectAll('.' + CLASS.selectedCircle + '-' + i)
  8932. .transition()
  8933. .duration(100)
  8934. .attr('r', 0)
  8935. .remove();
  8936. };
  8937. ChartInternal.prototype.togglePoint = function (selected, target, d, i) {
  8938. selected ? this.selectPoint(target, d, i) : this.unselectPoint(target, d, i);
  8939. };
  8940. ChartInternal.prototype.selectPath = function (target, d) {
  8941. var $$ = this;
  8942. $$.config.data_onselected.call($$, d, target.node());
  8943. if ($$.config.interaction_brighten) {
  8944. target
  8945. .transition()
  8946. .duration(100)
  8947. .style('fill', function () {
  8948. return $$.d3.rgb($$.color(d)).brighter(0.75);
  8949. });
  8950. }
  8951. };
  8952. ChartInternal.prototype.unselectPath = function (target, d) {
  8953. var $$ = this;
  8954. $$.config.data_onunselected.call($$, d, target.node());
  8955. if ($$.config.interaction_brighten) {
  8956. target
  8957. .transition()
  8958. .duration(100)
  8959. .style('fill', function () {
  8960. return $$.color(d);
  8961. });
  8962. }
  8963. };
  8964. ChartInternal.prototype.togglePath = function (selected, target, d, i) {
  8965. selected ? this.selectPath(target, d, i) : this.unselectPath(target, d, i);
  8966. };
  8967. ChartInternal.prototype.getToggle = function (that, d) {
  8968. var $$ = this, toggle;
  8969. if (that.nodeName === 'circle') {
  8970. if ($$.isStepType(d)) {
  8971. // circle is hidden in step chart, so treat as within the click area
  8972. toggle = function () { }; // TODO: how to select step chart?
  8973. }
  8974. else {
  8975. toggle = $$.togglePoint;
  8976. }
  8977. }
  8978. else if (that.nodeName === 'path') {
  8979. toggle = $$.togglePath;
  8980. }
  8981. return toggle;
  8982. };
  8983. ChartInternal.prototype.toggleShape = function (that, d, i) {
  8984. var $$ = this, d3 = $$.d3, config = $$.config, shape = d3.select(that), isSelected = shape.classed(CLASS.SELECTED), toggle = $$.getToggle(that, d).bind($$);
  8985. if (config.data_selection_enabled && config.data_selection_isselectable(d)) {
  8986. if (!config.data_selection_multiple) {
  8987. $$.main
  8988. .selectAll('.' +
  8989. CLASS.shapes +
  8990. (config.data_selection_grouped
  8991. ? $$.getTargetSelectorSuffix(d.id)
  8992. : ''))
  8993. .selectAll('.' + CLASS.shape)
  8994. .each(function (d, i) {
  8995. var shape = d3.select(this);
  8996. if (shape.classed(CLASS.SELECTED)) {
  8997. toggle(false, shape.classed(CLASS.SELECTED, false), d, i);
  8998. }
  8999. });
  9000. }
  9001. shape.classed(CLASS.SELECTED, !isSelected);
  9002. toggle(!isSelected, shape, d, i);
  9003. }
  9004. };
  9005. ChartInternal.prototype.initBar = function () {
  9006. var $$ = this;
  9007. $$.main
  9008. .select('.' + CLASS.chart)
  9009. .append('g')
  9010. .attr('class', CLASS.chartBars);
  9011. };
  9012. ChartInternal.prototype.updateTargetsForBar = function (targets) {
  9013. var $$ = this, config = $$.config, mainBars, mainBarEnter, classChartBar = $$.classChartBar.bind($$), classBars = $$.classBars.bind($$), classFocus = $$.classFocus.bind($$);
  9014. mainBars = $$.main
  9015. .select('.' + CLASS.chartBars)
  9016. .selectAll('.' + CLASS.chartBar)
  9017. .data(targets)
  9018. .attr('class', function (d) {
  9019. return classChartBar(d) + classFocus(d);
  9020. });
  9021. mainBarEnter = mainBars
  9022. .enter()
  9023. .append('g')
  9024. .attr('class', classChartBar)
  9025. .style('pointer-events', 'none');
  9026. // Bars for each data
  9027. mainBarEnter
  9028. .append('g')
  9029. .attr('class', classBars)
  9030. .style('cursor', function (d) {
  9031. return config.data_selection_isselectable(d) ? 'pointer' : null;
  9032. });
  9033. };
  9034. ChartInternal.prototype.updateBar = function (durationForExit) {
  9035. var $$ = this, barData = $$.barData.bind($$), classBar = $$.classBar.bind($$), initialOpacity = $$.initialOpacity.bind($$), color = function (d) {
  9036. return $$.color(d.id);
  9037. };
  9038. var mainBar = $$.main
  9039. .selectAll('.' + CLASS.bars)
  9040. .selectAll('.' + CLASS.bar)
  9041. .data(barData);
  9042. var mainBarEnter = mainBar
  9043. .enter()
  9044. .append('path')
  9045. .attr('class', classBar)
  9046. .style('stroke', color)
  9047. .style('fill', color);
  9048. $$.mainBar = mainBarEnter.merge(mainBar).style('opacity', initialOpacity);
  9049. mainBar
  9050. .exit()
  9051. .transition()
  9052. .duration(durationForExit)
  9053. .style('opacity', 0);
  9054. };
  9055. ChartInternal.prototype.redrawBar = function (drawBar, withTransition, transition) {
  9056. var $$ = this;
  9057. return [
  9058. (withTransition ? this.mainBar.transition(transition) : this.mainBar)
  9059. .attr('d', drawBar)
  9060. .style('stroke', this.color)
  9061. .style('fill', this.color)
  9062. .style('opacity', function (d) { return ($$.isTargetToShow(d.id) ? 1 : 0); })
  9063. ];
  9064. };
  9065. ChartInternal.prototype.getBarW = function (axis, barTargetsNum) {
  9066. var $$ = this, config = $$.config, w = typeof config.bar_width === 'number'
  9067. ? config.bar_width
  9068. : barTargetsNum
  9069. ? (axis.tickInterval() * config.bar_width_ratio) / barTargetsNum
  9070. : 0;
  9071. return config.bar_width_max && w > config.bar_width_max
  9072. ? config.bar_width_max
  9073. : w;
  9074. };
  9075. ChartInternal.prototype.getBars = function (i, id) {
  9076. var $$ = this;
  9077. return (id
  9078. ? $$.main.selectAll('.' + CLASS.bars + $$.getTargetSelectorSuffix(id))
  9079. : $$.main).selectAll('.' + CLASS.bar + (isValue(i) ? '-' + i : ''));
  9080. };
  9081. ChartInternal.prototype.expandBars = function (i, id, reset) {
  9082. var $$ = this;
  9083. if (reset) {
  9084. $$.unexpandBars();
  9085. }
  9086. $$.getBars(i, id).classed(CLASS.EXPANDED, true);
  9087. };
  9088. ChartInternal.prototype.unexpandBars = function (i) {
  9089. var $$ = this;
  9090. $$.getBars(i).classed(CLASS.EXPANDED, false);
  9091. };
  9092. ChartInternal.prototype.generateDrawBar = function (barIndices, isSub) {
  9093. var $$ = this, config = $$.config, getPoints = $$.generateGetBarPoints(barIndices, isSub);
  9094. return function (d, i) {
  9095. // 4 points that make a bar
  9096. var points = getPoints(d, i);
  9097. // switch points if axis is rotated, not applicable for sub chart
  9098. var indexX = config.axis_rotated ? 1 : 0;
  9099. var indexY = config.axis_rotated ? 0 : 1;
  9100. var path = 'M ' +
  9101. points[0][indexX] +
  9102. ',' +
  9103. points[0][indexY] +
  9104. ' ' +
  9105. 'L' +
  9106. points[1][indexX] +
  9107. ',' +
  9108. points[1][indexY] +
  9109. ' ' +
  9110. 'L' +
  9111. points[2][indexX] +
  9112. ',' +
  9113. points[2][indexY] +
  9114. ' ' +
  9115. 'L' +
  9116. points[3][indexX] +
  9117. ',' +
  9118. points[3][indexY] +
  9119. ' ' +
  9120. 'z';
  9121. return path;
  9122. };
  9123. };
  9124. ChartInternal.prototype.generateGetBarPoints = function (barIndices, isSub) {
  9125. var $$ = this, axis = isSub ? $$.subXAxis : $$.xAxis, barTargetsNum = barIndices.__max__ + 1, barW = $$.getBarW(axis, barTargetsNum), barX = $$.getShapeX(barW, barTargetsNum, barIndices, !!isSub), barY = $$.getShapeY(!!isSub), barOffset = $$.getShapeOffset($$.isBarType, barIndices, !!isSub), barSpaceOffset = barW * ($$.config.bar_space / 2), yScale = isSub ? $$.getSubYScale : $$.getYScale;
  9126. return function (d, i) {
  9127. var y0 = yScale.call($$, d.id)(0), offset = barOffset(d, i) || y0, // offset is for stacked bar chart
  9128. posX = barX(d), posY = barY(d);
  9129. // fix posY not to overflow opposite quadrant
  9130. if ($$.config.axis_rotated) {
  9131. if ((0 < d.value && posY < y0) || (d.value < 0 && y0 < posY)) {
  9132. posY = y0;
  9133. }
  9134. }
  9135. posY -= y0 - offset;
  9136. // 4 points that make a bar
  9137. return [
  9138. [posX + barSpaceOffset, offset],
  9139. [posX + barSpaceOffset, posY],
  9140. [posX + barW - barSpaceOffset, posY],
  9141. [posX + barW - barSpaceOffset, offset]
  9142. ];
  9143. };
  9144. };
  9145. /**
  9146. * Returns whether the data point is within the given bar shape.
  9147. *
  9148. * @param mouse
  9149. * @param barShape
  9150. * @return {boolean}
  9151. */
  9152. ChartInternal.prototype.isWithinBar = function (mouse, barShape) {
  9153. return isWithinBox(mouse, getBBox(barShape), 2);
  9154. };
  9155. ChartInternal.prototype.getShapeIndices = function (typeFilter) {
  9156. var $$ = this, config = $$.config, indices = {}, i = 0, j, k;
  9157. $$.filterTargetsToShow($$.data.targets.filter(typeFilter, $$)).forEach(function (d) {
  9158. for (j = 0; j < config.data_groups.length; j++) {
  9159. if (config.data_groups[j].indexOf(d.id) < 0) {
  9160. continue;
  9161. }
  9162. for (k = 0; k < config.data_groups[j].length; k++) {
  9163. if (config.data_groups[j][k] in indices) {
  9164. indices[d.id] = indices[config.data_groups[j][k]];
  9165. break;
  9166. }
  9167. }
  9168. }
  9169. if (isUndefined(indices[d.id])) {
  9170. indices[d.id] = i++;
  9171. }
  9172. });
  9173. indices.__max__ = i - 1;
  9174. return indices;
  9175. };
  9176. ChartInternal.prototype.getShapeX = function (offset, targetsNum, indices, isSub) {
  9177. var $$ = this, scale = isSub ? $$.subX : $$.x;
  9178. return function (d) {
  9179. var index = d.id in indices ? indices[d.id] : 0;
  9180. return d.x || d.x === 0 ? scale(d.x) - offset * (targetsNum / 2 - index) : 0;
  9181. };
  9182. };
  9183. ChartInternal.prototype.getShapeY = function (isSub) {
  9184. var $$ = this;
  9185. return function (d) {
  9186. var scale = isSub ? $$.getSubYScale(d.id) : $$.getYScale(d.id);
  9187. return scale($$.isTargetNormalized(d.id) ? $$.getRatio('index', d, true) : d.value);
  9188. };
  9189. };
  9190. ChartInternal.prototype.getShapeOffset = function (typeFilter, indices, isSub) {
  9191. var $$ = this, targets = $$.orderTargets($$.filterTargetsToShow($$.data.targets.filter(typeFilter, $$))), targetIds = targets.map(function (t) {
  9192. return t.id;
  9193. });
  9194. return function (d, i) {
  9195. var scale = isSub ? $$.getSubYScale(d.id) : $$.getYScale(d.id), y0 = scale(0), offset = y0;
  9196. targets.forEach(function (t) {
  9197. var rowValues = $$.isStepType(d)
  9198. ? $$.convertValuesToStep(t.values)
  9199. : t.values;
  9200. var isTargetNormalized = $$.isTargetNormalized(d.id);
  9201. var values = rowValues.map(function (v) {
  9202. return isTargetNormalized ? $$.getRatio('index', v, true) : v.value;
  9203. });
  9204. if (t.id === d.id || indices[t.id] !== indices[d.id]) {
  9205. return;
  9206. }
  9207. if (targetIds.indexOf(t.id) < targetIds.indexOf(d.id)) {
  9208. // check if the x values line up
  9209. if (isUndefined(rowValues[i]) || +rowValues[i].x !== +d.x) {
  9210. // "+" for timeseries
  9211. // if not, try to find the value that does line up
  9212. i = -1;
  9213. rowValues.forEach(function (v, j) {
  9214. var x1 = v.x.constructor === Date ? +v.x : v.x;
  9215. var x2 = d.x.constructor === Date ? +d.x : d.x;
  9216. if (x1 === x2) {
  9217. i = j;
  9218. }
  9219. });
  9220. }
  9221. if (i in rowValues && rowValues[i].value * d.value >= 0) {
  9222. offset += scale(values[i]) - y0;
  9223. }
  9224. }
  9225. });
  9226. return offset;
  9227. };
  9228. };
  9229. ChartInternal.prototype.isWithinShape = function (that, d) {
  9230. var $$ = this, shape = $$.d3.select(that), isWithin;
  9231. if (!$$.isTargetToShow(d.id)) {
  9232. isWithin = false;
  9233. }
  9234. else if (that.nodeName === 'circle') {
  9235. isWithin = $$.isStepType(d)
  9236. ? $$.isWithinStep(that, $$.getYScale(d.id)(d.value))
  9237. : $$.isWithinCircle(that, $$.pointSelectR(d) * 1.5);
  9238. }
  9239. else if (that.nodeName === 'path') {
  9240. isWithin = shape.classed(CLASS.bar)
  9241. ? $$.isWithinBar($$.d3.mouse(that), that)
  9242. : true;
  9243. }
  9244. return isWithin;
  9245. };
  9246. ChartInternal.prototype.getInterpolate = function (d) {
  9247. var $$ = this, d3 = $$.d3, types = {
  9248. linear: d3.curveLinear,
  9249. 'linear-closed': d3.curveLinearClosed,
  9250. basis: d3.curveBasis,
  9251. 'basis-open': d3.curveBasisOpen,
  9252. 'basis-closed': d3.curveBasisClosed,
  9253. bundle: d3.curveBundle,
  9254. cardinal: d3.curveCardinal,
  9255. 'cardinal-open': d3.curveCardinalOpen,
  9256. 'cardinal-closed': d3.curveCardinalClosed,
  9257. monotone: d3.curveMonotoneX,
  9258. step: d3.curveStep,
  9259. 'step-before': d3.curveStepBefore,
  9260. 'step-after': d3.curveStepAfter
  9261. }, type;
  9262. if ($$.isSplineType(d)) {
  9263. type = types[$$.config.spline_interpolation_type] || types.cardinal;
  9264. }
  9265. else if ($$.isStepType(d)) {
  9266. type = types[$$.config.line_step_type];
  9267. }
  9268. else {
  9269. type = types.linear;
  9270. }
  9271. return type;
  9272. };
  9273. ChartInternal.prototype.initLine = function () {
  9274. var $$ = this;
  9275. $$.main
  9276. .select('.' + CLASS.chart)
  9277. .append('g')
  9278. .attr('class', CLASS.chartLines);
  9279. };
  9280. ChartInternal.prototype.updateTargetsForLine = function (targets) {
  9281. var $$ = this, config = $$.config, mainLines, mainLineEnter, classChartLine = $$.classChartLine.bind($$), classLines = $$.classLines.bind($$), classAreas = $$.classAreas.bind($$), classCircles = $$.classCircles.bind($$), classFocus = $$.classFocus.bind($$);
  9282. mainLines = $$.main
  9283. .select('.' + CLASS.chartLines)
  9284. .selectAll('.' + CLASS.chartLine)
  9285. .data(targets)
  9286. .attr('class', function (d) {
  9287. return classChartLine(d) + classFocus(d);
  9288. });
  9289. mainLineEnter = mainLines
  9290. .enter()
  9291. .append('g')
  9292. .attr('class', classChartLine)
  9293. .style('opacity', 0)
  9294. .style('pointer-events', 'none');
  9295. // Lines for each data
  9296. mainLineEnter.append('g').attr('class', classLines);
  9297. // Areas
  9298. mainLineEnter.append('g').attr('class', classAreas);
  9299. // Circles for each data point on lines
  9300. mainLineEnter.append('g').attr('class', function (d) {
  9301. return $$.generateClass(CLASS.selectedCircles, d.id);
  9302. });
  9303. mainLineEnter
  9304. .append('g')
  9305. .attr('class', classCircles)
  9306. .style('cursor', function (d) {
  9307. return config.data_selection_isselectable(d) ? 'pointer' : null;
  9308. });
  9309. // Update date for selected circles
  9310. targets.forEach(function (t) {
  9311. $$.main
  9312. .selectAll('.' + CLASS.selectedCircles + $$.getTargetSelectorSuffix(t.id))
  9313. .selectAll('.' + CLASS.selectedCircle)
  9314. .each(function (d) {
  9315. d.value = t.values[d.index].value;
  9316. });
  9317. });
  9318. // MEMO: can not keep same color...
  9319. //mainLineUpdate.exit().remove();
  9320. };
  9321. ChartInternal.prototype.updateLine = function (durationForExit) {
  9322. var $$ = this;
  9323. var mainLine = $$.main
  9324. .selectAll('.' + CLASS.lines)
  9325. .selectAll('.' + CLASS.line)
  9326. .data($$.lineData.bind($$));
  9327. var mainLineEnter = mainLine
  9328. .enter()
  9329. .append('path')
  9330. .attr('class', $$.classLine.bind($$))
  9331. .style('stroke', $$.color);
  9332. $$.mainLine = mainLineEnter
  9333. .merge(mainLine)
  9334. .style('opacity', $$.initialOpacity.bind($$))
  9335. .style('shape-rendering', function (d) {
  9336. return $$.isStepType(d) ? 'crispEdges' : '';
  9337. })
  9338. .attr('transform', null);
  9339. mainLine
  9340. .exit()
  9341. .transition()
  9342. .duration(durationForExit)
  9343. .style('opacity', 0);
  9344. };
  9345. ChartInternal.prototype.redrawLine = function (drawLine, withTransition, transition) {
  9346. return [
  9347. (withTransition ? this.mainLine.transition(transition) : this.mainLine)
  9348. .attr('d', drawLine)
  9349. .style('stroke', this.color)
  9350. .style('opacity', 1)
  9351. ];
  9352. };
  9353. ChartInternal.prototype.generateDrawLine = function (lineIndices, isSub) {
  9354. var $$ = this, config = $$.config, line = $$.d3.line(), getPoints = $$.generateGetLinePoints(lineIndices, isSub), yScaleGetter = isSub ? $$.getSubYScale : $$.getYScale, xValue = function (d) {
  9355. return (isSub ? $$.subxx : $$.xx).call($$, d);
  9356. }, yValue = function (d, i) {
  9357. return config.data_groups.length > 0
  9358. ? getPoints(d, i)[0][1]
  9359. : yScaleGetter.call($$, d.id)(d.value);
  9360. };
  9361. line = config.axis_rotated
  9362. ? line.x(yValue).y(xValue)
  9363. : line.x(xValue).y(yValue);
  9364. if (!config.line_connectNull) {
  9365. line = line.defined(function (d) {
  9366. return d.value != null;
  9367. });
  9368. }
  9369. return function (d) {
  9370. var values = config.line_connectNull
  9371. ? $$.filterRemoveNull(d.values)
  9372. : d.values, x = isSub ? $$.subX : $$.x, y = yScaleGetter.call($$, d.id), x0 = 0, y0 = 0, path;
  9373. if ($$.isLineType(d)) {
  9374. if (config.data_regions[d.id]) {
  9375. path = $$.lineWithRegions(values, x, y, config.data_regions[d.id]);
  9376. }
  9377. else {
  9378. if ($$.isStepType(d)) {
  9379. values = $$.convertValuesToStep(values);
  9380. }
  9381. path = line.curve($$.getInterpolate(d))(values);
  9382. }
  9383. }
  9384. else {
  9385. if (values[0]) {
  9386. x0 = x(values[0].x);
  9387. y0 = y(values[0].value);
  9388. }
  9389. path = config.axis_rotated ? 'M ' + y0 + ' ' + x0 : 'M ' + x0 + ' ' + y0;
  9390. }
  9391. return path ? path : 'M 0 0';
  9392. };
  9393. };
  9394. ChartInternal.prototype.generateGetLinePoints = function (lineIndices, isSub) {
  9395. // partial duplication of generateGetBarPoints
  9396. var $$ = this, config = $$.config, lineTargetsNum = lineIndices.__max__ + 1, x = $$.getShapeX(0, lineTargetsNum, lineIndices, !!isSub), y = $$.getShapeY(!!isSub), lineOffset = $$.getShapeOffset($$.isLineType, lineIndices, !!isSub), yScale = isSub ? $$.getSubYScale : $$.getYScale;
  9397. return function (d, i) {
  9398. var y0 = yScale.call($$, d.id)(0), offset = lineOffset(d, i) || y0, // offset is for stacked area chart
  9399. posX = x(d), posY = y(d);
  9400. // fix posY not to overflow opposite quadrant
  9401. if (config.axis_rotated) {
  9402. if ((0 < d.value && posY < y0) || (d.value < 0 && y0 < posY)) {
  9403. posY = y0;
  9404. }
  9405. }
  9406. // 1 point that marks the line position
  9407. return [
  9408. [posX, posY - (y0 - offset)],
  9409. [posX, posY - (y0 - offset)],
  9410. [posX, posY - (y0 - offset)],
  9411. [posX, posY - (y0 - offset)] // needed for compatibility
  9412. ];
  9413. };
  9414. };
  9415. ChartInternal.prototype.lineWithRegions = function (d, x, y, _regions) {
  9416. var $$ = this, config = $$.config, prev = -1, i, j, s = 'M', sWithRegion, xp, yp, dx, dy, dd, diff, diffx2, xOffset = $$.isCategorized() ? 0.5 : 0, xValue, yValue, regions = [];
  9417. function isWithinRegions(x, regions) {
  9418. var i;
  9419. for (i = 0; i < regions.length; i++) {
  9420. if (regions[i].start < x && x <= regions[i].end) {
  9421. return true;
  9422. }
  9423. }
  9424. return false;
  9425. }
  9426. // Check start/end of regions
  9427. if (isDefined(_regions)) {
  9428. for (i = 0; i < _regions.length; i++) {
  9429. regions[i] = {};
  9430. if (isUndefined(_regions[i].start)) {
  9431. regions[i].start = d[0].x;
  9432. }
  9433. else {
  9434. regions[i].start = $$.isTimeSeries()
  9435. ? $$.parseDate(_regions[i].start)
  9436. : _regions[i].start;
  9437. }
  9438. if (isUndefined(_regions[i].end)) {
  9439. regions[i].end = d[d.length - 1].x;
  9440. }
  9441. else {
  9442. regions[i].end = $$.isTimeSeries()
  9443. ? $$.parseDate(_regions[i].end)
  9444. : _regions[i].end;
  9445. }
  9446. }
  9447. }
  9448. // Set scales
  9449. xValue = config.axis_rotated
  9450. ? function (d) {
  9451. return y(d.value);
  9452. }
  9453. : function (d) {
  9454. return x(d.x);
  9455. };
  9456. yValue = config.axis_rotated
  9457. ? function (d) {
  9458. return x(d.x);
  9459. }
  9460. : function (d) {
  9461. return y(d.value);
  9462. };
  9463. // Define svg generator function for region
  9464. function generateM(points) {
  9465. return ('M' +
  9466. points[0][0] +
  9467. ' ' +
  9468. points[0][1] +
  9469. ' ' +
  9470. points[1][0] +
  9471. ' ' +
  9472. points[1][1]);
  9473. }
  9474. if ($$.isTimeSeries()) {
  9475. sWithRegion = function (d0, d1, j, diff) {
  9476. var x0 = d0.x.getTime(), x_diff = d1.x - d0.x, xv0 = new Date(x0 + x_diff * j), xv1 = new Date(x0 + x_diff * (j + diff)), points;
  9477. if (config.axis_rotated) {
  9478. points = [
  9479. [y(yp(j)), x(xv0)],
  9480. [y(yp(j + diff)), x(xv1)]
  9481. ];
  9482. }
  9483. else {
  9484. points = [
  9485. [x(xv0), y(yp(j))],
  9486. [x(xv1), y(yp(j + diff))]
  9487. ];
  9488. }
  9489. return generateM(points);
  9490. };
  9491. }
  9492. else {
  9493. sWithRegion = function (d0, d1, j, diff) {
  9494. var points;
  9495. if (config.axis_rotated) {
  9496. points = [
  9497. [y(yp(j), true), x(xp(j))],
  9498. [y(yp(j + diff), true), x(xp(j + diff))]
  9499. ];
  9500. }
  9501. else {
  9502. points = [
  9503. [x(xp(j), true), y(yp(j))],
  9504. [x(xp(j + diff), true), y(yp(j + diff))]
  9505. ];
  9506. }
  9507. return generateM(points);
  9508. };
  9509. }
  9510. // Generate
  9511. for (i = 0; i < d.length; i++) {
  9512. // Draw as normal
  9513. if (isUndefined(regions) || !isWithinRegions(d[i].x, regions)) {
  9514. s += ' ' + xValue(d[i]) + ' ' + yValue(d[i]);
  9515. }
  9516. // Draw with region // TODO: Fix for horizotal charts
  9517. else {
  9518. xp = $$.getScale(d[i - 1].x + xOffset, d[i].x + xOffset, $$.isTimeSeries());
  9519. yp = $$.getScale(d[i - 1].value, d[i].value);
  9520. dx = x(d[i].x) - x(d[i - 1].x);
  9521. dy = y(d[i].value) - y(d[i - 1].value);
  9522. dd = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));
  9523. diff = 2 / dd;
  9524. diffx2 = diff * 2;
  9525. for (j = diff; j <= 1; j += diffx2) {
  9526. s += sWithRegion(d[i - 1], d[i], j, diff);
  9527. }
  9528. }
  9529. prev = d[i].x;
  9530. }
  9531. return s;
  9532. };
  9533. ChartInternal.prototype.updateArea = function (durationForExit) {
  9534. var $$ = this, d3 = $$.d3;
  9535. var mainArea = $$.main
  9536. .selectAll('.' + CLASS.areas)
  9537. .selectAll('.' + CLASS.area)
  9538. .data($$.lineData.bind($$));
  9539. var mainAreaEnter = mainArea
  9540. .enter()
  9541. .append('path')
  9542. .attr('class', $$.classArea.bind($$))
  9543. .style('fill', $$.color)
  9544. .style('opacity', function () {
  9545. $$.orgAreaOpacity = +d3.select(this).style('opacity');
  9546. return 0;
  9547. });
  9548. $$.mainArea = mainAreaEnter
  9549. .merge(mainArea)
  9550. .style('opacity', $$.orgAreaOpacity);
  9551. mainArea
  9552. .exit()
  9553. .transition()
  9554. .duration(durationForExit)
  9555. .style('opacity', 0);
  9556. };
  9557. ChartInternal.prototype.redrawArea = function (drawArea, withTransition, transition) {
  9558. return [
  9559. (withTransition ? this.mainArea.transition(transition) : this.mainArea)
  9560. .attr('d', drawArea)
  9561. .style('fill', this.color)
  9562. .style('opacity', this.orgAreaOpacity)
  9563. ];
  9564. };
  9565. ChartInternal.prototype.generateDrawArea = function (areaIndices, isSub) {
  9566. var $$ = this, config = $$.config, area = $$.d3.area(), getPoints = $$.generateGetAreaPoints(areaIndices, isSub), yScaleGetter = isSub ? $$.getSubYScale : $$.getYScale, xValue = function (d) {
  9567. return (isSub ? $$.subxx : $$.xx).call($$, d);
  9568. }, value0 = function (d, i) {
  9569. return config.data_groups.length > 0
  9570. ? getPoints(d, i)[0][1]
  9571. : yScaleGetter.call($$, d.id)($$.getAreaBaseValue(d.id));
  9572. }, value1 = function (d, i) {
  9573. return config.data_groups.length > 0
  9574. ? getPoints(d, i)[1][1]
  9575. : yScaleGetter.call($$, d.id)(d.value);
  9576. };
  9577. area = config.axis_rotated
  9578. ? area
  9579. .x0(value0)
  9580. .x1(value1)
  9581. .y(xValue)
  9582. : area
  9583. .x(xValue)
  9584. .y0(config.area_above ? 0 : value0)
  9585. .y1(value1);
  9586. if (!config.line_connectNull) {
  9587. area = area.defined(function (d) {
  9588. return d.value !== null;
  9589. });
  9590. }
  9591. return function (d) {
  9592. var values = config.line_connectNull
  9593. ? $$.filterRemoveNull(d.values)
  9594. : d.values, x0 = 0, y0 = 0, path;
  9595. if ($$.isAreaType(d)) {
  9596. if ($$.isStepType(d)) {
  9597. values = $$.convertValuesToStep(values);
  9598. }
  9599. path = area.curve($$.getInterpolate(d))(values);
  9600. }
  9601. else {
  9602. if (values[0]) {
  9603. x0 = $$.x(values[0].x);
  9604. y0 = $$.getYScale(d.id)(values[0].value);
  9605. }
  9606. path = config.axis_rotated ? 'M ' + y0 + ' ' + x0 : 'M ' + x0 + ' ' + y0;
  9607. }
  9608. return path ? path : 'M 0 0';
  9609. };
  9610. };
  9611. ChartInternal.prototype.getAreaBaseValue = function () {
  9612. return 0;
  9613. };
  9614. ChartInternal.prototype.generateGetAreaPoints = function (areaIndices, isSub) {
  9615. // partial duplication of generateGetBarPoints
  9616. var $$ = this, config = $$.config, areaTargetsNum = areaIndices.__max__ + 1, x = $$.getShapeX(0, areaTargetsNum, areaIndices, !!isSub), y = $$.getShapeY(!!isSub), areaOffset = $$.getShapeOffset($$.isAreaType, areaIndices, !!isSub), yScale = isSub ? $$.getSubYScale : $$.getYScale;
  9617. return function (d, i) {
  9618. var y0 = yScale.call($$, d.id)(0), offset = areaOffset(d, i) || y0, // offset is for stacked area chart
  9619. posX = x(d), posY = y(d);
  9620. // fix posY not to overflow opposite quadrant
  9621. if (config.axis_rotated) {
  9622. if ((0 < d.value && posY < y0) || (d.value < 0 && y0 < posY)) {
  9623. posY = y0;
  9624. }
  9625. }
  9626. // 1 point that marks the area position
  9627. return [
  9628. [posX, offset],
  9629. [posX, posY - (y0 - offset)],
  9630. [posX, posY - (y0 - offset)],
  9631. [posX, offset] // needed for compatibility
  9632. ];
  9633. };
  9634. };
  9635. ChartInternal.prototype.updateCircle = function (cx, cy) {
  9636. var $$ = this;
  9637. var mainCircle = $$.main
  9638. .selectAll('.' + CLASS.circles)
  9639. .selectAll('.' + CLASS.circle)
  9640. .data($$.lineOrScatterOrStanfordData.bind($$));
  9641. var mainCircleEnter = mainCircle
  9642. .enter()
  9643. .append('circle')
  9644. .attr('shape-rendering', $$.isStanfordGraphType() ? 'crispEdges' : '')
  9645. .attr('class', $$.classCircle.bind($$))
  9646. .attr('cx', cx)
  9647. .attr('cy', cy)
  9648. .attr('r', $$.pointR.bind($$))
  9649. .style('color', $$.isStanfordGraphType() ? $$.getStanfordPointColor.bind($$) : $$.color);
  9650. $$.mainCircle = mainCircleEnter
  9651. .merge(mainCircle)
  9652. .style('opacity', $$.isStanfordGraphType() ? 1 : $$.initialOpacityForCircle.bind($$));
  9653. mainCircle.exit().style('opacity', 0);
  9654. };
  9655. ChartInternal.prototype.redrawCircle = function (cx, cy, withTransition, transition) {
  9656. var $$ = this, selectedCircles = $$.main.selectAll('.' + CLASS.selectedCircle);
  9657. return [
  9658. (withTransition ? $$.mainCircle.transition(transition) : $$.mainCircle)
  9659. .style('opacity', this.opacityForCircle.bind($$))
  9660. .style('color', $$.isStanfordGraphType() ? $$.getStanfordPointColor.bind($$) : $$.color)
  9661. .attr('cx', cx)
  9662. .attr('cy', cy),
  9663. (withTransition ? selectedCircles.transition(transition) : selectedCircles)
  9664. .attr('cx', cx)
  9665. .attr('cy', cy)
  9666. ];
  9667. };
  9668. ChartInternal.prototype.circleX = function (d) {
  9669. return d.x || d.x === 0 ? this.x(d.x) : null;
  9670. };
  9671. ChartInternal.prototype.updateCircleY = function () {
  9672. var $$ = this, lineIndices, getPoints;
  9673. if ($$.config.data_groups.length > 0) {
  9674. (lineIndices = $$.getShapeIndices($$.isLineType)),
  9675. (getPoints = $$.generateGetLinePoints(lineIndices));
  9676. $$.circleY = function (d, i) {
  9677. return getPoints(d, i)[0][1];
  9678. };
  9679. }
  9680. else {
  9681. $$.circleY = function (d) {
  9682. return $$.getYScale(d.id)(d.value);
  9683. };
  9684. }
  9685. };
  9686. ChartInternal.prototype.getCircles = function (i, id) {
  9687. var $$ = this;
  9688. return (id
  9689. ? $$.main.selectAll('.' + CLASS.circles + $$.getTargetSelectorSuffix(id))
  9690. : $$.main).selectAll('.' + CLASS.circle + (isValue(i) ? '-' + i : ''));
  9691. };
  9692. ChartInternal.prototype.expandCircles = function (i, id, reset) {
  9693. var $$ = this, r = $$.pointExpandedR.bind($$);
  9694. if (reset) {
  9695. $$.unexpandCircles();
  9696. }
  9697. $$.getCircles(i, id)
  9698. .classed(CLASS.EXPANDED, true)
  9699. .attr('r', r);
  9700. };
  9701. ChartInternal.prototype.unexpandCircles = function (i) {
  9702. var $$ = this, r = $$.pointR.bind($$);
  9703. $$.getCircles(i)
  9704. .filter(function () {
  9705. return $$.d3.select(this).classed(CLASS.EXPANDED);
  9706. })
  9707. .classed(CLASS.EXPANDED, false)
  9708. .attr('r', r);
  9709. };
  9710. ChartInternal.prototype.pointR = function (d) {
  9711. var $$ = this, config = $$.config;
  9712. return $$.isStepType(d)
  9713. ? 0
  9714. : isFunction(config.point_r)
  9715. ? config.point_r(d)
  9716. : config.point_r;
  9717. };
  9718. ChartInternal.prototype.pointExpandedR = function (d) {
  9719. var $$ = this, config = $$.config;
  9720. if (config.point_focus_expand_enabled) {
  9721. return isFunction(config.point_focus_expand_r)
  9722. ? config.point_focus_expand_r(d)
  9723. : config.point_focus_expand_r
  9724. ? config.point_focus_expand_r
  9725. : $$.pointR(d) * 1.75;
  9726. }
  9727. else {
  9728. return $$.pointR(d);
  9729. }
  9730. };
  9731. ChartInternal.prototype.pointSelectR = function (d) {
  9732. var $$ = this, config = $$.config;
  9733. return isFunction(config.point_select_r)
  9734. ? config.point_select_r(d)
  9735. : config.point_select_r
  9736. ? config.point_select_r
  9737. : $$.pointR(d) * 4;
  9738. };
  9739. ChartInternal.prototype.isWithinCircle = function (that, r) {
  9740. var d3 = this.d3, mouse = d3.mouse(that), d3_this = d3.select(that), cx = +d3_this.attr('cx'), cy = +d3_this.attr('cy');
  9741. return Math.sqrt(Math.pow(cx - mouse[0], 2) + Math.pow(cy - mouse[1], 2)) < r;
  9742. };
  9743. ChartInternal.prototype.isWithinStep = function (that, y) {
  9744. return Math.abs(y - this.d3.mouse(that)[1]) < 30;
  9745. };
  9746. ChartInternal.prototype.getCurrentWidth = function () {
  9747. var $$ = this, config = $$.config;
  9748. return config.size_width ? config.size_width : $$.getParentWidth();
  9749. };
  9750. ChartInternal.prototype.getCurrentHeight = function () {
  9751. var $$ = this, config = $$.config, h = config.size_height ? config.size_height : $$.getParentHeight();
  9752. return h > 0
  9753. ? h
  9754. : 320 / ($$.hasType('gauge') && !config.gauge_fullCircle ? 2 : 1);
  9755. };
  9756. ChartInternal.prototype.getCurrentPaddingTop = function () {
  9757. var $$ = this, config = $$.config, padding = isValue(config.padding_top) ? config.padding_top : 0;
  9758. if ($$.title && $$.title.node()) {
  9759. padding += $$.getTitlePadding();
  9760. }
  9761. return padding;
  9762. };
  9763. ChartInternal.prototype.getCurrentPaddingBottom = function () {
  9764. var config = this.config;
  9765. return isValue(config.padding_bottom) ? config.padding_bottom : 0;
  9766. };
  9767. ChartInternal.prototype.getCurrentPaddingLeft = function (withoutRecompute) {
  9768. var $$ = this, config = $$.config;
  9769. if (isValue(config.padding_left)) {
  9770. return config.padding_left;
  9771. }
  9772. else if (config.axis_rotated) {
  9773. return !config.axis_x_show || config.axis_x_inner
  9774. ? 1
  9775. : Math.max(ceil10($$.getAxisWidthByAxisId('x', withoutRecompute)), 40);
  9776. }
  9777. else if (!config.axis_y_show || config.axis_y_inner) {
  9778. // && !config.axis_rotated
  9779. return $$.axis.getYAxisLabelPosition().isOuter ? 30 : 1;
  9780. }
  9781. else {
  9782. return ceil10($$.getAxisWidthByAxisId('y', withoutRecompute));
  9783. }
  9784. };
  9785. ChartInternal.prototype.getCurrentPaddingRight = function () {
  9786. var $$ = this, config = $$.config, padding = 0, defaultPadding = 10, legendWidthOnRight = $$.isLegendRight ? $$.getLegendWidth() + 20 : 0;
  9787. if (isValue(config.padding_right)) {
  9788. padding = config.padding_right + 1; // 1 is needed not to hide tick line
  9789. }
  9790. else if (config.axis_rotated) {
  9791. padding = defaultPadding + legendWidthOnRight;
  9792. }
  9793. else if (!config.axis_y2_show || config.axis_y2_inner) {
  9794. // && !config.axis_rotated
  9795. padding =
  9796. 2 +
  9797. legendWidthOnRight +
  9798. ($$.axis.getY2AxisLabelPosition().isOuter ? 20 : 0);
  9799. }
  9800. else {
  9801. padding = ceil10($$.getAxisWidthByAxisId('y2')) + legendWidthOnRight;
  9802. }
  9803. if ($$.colorScale && $$.colorScale.node()) {
  9804. padding += $$.getColorScalePadding();
  9805. }
  9806. return padding;
  9807. };
  9808. ChartInternal.prototype.getParentRectValue = function (key) {
  9809. var parent = this.selectChart.node(), v;
  9810. while (parent && parent.tagName !== 'BODY') {
  9811. try {
  9812. v = parent.getBoundingClientRect()[key];
  9813. }
  9814. catch (e) {
  9815. if (key === 'width') {
  9816. // In IE in certain cases getBoundingClientRect
  9817. // will cause an "unspecified error"
  9818. v = parent.offsetWidth;
  9819. }
  9820. }
  9821. if (v) {
  9822. break;
  9823. }
  9824. parent = parent.parentNode;
  9825. }
  9826. return v;
  9827. };
  9828. ChartInternal.prototype.getParentWidth = function () {
  9829. return this.getParentRectValue('width');
  9830. };
  9831. ChartInternal.prototype.getParentHeight = function () {
  9832. var h = this.selectChart.style('height');
  9833. return h.indexOf('px') > 0 ? +h.replace('px', '') : 0;
  9834. };
  9835. ChartInternal.prototype.getSvgLeft = function (withoutRecompute) {
  9836. var $$ = this, config = $$.config, hasLeftAxisRect = config.axis_rotated || (!config.axis_rotated && !config.axis_y_inner), leftAxisClass = config.axis_rotated ? CLASS.axisX : CLASS.axisY, leftAxis = $$.main.select('.' + leftAxisClass).node(), svgRect = leftAxis && hasLeftAxisRect
  9837. ? leftAxis.getBoundingClientRect()
  9838. : { right: 0 }, chartRect = $$.selectChart.node().getBoundingClientRect(), hasArc = $$.hasArcType(), svgLeft = svgRect.right -
  9839. chartRect.left -
  9840. (hasArc ? 0 : $$.getCurrentPaddingLeft(withoutRecompute));
  9841. return svgLeft > 0 ? svgLeft : 0;
  9842. };
  9843. ChartInternal.prototype.getAxisWidthByAxisId = function (id, withoutRecompute) {
  9844. var $$ = this, position = $$.axis.getLabelPositionById(id);
  9845. return ($$.axis.getMaxTickWidth(id, withoutRecompute) + (position.isInner ? 20 : 40));
  9846. };
  9847. ChartInternal.prototype.getHorizontalAxisHeight = function (axisId, isSubchart) {
  9848. var $$ = this, config = $$.config, h = 30;
  9849. if (axisId === 'x' && !(isDefined(isSubchart) && isSubchart ? config.subchart_axis_x_show : config.axis_x_show)) {
  9850. return 8;
  9851. }
  9852. if (axisId === 'x' && config.axis_x_height) {
  9853. return config.axis_x_height;
  9854. }
  9855. if (axisId === 'y' && !config.axis_y_show) {
  9856. return config.legend_show && !$$.isLegendRight && !$$.isLegendInset ? 10 : 1;
  9857. }
  9858. if (axisId === 'y2' && !config.axis_y2_show) {
  9859. return $$.rotated_padding_top;
  9860. }
  9861. // Calculate x axis height when tick rotated
  9862. if (axisId === 'x' && !config.axis_rotated && config.axis_x_tick_rotate) {
  9863. h =
  9864. 30 +
  9865. $$.axis.getMaxTickWidth(axisId) *
  9866. Math.cos((Math.PI * (90 - Math.abs(config.axis_x_tick_rotate))) / 180);
  9867. }
  9868. // Calculate y axis height when tick rotated
  9869. if (axisId === 'y' && config.axis_rotated && config.axis_y_tick_rotate) {
  9870. h =
  9871. 30 +
  9872. $$.axis.getMaxTickWidth(axisId) *
  9873. Math.cos((Math.PI * (90 - Math.abs(config.axis_y_tick_rotate))) / 180);
  9874. }
  9875. return (h +
  9876. ($$.axis.getLabelPositionById(axisId).isInner ? 0 : 10) +
  9877. (axisId === 'y2' ? -10 : 0));
  9878. };
  9879. ChartInternal.prototype.initBrush = function (scale) {
  9880. var $$ = this, d3 = $$.d3;
  9881. // TODO: dynamically change brushY/brushX according to axis_rotated.
  9882. $$.brush = ($$.config.axis_rotated ? d3.brushY() : d3.brushX())
  9883. .on('brush', function () {
  9884. var event = d3.event.sourceEvent;
  9885. if (event && event.type === 'zoom') {
  9886. return;
  9887. }
  9888. $$.redrawForBrush();
  9889. })
  9890. .on('end', function () {
  9891. var event = d3.event.sourceEvent;
  9892. if (event && event.type === 'zoom') {
  9893. return;
  9894. }
  9895. if ($$.brush.empty() && event && event.type !== 'end') {
  9896. $$.brush.clear();
  9897. }
  9898. });
  9899. $$.brush.updateExtent = function () {
  9900. var range = this.scale.range(), extent;
  9901. if ($$.config.axis_rotated) {
  9902. extent = [
  9903. [0, range[0]],
  9904. [$$.width2, range[1]]
  9905. ];
  9906. }
  9907. else {
  9908. extent = [
  9909. [range[0], 0],
  9910. [range[1], $$.height2]
  9911. ];
  9912. }
  9913. this.extent(extent);
  9914. return this;
  9915. };
  9916. $$.brush.updateScale = function (scale) {
  9917. this.scale = scale;
  9918. return this;
  9919. };
  9920. $$.brush.update = function (scale) {
  9921. this.updateScale(scale || $$.subX).updateExtent();
  9922. $$.context.select('.' + CLASS.brush).call(this);
  9923. };
  9924. $$.brush.clear = function () {
  9925. $$.context.select('.' + CLASS.brush).call($$.brush.move, null);
  9926. };
  9927. $$.brush.selection = function () {
  9928. return d3.brushSelection($$.context.select('.' + CLASS.brush).node());
  9929. };
  9930. $$.brush.selectionAsValue = function (selectionAsValue, withTransition) {
  9931. var selection, brush;
  9932. if (selectionAsValue) {
  9933. if ($$.context) {
  9934. selection = [
  9935. this.scale(selectionAsValue[0]),
  9936. this.scale(selectionAsValue[1])
  9937. ];
  9938. brush = $$.context.select('.' + CLASS.brush);
  9939. if (withTransition) {
  9940. brush = brush.transition();
  9941. }
  9942. $$.brush.move(brush, selection);
  9943. }
  9944. return [];
  9945. }
  9946. selection = $$.brush.selection() || [0, 0];
  9947. return [this.scale.invert(selection[0]), this.scale.invert(selection[1])];
  9948. };
  9949. $$.brush.empty = function () {
  9950. var selection = $$.brush.selection();
  9951. return !selection || selection[0] === selection[1];
  9952. };
  9953. return $$.brush.updateScale(scale);
  9954. };
  9955. ChartInternal.prototype.initSubchart = function () {
  9956. var $$ = this, config = $$.config, context = ($$.context = $$.svg
  9957. .append('g')
  9958. .attr('transform', $$.getTranslate('context')));
  9959. // set style
  9960. context.style('visibility', 'visible');
  9961. // Define g for chart area
  9962. context
  9963. .append('g')
  9964. .attr('clip-path', $$.clipPathForSubchart)
  9965. .attr('class', CLASS.chart);
  9966. // Define g for bar chart area
  9967. context
  9968. .select('.' + CLASS.chart)
  9969. .append('g')
  9970. .attr('class', CLASS.chartBars);
  9971. // Define g for line chart area
  9972. context
  9973. .select('.' + CLASS.chart)
  9974. .append('g')
  9975. .attr('class', CLASS.chartLines);
  9976. // Add extent rect for Brush
  9977. context
  9978. .append('g')
  9979. .attr('clip-path', $$.clipPath)
  9980. .attr('class', CLASS.brush);
  9981. // ATTENTION: This must be called AFTER chart added
  9982. // Add Axis
  9983. $$.axes.subx = context
  9984. .append('g')
  9985. .attr('class', CLASS.axisX)
  9986. .attr('transform', $$.getTranslate('subx'))
  9987. .attr('clip-path', config.axis_rotated ? '' : $$.clipPathForXAxis)
  9988. .style('visibility', config.subchart_axis_x_show ? 'visible' : 'hidden');
  9989. };
  9990. ChartInternal.prototype.initSubchartBrush = function () {
  9991. var $$ = this;
  9992. // Add extent rect for Brush
  9993. $$.initBrush($$.subX).updateExtent();
  9994. $$.context.select('.' + CLASS.brush).call($$.brush);
  9995. };
  9996. ChartInternal.prototype.updateTargetsForSubchart = function (targets) {
  9997. var $$ = this, context = $$.context, config = $$.config, contextLineEnter, contextLine, contextBarEnter, contextBar, classChartBar = $$.classChartBar.bind($$), classBars = $$.classBars.bind($$), classChartLine = $$.classChartLine.bind($$), classLines = $$.classLines.bind($$), classAreas = $$.classAreas.bind($$);
  9998. //-- Bar --//
  9999. contextBar = context
  10000. .select('.' + CLASS.chartBars)
  10001. .selectAll('.' + CLASS.chartBar)
  10002. .data(targets);
  10003. contextBarEnter = contextBar
  10004. .enter()
  10005. .append('g')
  10006. .style('opacity', 0);
  10007. contextBarEnter.merge(contextBar).attr('class', classChartBar);
  10008. // Bars for each data
  10009. contextBarEnter.append('g').attr('class', classBars);
  10010. //-- Line --//
  10011. contextLine = context
  10012. .select('.' + CLASS.chartLines)
  10013. .selectAll('.' + CLASS.chartLine)
  10014. .data(targets);
  10015. contextLineEnter = contextLine
  10016. .enter()
  10017. .append('g')
  10018. .style('opacity', 0);
  10019. contextLineEnter.merge(contextLine).attr('class', classChartLine);
  10020. // Lines for each data
  10021. contextLineEnter.append('g').attr('class', classLines);
  10022. // Area
  10023. contextLineEnter.append('g').attr('class', classAreas);
  10024. //-- Brush --//
  10025. context
  10026. .selectAll('.' + CLASS.brush + ' rect')
  10027. .attr(config.axis_rotated ? 'width' : 'height', config.axis_rotated ? $$.width2 : $$.height2);
  10028. };
  10029. ChartInternal.prototype.updateBarForSubchart = function (durationForExit) {
  10030. var $$ = this;
  10031. var contextBar = $$.context
  10032. .selectAll('.' + CLASS.bars)
  10033. .selectAll('.' + CLASS.bar)
  10034. .data($$.barData.bind($$));
  10035. var contextBarEnter = contextBar
  10036. .enter()
  10037. .append('path')
  10038. .attr('class', $$.classBar.bind($$))
  10039. .style('stroke', 'none')
  10040. .style('fill', $$.color);
  10041. contextBar
  10042. .exit()
  10043. .transition()
  10044. .duration(durationForExit)
  10045. .style('opacity', 0)
  10046. .remove();
  10047. $$.contextBar = contextBarEnter
  10048. .merge(contextBar)
  10049. .style('opacity', $$.initialOpacity.bind($$));
  10050. };
  10051. ChartInternal.prototype.redrawBarForSubchart = function (drawBarOnSub, withTransition, duration) {
  10052. (withTransition
  10053. ? this.contextBar.transition(Math.random().toString()).duration(duration)
  10054. : this.contextBar)
  10055. .attr('d', drawBarOnSub)
  10056. .style('opacity', 1);
  10057. };
  10058. ChartInternal.prototype.updateLineForSubchart = function (durationForExit) {
  10059. var $$ = this;
  10060. var contextLine = $$.context
  10061. .selectAll('.' + CLASS.lines)
  10062. .selectAll('.' + CLASS.line)
  10063. .data($$.lineData.bind($$));
  10064. var contextLineEnter = contextLine
  10065. .enter()
  10066. .append('path')
  10067. .attr('class', $$.classLine.bind($$))
  10068. .style('stroke', $$.color);
  10069. contextLine
  10070. .exit()
  10071. .transition()
  10072. .duration(durationForExit)
  10073. .style('opacity', 0)
  10074. .remove();
  10075. $$.contextLine = contextLineEnter
  10076. .merge(contextLine)
  10077. .style('opacity', $$.initialOpacity.bind($$));
  10078. };
  10079. ChartInternal.prototype.redrawLineForSubchart = function (drawLineOnSub, withTransition, duration) {
  10080. (withTransition
  10081. ? this.contextLine.transition(Math.random().toString()).duration(duration)
  10082. : this.contextLine)
  10083. .attr('d', drawLineOnSub)
  10084. .style('opacity', 1);
  10085. };
  10086. ChartInternal.prototype.updateAreaForSubchart = function (durationForExit) {
  10087. var $$ = this, d3 = $$.d3;
  10088. var contextArea = $$.context
  10089. .selectAll('.' + CLASS.areas)
  10090. .selectAll('.' + CLASS.area)
  10091. .data($$.lineData.bind($$));
  10092. var contextAreaEnter = contextArea
  10093. .enter()
  10094. .append('path')
  10095. .attr('class', $$.classArea.bind($$))
  10096. .style('fill', $$.color)
  10097. .style('opacity', function () {
  10098. $$.orgAreaOpacity = +d3.select(this).style('opacity');
  10099. return 0;
  10100. });
  10101. contextArea
  10102. .exit()
  10103. .transition()
  10104. .duration(durationForExit)
  10105. .style('opacity', 0)
  10106. .remove();
  10107. $$.contextArea = contextAreaEnter.merge(contextArea).style('opacity', 0);
  10108. };
  10109. ChartInternal.prototype.redrawAreaForSubchart = function (drawAreaOnSub, withTransition, duration) {
  10110. (withTransition
  10111. ? this.contextArea.transition(Math.random().toString()).duration(duration)
  10112. : this.contextArea)
  10113. .attr('d', drawAreaOnSub)
  10114. .style('fill', this.color)
  10115. .style('opacity', this.orgAreaOpacity);
  10116. };
  10117. ChartInternal.prototype.redrawSubchart = function (withSubchart, transitions, duration, durationForExit, areaIndices, barIndices, lineIndices) {
  10118. var $$ = this, d3 = $$.d3, drawAreaOnSub, drawBarOnSub, drawLineOnSub;
  10119. // reflect main chart to extent on subchart if zoomed
  10120. if (d3.event && d3.event.type === 'zoom') {
  10121. $$.brush.selectionAsValue($$.x.orgDomain());
  10122. }
  10123. // update subchart elements if needed
  10124. if (withSubchart) {
  10125. // extent rect
  10126. if (!$$.brush.empty()) {
  10127. $$.brush.selectionAsValue($$.x.orgDomain());
  10128. }
  10129. // setup drawer - MEMO: this must be called after axis updated
  10130. drawAreaOnSub = $$.generateDrawArea(areaIndices, true);
  10131. drawBarOnSub = $$.generateDrawBar(barIndices, true);
  10132. drawLineOnSub = $$.generateDrawLine(lineIndices, true);
  10133. $$.updateBarForSubchart(duration);
  10134. $$.updateLineForSubchart(duration);
  10135. $$.updateAreaForSubchart(duration);
  10136. $$.redrawBarForSubchart(drawBarOnSub, duration, duration);
  10137. $$.redrawLineForSubchart(drawLineOnSub, duration, duration);
  10138. $$.redrawAreaForSubchart(drawAreaOnSub, duration, duration);
  10139. }
  10140. };
  10141. ChartInternal.prototype.redrawForBrush = function () {
  10142. var $$ = this, x = $$.x, d3 = $$.d3, s;
  10143. $$.redraw({
  10144. withTransition: false,
  10145. withY: $$.config.zoom_rescale,
  10146. withSubchart: false,
  10147. withUpdateXDomain: true,
  10148. withEventRect: false,
  10149. withDimension: false
  10150. });
  10151. // update zoom transation binded to event rect
  10152. s = d3.event.selection || $$.brush.scale.range();
  10153. $$.main
  10154. .select('.' + CLASS.eventRect)
  10155. .call($$.zoom.transform, d3.zoomIdentity.scale($$.width / (s[1] - s[0])).translate(-s[0], 0));
  10156. $$.config.subchart_onbrush.call($$.api, x.orgDomain());
  10157. };
  10158. ChartInternal.prototype.transformContext = function (withTransition, transitions) {
  10159. var $$ = this, subXAxis;
  10160. if (transitions && transitions.axisSubX) {
  10161. subXAxis = transitions.axisSubX;
  10162. }
  10163. else {
  10164. subXAxis = $$.context.select('.' + CLASS.axisX);
  10165. if (withTransition) {
  10166. subXAxis = subXAxis.transition();
  10167. }
  10168. }
  10169. $$.context.attr('transform', $$.getTranslate('context'));
  10170. subXAxis.attr('transform', $$.getTranslate('subx'));
  10171. };
  10172. ChartInternal.prototype.getDefaultSelection = function () {
  10173. var $$ = this, config = $$.config, selection = isFunction(config.axis_x_selection)
  10174. ? config.axis_x_selection($$.getXDomain($$.data.targets))
  10175. : config.axis_x_selection;
  10176. if ($$.isTimeSeries()) {
  10177. selection = [$$.parseDate(selection[0]), $$.parseDate(selection[1])];
  10178. }
  10179. return selection;
  10180. };
  10181. ChartInternal.prototype.removeSubchart = function () {
  10182. var $$ = this;
  10183. $$.brush = null;
  10184. $$.context.remove();
  10185. $$.context = null;
  10186. };
  10187. ChartInternal.prototype.initText = function () {
  10188. var $$ = this;
  10189. $$.main
  10190. .select('.' + CLASS.chart)
  10191. .append('g')
  10192. .attr('class', CLASS.chartTexts);
  10193. $$.mainText = $$.d3.selectAll([]);
  10194. };
  10195. ChartInternal.prototype.updateTargetsForText = function (targets) {
  10196. var $$ = this, classChartText = $$.classChartText.bind($$), classTexts = $$.classTexts.bind($$), classFocus = $$.classFocus.bind($$);
  10197. var mainText = $$.main
  10198. .select('.' + CLASS.chartTexts)
  10199. .selectAll('.' + CLASS.chartText)
  10200. .data(targets);
  10201. var mainTextEnter = mainText
  10202. .enter()
  10203. .append('g')
  10204. .attr('class', classChartText)
  10205. .style('opacity', 0)
  10206. .style('pointer-events', 'none');
  10207. mainTextEnter.append('g').attr('class', classTexts);
  10208. mainTextEnter.merge(mainText).attr('class', function (d) {
  10209. return classChartText(d) + classFocus(d);
  10210. });
  10211. };
  10212. ChartInternal.prototype.updateText = function (xForText, yForText, durationForExit) {
  10213. var $$ = this, config = $$.config, barOrLineData = $$.barOrLineData.bind($$), classText = $$.classText.bind($$);
  10214. var mainText = $$.main
  10215. .selectAll('.' + CLASS.texts)
  10216. .selectAll('.' + CLASS.text)
  10217. .data(barOrLineData);
  10218. var mainTextEnter = mainText
  10219. .enter()
  10220. .append('text')
  10221. .attr('class', classText)
  10222. .attr('text-anchor', function (d) {
  10223. return config.axis_rotated ? (d.value < 0 ? 'end' : 'start') : 'middle';
  10224. })
  10225. .style('stroke', 'none')
  10226. .attr('x', xForText)
  10227. .attr('y', yForText)
  10228. .style('fill', function (d) {
  10229. return $$.color(d);
  10230. })
  10231. .style('fill-opacity', 0);
  10232. $$.mainText = mainTextEnter.merge(mainText).text(function (d, i, j) {
  10233. return $$.dataLabelFormat(d.id)(d.value, d.id, i, j);
  10234. });
  10235. mainText
  10236. .exit()
  10237. .transition()
  10238. .duration(durationForExit)
  10239. .style('fill-opacity', 0)
  10240. .remove();
  10241. };
  10242. ChartInternal.prototype.redrawText = function (xForText, yForText, forFlow, withTransition, transition) {
  10243. return [
  10244. (withTransition ? this.mainText.transition(transition) : this.mainText)
  10245. .attr('x', xForText)
  10246. .attr('y', yForText)
  10247. .style('fill', this.color)
  10248. .style('fill-opacity', forFlow ? 0 : this.opacityForText.bind(this))
  10249. ];
  10250. };
  10251. ChartInternal.prototype.getTextRect = function (text, cls, element) {
  10252. var dummy = this.d3
  10253. .select('body')
  10254. .append('div')
  10255. .classed('c3', true), svg = dummy
  10256. .append('svg')
  10257. .style('visibility', 'hidden')
  10258. .style('position', 'fixed')
  10259. .style('top', 0)
  10260. .style('left', 0), font = this.d3.select(element).style('font'), rect;
  10261. svg
  10262. .selectAll('.dummy')
  10263. .data([text])
  10264. .enter()
  10265. .append('text')
  10266. .classed(cls ? cls : '', true)
  10267. .style('font', font)
  10268. .text(text)
  10269. .each(function () {
  10270. rect = getBBox(this);
  10271. });
  10272. dummy.remove();
  10273. return rect;
  10274. };
  10275. ChartInternal.prototype.generateXYForText = function (areaIndices, barIndices, lineIndices, forX) {
  10276. var $$ = this, getAreaPoints = $$.generateGetAreaPoints(areaIndices, false), getBarPoints = $$.generateGetBarPoints(barIndices, false), getLinePoints = $$.generateGetLinePoints(lineIndices, false), getter = forX ? $$.getXForText : $$.getYForText;
  10277. return function (d, i) {
  10278. var getPoints = $$.isAreaType(d)
  10279. ? getAreaPoints
  10280. : $$.isBarType(d)
  10281. ? getBarPoints
  10282. : getLinePoints;
  10283. return getter.call($$, getPoints(d, i), d, this);
  10284. };
  10285. };
  10286. ChartInternal.prototype.getXForText = function (points, d, textElement) {
  10287. var $$ = this, box = getBBox(textElement), xPos, padding;
  10288. if ($$.config.axis_rotated) {
  10289. padding = $$.isBarType(d) ? 4 : 6;
  10290. xPos = points[2][1] + padding * (d.value < 0 ? -1 : 1);
  10291. }
  10292. else {
  10293. xPos = $$.hasType('bar') ? (points[2][0] + points[0][0]) / 2 : points[0][0];
  10294. }
  10295. // show labels regardless of the domain if value is null
  10296. if (d.value === null) {
  10297. if (xPos > $$.width) {
  10298. xPos = $$.width - box.width;
  10299. }
  10300. else if (xPos < 0) {
  10301. xPos = 4;
  10302. }
  10303. }
  10304. return xPos;
  10305. };
  10306. ChartInternal.prototype.getYForText = function (points, d, textElement) {
  10307. var $$ = this, box = getBBox(textElement), yPos;
  10308. if ($$.config.axis_rotated) {
  10309. yPos = (points[0][0] + points[2][0] + box.height * 0.6) / 2;
  10310. }
  10311. else {
  10312. yPos = points[2][1];
  10313. if (d.value < 0 || (d.value === 0 && !$$.hasPositiveValue)) {
  10314. yPos += box.height;
  10315. if ($$.isBarType(d) && $$.isSafari()) {
  10316. yPos -= 3;
  10317. }
  10318. else if (!$$.isBarType(d) && $$.isChrome()) {
  10319. yPos += 3;
  10320. }
  10321. }
  10322. else {
  10323. yPos += $$.isBarType(d) ? -3 : -6;
  10324. }
  10325. }
  10326. // show labels regardless of the domain if value is null
  10327. if (d.value === null && !$$.config.axis_rotated) {
  10328. if (yPos < box.height) {
  10329. yPos = box.height;
  10330. }
  10331. else if (yPos > this.height) {
  10332. yPos = this.height - 4;
  10333. }
  10334. }
  10335. return yPos;
  10336. };
  10337. ChartInternal.prototype.initTitle = function () {
  10338. var $$ = this;
  10339. $$.title = $$.svg
  10340. .append('text')
  10341. .text($$.config.title_text)
  10342. .attr('class', $$.CLASS.title);
  10343. };
  10344. ChartInternal.prototype.redrawTitle = function () {
  10345. var $$ = this;
  10346. $$.title.attr('x', $$.xForTitle.bind($$)).attr('y', $$.yForTitle.bind($$));
  10347. };
  10348. ChartInternal.prototype.xForTitle = function () {
  10349. var $$ = this, config = $$.config, position = config.title_position || 'left', x;
  10350. if (position.indexOf('right') >= 0) {
  10351. x =
  10352. $$.currentWidth -
  10353. $$.getTextRect($$.title.node().textContent, $$.CLASS.title, $$.title.node()).width -
  10354. config.title_padding.right;
  10355. }
  10356. else if (position.indexOf('center') >= 0) {
  10357. x = Math.max(($$.currentWidth -
  10358. $$.getTextRect($$.title.node().textContent, $$.CLASS.title, $$.title.node()).width) /
  10359. 2, 0);
  10360. }
  10361. else {
  10362. // left
  10363. x = config.title_padding.left;
  10364. }
  10365. return x;
  10366. };
  10367. ChartInternal.prototype.yForTitle = function () {
  10368. var $$ = this;
  10369. return ($$.config.title_padding.top +
  10370. $$.getTextRect($$.title.node().textContent, $$.CLASS.title, $$.title.node())
  10371. .height);
  10372. };
  10373. ChartInternal.prototype.getTitlePadding = function () {
  10374. var $$ = this;
  10375. return $$.yForTitle() + $$.config.title_padding.bottom;
  10376. };
  10377. function powerOfTen(d) {
  10378. return d / Math.pow(10, Math.ceil(Math.log(d) / Math.LN10 - 1e-12)) === 1;
  10379. }
  10380. ChartInternal.prototype.drawColorScale = function () {
  10381. var $$ = this, d3 = $$.d3, config = $$.config, target = $$.data.targets[0], barWidth, barHeight, axis, points, legendAxis, axisScale, inverseScale, height;
  10382. barWidth = !isNaN(config.stanford_scaleWidth)
  10383. ? config.stanford_scaleWidth
  10384. : 20;
  10385. barHeight = 5;
  10386. if (barHeight < 0 || barWidth < 0) {
  10387. throw Error("Colorscale's barheight and barwidth must be greater than 0.");
  10388. }
  10389. height =
  10390. $$.height - config.stanford_padding.bottom - config.stanford_padding.top;
  10391. points = d3.range(config.stanford_padding.bottom, height, barHeight);
  10392. inverseScale = d3
  10393. .scaleSequential(target.colors)
  10394. .domain([points[points.length - 1], points[0]]);
  10395. if ($$.colorScale) {
  10396. $$.colorScale.remove();
  10397. }
  10398. $$.colorScale = $$.svg
  10399. .append('g')
  10400. .attr('width', 50)
  10401. .attr('height', height)
  10402. .attr('class', CLASS.colorScale);
  10403. $$.colorScale
  10404. .append('g')
  10405. .attr('transform', "translate(0, " + config.stanford_padding.top + ")")
  10406. .selectAll('bars')
  10407. .data(points)
  10408. .enter()
  10409. .append('rect')
  10410. .attr('y', function (d, i) { return i * barHeight; })
  10411. .attr('x', 0)
  10412. .attr('width', barWidth)
  10413. .attr('height', barHeight)
  10414. .attr('fill', function (d) {
  10415. return inverseScale(d);
  10416. });
  10417. // Legend Axis
  10418. axisScale = d3
  10419. .scaleLog()
  10420. .domain([target.minEpochs, target.maxEpochs])
  10421. .range([
  10422. points[0] +
  10423. config.stanford_padding.top +
  10424. points[points.length - 1] +
  10425. barHeight -
  10426. 1,
  10427. points[0] + config.stanford_padding.top
  10428. ]);
  10429. legendAxis = d3.axisRight(axisScale);
  10430. if (config.stanford_scaleFormat === 'pow10') {
  10431. legendAxis.tickValues([1, 10, 100, 1000, 10000, 100000, 1000000, 10000000]);
  10432. }
  10433. else if (isFunction(config.stanford_scaleFormat)) {
  10434. legendAxis.tickFormat(config.stanford_scaleFormat);
  10435. }
  10436. else {
  10437. legendAxis.tickFormat(d3.format('d'));
  10438. }
  10439. if (isFunction(config.stanford_scaleValues)) {
  10440. legendAxis.tickValues(config.stanford_scaleValues(target.minEpochs, target.maxEpochs));
  10441. }
  10442. // Draw Axis
  10443. axis = $$.colorScale
  10444. .append('g')
  10445. .attr('class', 'legend axis')
  10446. .attr('transform', "translate(" + barWidth + ",0)")
  10447. .call(legendAxis);
  10448. if (config.stanford_scaleFormat === 'pow10') {
  10449. axis
  10450. .selectAll('.tick text')
  10451. .text(null)
  10452. .filter(powerOfTen)
  10453. .text(10)
  10454. .append('tspan')
  10455. .attr('dy', '-.7em') // https://bl.ocks.org/mbostock/6738229
  10456. .text(function (d) {
  10457. return Math.round(Math.log(d) / Math.LN10);
  10458. });
  10459. }
  10460. $$.colorScale.attr('transform', "translate(" + ($$.currentWidth - $$.xForColorScale()) + ", 0)");
  10461. };
  10462. ChartInternal.prototype.xForColorScale = function () {
  10463. var $$ = this;
  10464. return $$.config.stanford_padding.right + getBBox($$.colorScale.node()).width;
  10465. };
  10466. ChartInternal.prototype.getColorScalePadding = function () {
  10467. var $$ = this;
  10468. return $$.xForColorScale() + $$.config.stanford_padding.left + 20;
  10469. };
  10470. ChartInternal.prototype.isStanfordGraphType = function () {
  10471. var $$ = this;
  10472. return $$.config.data_type === 'stanford';
  10473. };
  10474. ChartInternal.prototype.initStanfordData = function () {
  10475. var $$ = this, d3 = $$.d3, config = $$.config, target = $$.data.targets[0], epochs, maxEpochs, minEpochs;
  10476. // Make larger values appear on top
  10477. target.values.sort(compareEpochs);
  10478. // Get array of epochs
  10479. epochs = target.values.map(function (a) { return a.epochs; });
  10480. minEpochs = !isNaN(config.stanford_scaleMin)
  10481. ? config.stanford_scaleMin
  10482. : d3.min(epochs);
  10483. maxEpochs = !isNaN(config.stanford_scaleMax)
  10484. ? config.stanford_scaleMax
  10485. : d3.max(epochs);
  10486. if (minEpochs > maxEpochs) {
  10487. throw Error('Number of minEpochs has to be smaller than maxEpochs');
  10488. }
  10489. target.colors = isFunction(config.stanford_colors)
  10490. ? config.stanford_colors
  10491. : d3.interpolateHslLong(d3.hsl(250, 1, 0.5), d3.hsl(0, 1, 0.5));
  10492. target.colorscale = d3
  10493. .scaleSequentialLog(target.colors)
  10494. .domain([minEpochs, maxEpochs]);
  10495. target.minEpochs = minEpochs;
  10496. target.maxEpochs = maxEpochs;
  10497. };
  10498. ChartInternal.prototype.getStanfordPointColor = function (d) {
  10499. var $$ = this, target = $$.data.targets[0];
  10500. return target.colorscale(d.epochs);
  10501. };
  10502. // http://jsfiddle.net/Xotic750/KtzLq/
  10503. ChartInternal.prototype.getCentroid = function (points) {
  10504. var area = getRegionArea(points);
  10505. var x = 0, y = 0, i, j, f, point1, point2;
  10506. for (i = 0, j = points.length - 1; i < points.length; j = i, i += 1) {
  10507. point1 = points[i];
  10508. point2 = points[j];
  10509. f = point1.x * point2.y - point2.x * point1.y;
  10510. x += (point1.x + point2.x) * f;
  10511. y += (point1.y + point2.y) * f;
  10512. }
  10513. f = area * 6;
  10514. return {
  10515. x: x / f,
  10516. y: y / f
  10517. };
  10518. };
  10519. ChartInternal.prototype.getStanfordTooltipTitle = function (d) {
  10520. var $$ = this, labelX = $$.axis.getLabelText('x'), labelY = $$.axis.getLabelText('y');
  10521. return "\n <tr><th>" + (labelX ? sanitise(labelX) : 'x') + "</th><th class='value'>" + d.x + "</th></tr>\n <tr><th>" + (labelY ? sanitise(labelY) : 'y') + "</th><th class='value'>" + d.value + "</th></tr>\n ";
  10522. };
  10523. ChartInternal.prototype.countEpochsInRegion = function (region) {
  10524. var $$ = this, target = $$.data.targets[0], total, count;
  10525. total = target.values.reduce(function (accumulator, currentValue) { return accumulator + Number(currentValue.epochs); }, 0);
  10526. count = target.values.reduce(function (accumulator, currentValue) {
  10527. if (pointInRegion(currentValue, region)) {
  10528. return accumulator + Number(currentValue.epochs);
  10529. }
  10530. return accumulator;
  10531. }, 0);
  10532. return {
  10533. value: count,
  10534. percentage: count !== 0 ? ((count / total) * 100).toFixed(1) : 0
  10535. };
  10536. };
  10537. var getRegionArea = function (points) {
  10538. // thanks to: https://stackoverflow.com/questions/16282330/find-centerpoint-of-polygon-in-javascript
  10539. var area = 0, i, j, point1, point2;
  10540. for (i = 0, j = points.length - 1; i < points.length; j = i, i += 1) {
  10541. point1 = points[i];
  10542. point2 = points[j];
  10543. area += point1.x * point2.y;
  10544. area -= point1.y * point2.x;
  10545. }
  10546. area /= 2;
  10547. return area;
  10548. };
  10549. var pointInRegion = function (point, region) {
  10550. // thanks to: http://bl.ocks.org/bycoffe/5575904
  10551. // ray-casting algorithm based on
  10552. // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
  10553. var xi, yi, yj, xj, intersect, x = point.x, y = point.value, inside = false;
  10554. for (var i = 0, j = region.length - 1; i < region.length; j = i++) {
  10555. xi = region[i].x;
  10556. yi = region[i].y;
  10557. xj = region[j].x;
  10558. yj = region[j].y;
  10559. intersect = yi > y !== yj > y && x < ((xj - xi) * (y - yi)) / (yj - yi) + xi;
  10560. if (intersect) {
  10561. inside = !inside;
  10562. }
  10563. }
  10564. return inside;
  10565. };
  10566. var compareEpochs = function (a, b) {
  10567. if (a.epochs < b.epochs) {
  10568. return -1;
  10569. }
  10570. if (a.epochs > b.epochs) {
  10571. return 1;
  10572. }
  10573. return 0;
  10574. };
  10575. ChartInternal.prototype.initStanfordElements = function () {
  10576. var $$ = this;
  10577. // Avoid blocking eventRect
  10578. $$.stanfordElements = $$.main
  10579. .select('.' + CLASS.chart)
  10580. .append('g')
  10581. .attr('class', CLASS.stanfordElements);
  10582. $$.stanfordElements.append('g').attr('class', CLASS.stanfordLines);
  10583. $$.stanfordElements.append('g').attr('class', CLASS.stanfordTexts);
  10584. $$.stanfordElements.append('g').attr('class', CLASS.stanfordRegions);
  10585. };
  10586. ChartInternal.prototype.updateStanfordElements = function (duration) {
  10587. var $$ = this, main = $$.main, config = $$.config, stanfordLine, stanfordLineEnter, stanfordRegion, stanfordRegionEnter, stanfordText, stanfordTextEnter, xvCustom = $$.xvCustom.bind($$), yvCustom = $$.yvCustom.bind($$), countPointsInRegion = $$.countEpochsInRegion.bind($$);
  10588. // Stanford-Lines
  10589. stanfordLine = main
  10590. .select('.' + CLASS.stanfordLines)
  10591. .style('shape-rendering', 'geometricprecision')
  10592. .selectAll('.' + CLASS.stanfordLine)
  10593. .data(config.stanford_lines);
  10594. // enter
  10595. stanfordLineEnter = stanfordLine
  10596. .enter()
  10597. .append('g')
  10598. .attr('class', function (d) {
  10599. return CLASS.stanfordLine + (d['class'] ? ' ' + d['class'] : '');
  10600. });
  10601. stanfordLineEnter
  10602. .append('line')
  10603. .attr('x1', function (d) {
  10604. return config.axis_rotated ? yvCustom(d, 'value_y1') : xvCustom(d, 'value_x1');
  10605. })
  10606. .attr('x2', function (d) {
  10607. return config.axis_rotated ? yvCustom(d, 'value_y2') : xvCustom(d, 'value_x2');
  10608. })
  10609. .attr('y1', function (d) {
  10610. return config.axis_rotated ? xvCustom(d, 'value_x1') : yvCustom(d, 'value_y1');
  10611. })
  10612. .attr('y2', function (d) {
  10613. return config.axis_rotated ? xvCustom(d, 'value_x2') : yvCustom(d, 'value_y2');
  10614. })
  10615. .style('opacity', 0);
  10616. // update
  10617. $$.stanfordLines = stanfordLineEnter.merge(stanfordLine);
  10618. $$.stanfordLines
  10619. .select('line')
  10620. .transition()
  10621. .duration(duration)
  10622. .attr('x1', function (d) {
  10623. return config.axis_rotated ? yvCustom(d, 'value_y1') : xvCustom(d, 'value_x1');
  10624. })
  10625. .attr('x2', function (d) {
  10626. return config.axis_rotated ? yvCustom(d, 'value_y2') : xvCustom(d, 'value_x2');
  10627. })
  10628. .attr('y1', function (d) {
  10629. return config.axis_rotated ? xvCustom(d, 'value_x1') : yvCustom(d, 'value_y1');
  10630. })
  10631. .attr('y2', function (d) {
  10632. return config.axis_rotated ? xvCustom(d, 'value_x2') : yvCustom(d, 'value_y2');
  10633. })
  10634. .style('opacity', 1);
  10635. // exit
  10636. stanfordLine
  10637. .exit()
  10638. .transition()
  10639. .duration(duration)
  10640. .style('opacity', 0)
  10641. .remove();
  10642. // Stanford-Text
  10643. stanfordText = main
  10644. .select('.' + CLASS.stanfordTexts)
  10645. .selectAll('.' + CLASS.stanfordText)
  10646. .data(config.stanford_texts);
  10647. // enter
  10648. stanfordTextEnter = stanfordText
  10649. .enter()
  10650. .append('g')
  10651. .attr('class', function (d) {
  10652. return CLASS.stanfordText + (d['class'] ? ' ' + d['class'] : '');
  10653. });
  10654. stanfordTextEnter
  10655. .append('text')
  10656. .attr('x', function (d) { return (config.axis_rotated ? yvCustom(d, 'y') : xvCustom(d, 'x')); })
  10657. .attr('y', function (d) { return (config.axis_rotated ? xvCustom(d, 'x') : yvCustom(d, 'y')); })
  10658. .style('opacity', 0);
  10659. // update
  10660. $$.stanfordTexts = stanfordTextEnter.merge(stanfordText);
  10661. $$.stanfordTexts
  10662. .select('text')
  10663. .transition()
  10664. .duration(duration)
  10665. .attr('x', function (d) { return (config.axis_rotated ? yvCustom(d, 'y') : xvCustom(d, 'x')); })
  10666. .attr('y', function (d) { return (config.axis_rotated ? xvCustom(d, 'x') : yvCustom(d, 'y')); })
  10667. .text(function (d) {
  10668. return d.content;
  10669. })
  10670. .style('opacity', 1);
  10671. // exit
  10672. stanfordText
  10673. .exit()
  10674. .transition()
  10675. .duration(duration)
  10676. .style('opacity', 0)
  10677. .remove();
  10678. // Stanford-Regions
  10679. stanfordRegion = main
  10680. .select('.' + CLASS.stanfordRegions)
  10681. .selectAll('.' + CLASS.stanfordRegion)
  10682. .data(config.stanford_regions);
  10683. // enter
  10684. stanfordRegionEnter = stanfordRegion
  10685. .enter()
  10686. .append('g')
  10687. .attr('class', function (d) {
  10688. return CLASS.stanfordRegion + (d['class'] ? ' ' + d['class'] : '');
  10689. });
  10690. stanfordRegionEnter
  10691. .append('polygon')
  10692. .attr('points', function (d) {
  10693. return d.points
  10694. .map(function (value) {
  10695. return [
  10696. config.axis_rotated ? yvCustom(value, 'y') : xvCustom(value, 'x'),
  10697. config.axis_rotated ? xvCustom(value, 'x') : yvCustom(value, 'y')
  10698. ].join(',');
  10699. })
  10700. .join(' ');
  10701. })
  10702. .style('opacity', 0);
  10703. stanfordRegionEnter
  10704. .append('text')
  10705. .attr('x', function (d) { return $$.getCentroid(d.points).x; })
  10706. .attr('y', function (d) { return $$.getCentroid(d.points).y; })
  10707. .style('opacity', 0);
  10708. // update
  10709. $$.stanfordRegions = stanfordRegionEnter.merge(stanfordRegion);
  10710. $$.stanfordRegions
  10711. .select('polygon')
  10712. .transition()
  10713. .duration(duration)
  10714. .attr('points', function (d) {
  10715. return d.points
  10716. .map(function (value) {
  10717. return [
  10718. config.axis_rotated ? yvCustom(value, 'y') : xvCustom(value, 'x'),
  10719. config.axis_rotated ? xvCustom(value, 'x') : yvCustom(value, 'y')
  10720. ].join(',');
  10721. })
  10722. .join(' ');
  10723. })
  10724. .style('opacity', function (d) {
  10725. return d.opacity ? d.opacity : 0.2;
  10726. });
  10727. $$.stanfordRegions
  10728. .select('text')
  10729. .transition()
  10730. .duration(duration)
  10731. .attr('x', function (d) {
  10732. return config.axis_rotated
  10733. ? yvCustom($$.getCentroid(d.points), 'y')
  10734. : xvCustom($$.getCentroid(d.points), 'x');
  10735. })
  10736. .attr('y', function (d) {
  10737. return config.axis_rotated
  10738. ? xvCustom($$.getCentroid(d.points), 'x')
  10739. : yvCustom($$.getCentroid(d.points), 'y');
  10740. })
  10741. .text(function (d) {
  10742. if (d.text) {
  10743. var value, percentage, temp;
  10744. if ($$.isStanfordGraphType()) {
  10745. temp = countPointsInRegion(d.points);
  10746. value = temp.value;
  10747. percentage = temp.percentage;
  10748. }
  10749. return d.text(value, percentage);
  10750. }
  10751. return '';
  10752. })
  10753. .attr('text-anchor', 'middle')
  10754. .attr('dominant-baseline', 'middle')
  10755. .style('opacity', 1);
  10756. // exit
  10757. stanfordRegion
  10758. .exit()
  10759. .transition()
  10760. .duration(duration)
  10761. .style('opacity', 0)
  10762. .remove();
  10763. };
  10764. ChartInternal.prototype.initTooltip = function () {
  10765. var $$ = this, config = $$.config, i;
  10766. $$.tooltip = $$.selectChart
  10767. .style('position', 'relative')
  10768. .append('div')
  10769. .attr('class', CLASS.tooltipContainer)
  10770. .style('position', 'absolute')
  10771. .style('pointer-events', 'none')
  10772. .style('display', 'none');
  10773. // Show tooltip if needed
  10774. if (config.tooltip_init_show) {
  10775. if ($$.isTimeSeries() && isString(config.tooltip_init_x)) {
  10776. config.tooltip_init_x = $$.parseDate(config.tooltip_init_x);
  10777. for (i = 0; i < $$.data.targets[0].values.length; i++) {
  10778. if ($$.data.targets[0].values[i].x - config.tooltip_init_x === 0) {
  10779. break;
  10780. }
  10781. }
  10782. config.tooltip_init_x = i;
  10783. }
  10784. $$.tooltip.html(config.tooltip_contents.call($$, $$.data.targets.map(function (d) {
  10785. return $$.addName(d.values[config.tooltip_init_x]);
  10786. }), $$.axis.getXAxisTickFormat(), $$.getYFormat($$.hasArcType()), $$.color));
  10787. $$.tooltip
  10788. .style('top', config.tooltip_init_position.top)
  10789. .style('left', config.tooltip_init_position.left)
  10790. .style('display', 'block');
  10791. }
  10792. };
  10793. ChartInternal.prototype.getTooltipSortFunction = function () {
  10794. var $$ = this, config = $$.config;
  10795. if (config.data_groups.length === 0 || config.tooltip_order !== undefined) {
  10796. // if data are not grouped or if an order is specified
  10797. // for the tooltip values we sort them by their values
  10798. var order = config.tooltip_order;
  10799. if (order === undefined) {
  10800. order = config.data_order;
  10801. }
  10802. var valueOf = function (obj) {
  10803. return obj ? obj.value : null;
  10804. };
  10805. // if data are not grouped, we sort them by their value
  10806. if (isString(order) && order.toLowerCase() === 'asc') {
  10807. return function (a, b) {
  10808. return valueOf(a) - valueOf(b);
  10809. };
  10810. }
  10811. else if (isString(order) && order.toLowerCase() === 'desc') {
  10812. return function (a, b) {
  10813. return valueOf(b) - valueOf(a);
  10814. };
  10815. }
  10816. else if (isFunction(order)) {
  10817. // if the function is from data_order we need
  10818. // to wrap the returned function in order to format
  10819. // the sorted value to the expected format
  10820. var sortFunction = order;
  10821. if (config.tooltip_order === undefined) {
  10822. sortFunction = function (a, b) {
  10823. return order(a
  10824. ? {
  10825. id: a.id,
  10826. values: [a]
  10827. }
  10828. : null, b
  10829. ? {
  10830. id: b.id,
  10831. values: [b]
  10832. }
  10833. : null);
  10834. };
  10835. }
  10836. return sortFunction;
  10837. }
  10838. else if (isArray(order)) {
  10839. return function (a, b) {
  10840. return order.indexOf(a.id) - order.indexOf(b.id);
  10841. };
  10842. }
  10843. }
  10844. else {
  10845. // if data are grouped, we follow the order of grouped targets
  10846. var ids = $$.orderTargets($$.data.targets).map(function (i) {
  10847. return i.id;
  10848. });
  10849. // if it was either asc or desc we need to invert the order
  10850. // returned by orderTargets
  10851. if ($$.isOrderAsc() || $$.isOrderDesc()) {
  10852. ids = ids.reverse();
  10853. }
  10854. return function (a, b) {
  10855. return ids.indexOf(a.id) - ids.indexOf(b.id);
  10856. };
  10857. }
  10858. };
  10859. ChartInternal.prototype.getTooltipContent = function (d, defaultTitleFormat, defaultValueFormat, color) {
  10860. var $$ = this, config = $$.config, titleFormat = config.tooltip_format_title || defaultTitleFormat, nameFormat = config.tooltip_format_name ||
  10861. function (name) {
  10862. return name;
  10863. }, text, i, title, value, name, bgcolor;
  10864. var valueFormat = config.tooltip_format_value;
  10865. if (!valueFormat) {
  10866. valueFormat = $$.isTargetNormalized(d.id)
  10867. ? function (v, ratio) { return (ratio * 100).toFixed(2) + "%"; }
  10868. : defaultValueFormat;
  10869. }
  10870. var tooltipSortFunction = this.getTooltipSortFunction();
  10871. if (tooltipSortFunction) {
  10872. d.sort(tooltipSortFunction);
  10873. }
  10874. for (i = 0; i < d.length; i++) {
  10875. if (!(d[i] && (d[i].value || d[i].value === 0))) {
  10876. continue;
  10877. }
  10878. if ($$.isStanfordGraphType()) {
  10879. // Custom tooltip for stanford plots
  10880. if (!text) {
  10881. title = $$.getStanfordTooltipTitle(d[i]);
  10882. text = "<table class='" + $$.CLASS.tooltip + "'>" + title;
  10883. }
  10884. bgcolor = $$.getStanfordPointColor(d[i]);
  10885. name = sanitise(config.data_epochs); // Epochs key name
  10886. value = d[i].epochs;
  10887. }
  10888. else {
  10889. // Regular tooltip
  10890. if (!text) {
  10891. title = sanitise(titleFormat ? titleFormat(d[i].x, d[i].index) : d[i].x);
  10892. text =
  10893. "<table class='" +
  10894. $$.CLASS.tooltip +
  10895. "'>" +
  10896. (title || title === 0
  10897. ? "<tr><th colspan='2'>" + title + '</th></tr>'
  10898. : '');
  10899. }
  10900. value = sanitise(valueFormat(d[i].value, d[i].ratio, d[i].id, d[i].index, d));
  10901. if (value !== undefined) {
  10902. // Skip elements when their name is set to null
  10903. if (d[i].name === null) {
  10904. continue;
  10905. }
  10906. name = sanitise(nameFormat(d[i].name, d[i].ratio, d[i].id, d[i].index));
  10907. bgcolor = $$.levelColor ? $$.levelColor(d[i].value) : color(d[i].id);
  10908. }
  10909. }
  10910. if (value !== undefined) {
  10911. text +=
  10912. "<tr class='" +
  10913. $$.CLASS.tooltipName +
  10914. '-' +
  10915. $$.getTargetSelectorSuffix(d[i].id) +
  10916. "'>";
  10917. text +=
  10918. "<td class='name'><span style='background-color:" +
  10919. bgcolor +
  10920. "'></span>" +
  10921. name +
  10922. '</td>';
  10923. text += "<td class='value'>" + value + '</td>';
  10924. text += '</tr>';
  10925. }
  10926. }
  10927. return text + '</table>';
  10928. };
  10929. ChartInternal.prototype.tooltipPosition = function (dataToShow, tWidth, tHeight, element) {
  10930. var $$ = this, config = $$.config, d3 = $$.d3;
  10931. var svgLeft, tooltipLeft, tooltipRight, tooltipTop, chartRight;
  10932. var forArc = $$.hasArcType(), mouse = d3.mouse(element);
  10933. // Determin tooltip position
  10934. if (forArc) {
  10935. tooltipLeft =
  10936. ($$.width - ($$.isLegendRight ? $$.getLegendWidth() : 0)) / 2 + mouse[0];
  10937. tooltipTop =
  10938. ($$.hasType('gauge') ? $$.height : $$.height / 2) + mouse[1] + 20;
  10939. }
  10940. else {
  10941. svgLeft = $$.getSvgLeft(true);
  10942. if (config.axis_rotated) {
  10943. tooltipLeft = svgLeft + mouse[0] + 100;
  10944. tooltipRight = tooltipLeft + tWidth;
  10945. chartRight = $$.currentWidth - $$.getCurrentPaddingRight();
  10946. tooltipTop = $$.x(dataToShow[0].x) + 20;
  10947. }
  10948. else {
  10949. tooltipLeft =
  10950. svgLeft + $$.getCurrentPaddingLeft(true) + $$.x(dataToShow[0].x) + 20;
  10951. tooltipRight = tooltipLeft + tWidth;
  10952. chartRight = svgLeft + $$.currentWidth - $$.getCurrentPaddingRight();
  10953. tooltipTop = mouse[1] + 15;
  10954. }
  10955. if (tooltipRight > chartRight) {
  10956. // 20 is needed for Firefox to keep tooltip width
  10957. tooltipLeft -= tooltipRight - chartRight + 20;
  10958. }
  10959. if (tooltipTop + tHeight > $$.currentHeight) {
  10960. tooltipTop -= tHeight + 30;
  10961. }
  10962. }
  10963. if (tooltipTop < 0) {
  10964. tooltipTop = 0;
  10965. }
  10966. return {
  10967. top: tooltipTop,
  10968. left: tooltipLeft
  10969. };
  10970. };
  10971. ChartInternal.prototype.showTooltip = function (selectedData, element) {
  10972. var $$ = this, config = $$.config;
  10973. var tWidth, tHeight, position;
  10974. var forArc = $$.hasArcType(), dataToShow = selectedData.filter(function (d) {
  10975. return d && isValue(d.value);
  10976. }), positionFunction = config.tooltip_position || ChartInternal.prototype.tooltipPosition;
  10977. if (dataToShow.length === 0 || !config.tooltip_show) {
  10978. $$.hideTooltip();
  10979. return;
  10980. }
  10981. $$.tooltip
  10982. .html(config.tooltip_contents.call($$, selectedData, $$.axis.getXAxisTickFormat(), $$.getYFormat(forArc), $$.color))
  10983. .style('display', 'block');
  10984. // Get tooltip dimensions
  10985. tWidth = $$.tooltip.property('offsetWidth');
  10986. tHeight = $$.tooltip.property('offsetHeight');
  10987. position = positionFunction.call(this, dataToShow, tWidth, tHeight, element);
  10988. // Set tooltip
  10989. $$.tooltip
  10990. .style('top', position.top + 'px')
  10991. .style('left', position.left + 'px');
  10992. };
  10993. ChartInternal.prototype.hideTooltip = function () {
  10994. this.tooltip.style('display', 'none');
  10995. };
  10996. ChartInternal.prototype.setTargetType = function (targetIds, type) {
  10997. var $$ = this, config = $$.config;
  10998. $$.mapToTargetIds(targetIds).forEach(function (id) {
  10999. $$.withoutFadeIn[id] = type === config.data_types[id];
  11000. config.data_types[id] = type;
  11001. });
  11002. if (!targetIds) {
  11003. config.data_type = type;
  11004. }
  11005. };
  11006. ChartInternal.prototype.hasType = function (type, targets) {
  11007. var $$ = this, types = $$.config.data_types, has = false;
  11008. targets = targets || $$.data.targets;
  11009. if (targets && targets.length) {
  11010. targets.forEach(function (target) {
  11011. var t = types[target.id];
  11012. if ((t && t.indexOf(type) >= 0) || (!t && type === 'line')) {
  11013. has = true;
  11014. }
  11015. });
  11016. }
  11017. else if (Object.keys(types).length) {
  11018. Object.keys(types).forEach(function (id) {
  11019. if (types[id] === type) {
  11020. has = true;
  11021. }
  11022. });
  11023. }
  11024. else {
  11025. has = $$.config.data_type === type;
  11026. }
  11027. return has;
  11028. };
  11029. ChartInternal.prototype.hasArcType = function (targets) {
  11030. return (this.hasType('pie', targets) ||
  11031. this.hasType('donut', targets) ||
  11032. this.hasType('gauge', targets));
  11033. };
  11034. ChartInternal.prototype.isLineType = function (d) {
  11035. var config = this.config, id = isString(d) ? d : d.id;
  11036. return (!config.data_types[id] ||
  11037. ['line', 'spline', 'area', 'area-spline', 'step', 'area-step'].indexOf(config.data_types[id]) >= 0);
  11038. };
  11039. ChartInternal.prototype.isStepType = function (d) {
  11040. var id = isString(d) ? d : d.id;
  11041. return ['step', 'area-step'].indexOf(this.config.data_types[id]) >= 0;
  11042. };
  11043. ChartInternal.prototype.isSplineType = function (d) {
  11044. var id = isString(d) ? d : d.id;
  11045. return ['spline', 'area-spline'].indexOf(this.config.data_types[id]) >= 0;
  11046. };
  11047. ChartInternal.prototype.isAreaType = function (d) {
  11048. var id = isString(d) ? d : d.id;
  11049. return (['area', 'area-spline', 'area-step'].indexOf(this.config.data_types[id]) >=
  11050. 0);
  11051. };
  11052. ChartInternal.prototype.isBarType = function (d) {
  11053. var id = isString(d) ? d : d.id;
  11054. return this.config.data_types[id] === 'bar';
  11055. };
  11056. ChartInternal.prototype.isScatterType = function (d) {
  11057. var id = isString(d) ? d : d.id;
  11058. return this.config.data_types[id] === 'scatter';
  11059. };
  11060. ChartInternal.prototype.isStanfordType = function (d) {
  11061. var id = isString(d) ? d : d.id;
  11062. return this.config.data_types[id] === 'stanford';
  11063. };
  11064. ChartInternal.prototype.isPieType = function (d) {
  11065. var id = isString(d) ? d : d.id;
  11066. return this.config.data_types[id] === 'pie';
  11067. };
  11068. ChartInternal.prototype.isGaugeType = function (d) {
  11069. var id = isString(d) ? d : d.id;
  11070. return this.config.data_types[id] === 'gauge';
  11071. };
  11072. ChartInternal.prototype.isDonutType = function (d) {
  11073. var id = isString(d) ? d : d.id;
  11074. return this.config.data_types[id] === 'donut';
  11075. };
  11076. ChartInternal.prototype.isArcType = function (d) {
  11077. return this.isPieType(d) || this.isDonutType(d) || this.isGaugeType(d);
  11078. };
  11079. ChartInternal.prototype.lineData = function (d) {
  11080. return this.isLineType(d) ? [d] : [];
  11081. };
  11082. ChartInternal.prototype.arcData = function (d) {
  11083. return this.isArcType(d.data) ? [d] : [];
  11084. };
  11085. /* not used
  11086. function scatterData(d) {
  11087. return isScatterType(d) ? d.values : [];
  11088. }
  11089. */
  11090. ChartInternal.prototype.barData = function (d) {
  11091. return this.isBarType(d) ? d.values : [];
  11092. };
  11093. ChartInternal.prototype.lineOrScatterOrStanfordData = function (d) {
  11094. return this.isLineType(d) || this.isScatterType(d) || this.isStanfordType(d)
  11095. ? d.values
  11096. : [];
  11097. };
  11098. ChartInternal.prototype.barOrLineData = function (d) {
  11099. return this.isBarType(d) || this.isLineType(d) ? d.values : [];
  11100. };
  11101. ChartInternal.prototype.isSafari = function () {
  11102. var ua = window.navigator.userAgent;
  11103. return ua.indexOf('Safari') >= 0 && ua.indexOf('Chrome') < 0;
  11104. };
  11105. ChartInternal.prototype.isChrome = function () {
  11106. var ua = window.navigator.userAgent;
  11107. return ua.indexOf('Chrome') >= 0;
  11108. };
  11109. ChartInternal.prototype.initZoom = function () {
  11110. var $$ = this, d3 = $$.d3, config = $$.config, startEvent;
  11111. $$.zoom = d3
  11112. .zoom()
  11113. .on('start', function () {
  11114. if (config.zoom_type !== 'scroll') {
  11115. return;
  11116. }
  11117. var e = d3.event.sourceEvent;
  11118. if (e && e.type === 'brush') {
  11119. return;
  11120. }
  11121. startEvent = e;
  11122. config.zoom_onzoomstart.call($$.api, e);
  11123. })
  11124. .on('zoom', function () {
  11125. if (config.zoom_type !== 'scroll') {
  11126. return;
  11127. }
  11128. var e = d3.event.sourceEvent;
  11129. if (e && e.type === 'brush') {
  11130. return;
  11131. }
  11132. $$.redrawForZoom();
  11133. config.zoom_onzoom.call($$.api, $$.x.orgDomain());
  11134. })
  11135. .on('end', function () {
  11136. if (config.zoom_type !== 'scroll') {
  11137. return;
  11138. }
  11139. var e = d3.event.sourceEvent;
  11140. if (e && e.type === 'brush') {
  11141. return;
  11142. }
  11143. // if click, do nothing. otherwise, click interaction will be canceled.
  11144. if (e &&
  11145. startEvent.clientX === e.clientX &&
  11146. startEvent.clientY === e.clientY) {
  11147. return;
  11148. }
  11149. config.zoom_onzoomend.call($$.api, $$.x.orgDomain());
  11150. });
  11151. $$.zoom.updateDomain = function () {
  11152. if (d3.event && d3.event.transform) {
  11153. if (config.axis_rotated && config.zoom_type === 'scroll' && d3.event.sourceEvent.type === 'mousemove') {
  11154. // we're moving the mouse in a rotated chart with zoom = "scroll", so we need rescaleY (i.e. vertical)
  11155. $$.x.domain(d3.event.transform.rescaleY($$.subX).domain());
  11156. }
  11157. else {
  11158. $$.x.domain(d3.event.transform.rescaleX($$.subX).domain());
  11159. }
  11160. }
  11161. return this;
  11162. };
  11163. $$.zoom.updateExtent = function () {
  11164. this.scaleExtent([1, Infinity])
  11165. .translateExtent([
  11166. [0, 0],
  11167. [$$.width, $$.height]
  11168. ])
  11169. .extent([
  11170. [0, 0],
  11171. [$$.width, $$.height]
  11172. ]);
  11173. return this;
  11174. };
  11175. $$.zoom.update = function () {
  11176. return this.updateExtent().updateDomain();
  11177. };
  11178. return $$.zoom.updateExtent();
  11179. };
  11180. ChartInternal.prototype.zoomTransform = function (range) {
  11181. var $$ = this, s = [$$.x(range[0]), $$.x(range[1])];
  11182. return $$.d3.zoomIdentity.scale($$.width / (s[1] - s[0])).translate(-s[0], 0);
  11183. };
  11184. ChartInternal.prototype.initDragZoom = function () {
  11185. var $$ = this;
  11186. var d3 = $$.d3;
  11187. var config = $$.config;
  11188. var context = ($$.context = $$.svg);
  11189. var brushXPos = $$.margin.left + 20.5;
  11190. var brushYPos = $$.margin.top + 0.5;
  11191. if (!(config.zoom_type === 'drag' && config.zoom_enabled)) {
  11192. return;
  11193. }
  11194. var getZoomedDomain = function (selection) {
  11195. return selection && selection.map(function (x) { return $$.x.invert(x); });
  11196. };
  11197. var brush = ($$.dragZoomBrush = d3
  11198. .brushX()
  11199. .on('start', function () {
  11200. $$.api.unzoom();
  11201. $$.svg.select('.' + CLASS.dragZoom).classed('disabled', false);
  11202. config.zoom_onzoomstart.call($$.api, d3.event.sourceEvent);
  11203. })
  11204. .on('brush', function () {
  11205. config.zoom_onzoom.call($$.api, getZoomedDomain(d3.event.selection));
  11206. })
  11207. .on('end', function () {
  11208. if (d3.event.selection == null) {
  11209. return;
  11210. }
  11211. var zoomedDomain = getZoomedDomain(d3.event.selection);
  11212. if (!config.zoom_disableDefaultBehavior) {
  11213. $$.api.zoom(zoomedDomain);
  11214. }
  11215. $$.svg.select('.' + CLASS.dragZoom).classed('disabled', true);
  11216. config.zoom_onzoomend.call($$.api, zoomedDomain);
  11217. }));
  11218. context
  11219. .append('g')
  11220. .classed(CLASS.dragZoom, true)
  11221. .attr('clip-path', $$.clipPath)
  11222. .attr('transform', 'translate(' + brushXPos + ',' + brushYPos + ')')
  11223. .call(brush);
  11224. };
  11225. ChartInternal.prototype.getZoomDomain = function () {
  11226. var $$ = this, config = $$.config, d3 = $$.d3, min = d3.min([$$.orgXDomain[0], config.zoom_x_min]), max = d3.max([$$.orgXDomain[1], config.zoom_x_max]);
  11227. return [min, max];
  11228. };
  11229. ChartInternal.prototype.redrawForZoom = function () {
  11230. var $$ = this, d3 = $$.d3, config = $$.config, zoom = $$.zoom, x = $$.x;
  11231. if (!config.zoom_enabled) {
  11232. return;
  11233. }
  11234. if ($$.filterTargetsToShow($$.data.targets).length === 0) {
  11235. return;
  11236. }
  11237. zoom.update();
  11238. if (config.zoom_disableDefaultBehavior) {
  11239. return;
  11240. }
  11241. if ($$.isCategorized() && x.orgDomain()[0] === $$.orgXDomain[0]) {
  11242. x.domain([$$.orgXDomain[0] - 1e-10, x.orgDomain()[1]]);
  11243. }
  11244. $$.redraw({
  11245. withTransition: false,
  11246. withY: config.zoom_rescale,
  11247. withSubchart: false,
  11248. withEventRect: false,
  11249. withDimension: false
  11250. });
  11251. if (d3.event.sourceEvent && d3.event.sourceEvent.type === 'mousemove') {
  11252. $$.cancelClick = true;
  11253. }
  11254. };
  11255. return c3;
  11256. })));